void apply_lnn( circuit& circ, const circuit& base, lnn_optimization_mode operation, gate::line allocation[]) { unsigned index = 0; foreach( const gate& g, base) { if(is_toffoli(g)) { //do nothing for this gate } else { gate_details gate_d= calculate_gate_details(g, operation, allocation, base); //std::cout << gate_d.distance << std::endl; if(gate_d.control_exists) { unsigned abs_dist = abs(gate_d.distance); if(abs_dist > 0) { index+=abs_dist; adding_swap_gates(circ, gate_d , index, operation, allocation); if(operation == LNN_OPTIMIZATION_NAIVE) index+=abs_dist; //remove old gate circ.remove_gate_at(index+1); } else { if(operation == LNN_OPTIMIZATION_LOCAL_REORDER) { circ.insert_gate(index) = gate_d.mod_gate; circ.remove_gate_at(index+1); } } } index++; } } }
void copy_metadata( const truth_table<T>& spec, circuit& circ ) { circ.set_inputs( spec.inputs() ); circ.set_outputs( spec.outputs() ); circ.set_constants( spec.constants() ); circ.set_garbage( spec.garbage() ); }
bool circuit_to_truth_table( const circuit& circ, binary_truth_table& spec, const functor<bool(boost::dynamic_bitset<>&, const circuit&, const boost::dynamic_bitset<>&)>& simulation ) { // number of patterns to check depends on partial or non-partial simulation boost::dynamic_bitset<>::size_type n = ( simulation.settings() && simulation.settings()->get<bool>( "partial", false ) ) ? std::count( circ.constants().begin(), circ.constants().end(), constant() ) : circ.lines(); boost::dynamic_bitset<> input( n, 0u ); do { boost::dynamic_bitset<> output; if ( simulation( output, circ, input ) ) { binary_truth_table::cube_type in_cube, out_cube; bitset_to_vector( in_cube, input ); bitset_to_vector( out_cube, output ); spec.add_entry( in_cube, out_cube ); } else { return false; } } while ( !inc( input ).none() ); // metadata spec.set_inputs( circ.inputs() ); spec.set_outputs( circ.outputs() ); spec.set_constants( circ.constants() ); spec.set_garbage( circ.garbage() ); return true; }
command::log_opt_t log_store_entry_statistics<circuit>( const circuit& circ ) { return command::log_opt_t({ {"gates", static_cast<int>( circ.num_gates() )}, {"lines", static_cast<int>( circ.lines() )} }); }
void write_to_dimacs( const circuit& circ, const std::string& filename ) { using boost::format; using boost::str; std::vector<unsigned> line_to_var( circ.lines() ); boost::iota( line_to_var, 1u ); auto next_var = circ.lines() + 1u; std::ofstream os( filename.c_str() ); for ( const auto& g : circ ) { assert( is_toffoli( g ) ); const auto target = g.targets().front(); switch ( g.controls().size() ) { case 0u: os << format( "x%d %d 0" ) % line_to_var[target] % next_var << std::endl; line_to_var[target] = next_var++; break; case 1u: { const auto c = g.controls().front(); os << format( "x%s%d %d -%d 0" ) % ( c.polarity() ? "" : "-" ) % line_to_var[c.line()] % line_to_var[target] % next_var << std::endl; line_to_var[target] = next_var++; } break; default: { std::string all; for ( const auto& c : g.controls() ) { os << format( "%s%d -%d 0" ) % ( c.polarity() ? "" : "-" ) % line_to_var[c.line()] % next_var << std::endl; all += str( format( "%s%d " ) % ( c.polarity() ? "-" : "" ) % line_to_var[c.line()] ); } os << format( "%s%d 0" ) % all % next_var << std::endl; os << format( "x%d %d -%d 0" ) % next_var % line_to_var[target] % ( next_var + 1 ) << std::endl; line_to_var[target] = next_var + 1; next_var += 2u; } break; } } std::string ors; for ( auto i = 0u; i < circ.lines(); ++i ) { os << format( "x-%d %d %d 0" ) % ( next_var + i ) % ( i + 1 ) % line_to_var[i] << std::endl; ors += str( format( "%d " ) % ( next_var + i ) ); } os << ors << "0" << std::endl; os.close(); }
bool xorsat_equivalence_check( const circuit& circ1, const circuit& circ2, const properties::ptr& settings, const properties::ptr& statistics ) { /* settings */ const auto name_mapping = get( settings, "name_mapping", false ); const auto tmpname = get( settings, "tmpname", std::string( "/tmp/test.cnf" ) ); /* timing */ properties_timer t( statistics ); if ( circ1.lines() != circ2.lines() ) { std::cout << "[e] circuits do not have the same number of lines" << std::endl; return false; } circuit id_circ; if ( name_mapping ) { circuit circ2_copy; copy_circuit( circ2, circ2_copy ); const auto operm = derive_output_permutation( circ1.outputs(), circ2.outputs() ); //std::cout << "operm: " << any_join( operm, " " ) << std::endl; const auto idx = circ2_copy.num_gates(); for ( const auto& t : permutation_to_transpositions( operm ) ) { //std::cout << t.first << " " << t.second << std::endl; insert_cnot( circ2_copy, idx, t.first, t.second ); insert_cnot( circ2_copy, idx, t.second, t.first ); insert_cnot( circ2_copy, idx, t.first, t.second ); } id_circ = create_identity_miter( circ1, circ2_copy ); } else { id_circ = create_identity_miter( circ1, circ2 ); } write_to_dimacs( id_circ, tmpname ); return solve_identity_miter( tmpname ); }
struct gate_details calculate_gate_details(gate cur_gate, lnn_optimization_mode operation, gate::line *allocation, const circuit& base) throw (std::exception) { gate_details gate_d; gate_d.mod_gate = cur_gate; gate_d.control_exists = false; gate_d.control = 0; gate_d.target = 0; //Control_lines if(cur_gate.size() > 2) { //more than 1 control line // failed throw std::exception(); } else { for(gate::iterator line_iter = cur_gate.begin_controls(); line_iter != cur_gate.end_controls(); ++line_iter ) { //es gibt nur eine control-line gate_d.control = *line_iter; gate_d.control_exists = true; } } //target_lines for(gate::iterator line_iter = cur_gate.begin_targets(); line_iter != cur_gate.end_targets(); ++line_iter) { gate_d.target = *line_iter; } //calc distance if(gate_d.control_exists) { //if we use the heuristic lnn optimization the lines could be on a different position if(operation == LNN_OPTIMIZATION_LOCAL_REORDER) { gate_d.mod_gate.remove_target(gate_d.target); gate_d.target = lookup(gate_d.target, allocation, base.lines()); gate_d.mod_gate.add_target(gate_d.target); gate_d.mod_gate.remove_control(gate_d.control); gate_d.control = lookup(gate_d.control, allocation, base.lines()); gate_d.mod_gate.add_control(gate_d.control); } gate_d.distance = (gate_d.target - gate_d.control); gate_d.target > gate_d.control ? gate_d.distance-- : gate_d.distance++; } return gate_d; }
void adding_swap_gates(circuit& circ, struct gate_details gate_details, unsigned index, lnn_optimization_mode operation, gate::line allocation[]) { gate cur_gate = gate_details.mod_gate; gate::line target_line = gate_details.target; int distance = gate_details.distance; unsigned abs_dist = abs(distance); //swap infront for(unsigned i = 0; i< abs_dist; i++) { cur_gate.remove_target(target_line); unsigned tmptar = target_line; if(distance>0) { tmptar--; insert_swap_gate(circ, index-abs_dist+i, target_line, tmptar ); if(operation == LNN_OPTIMIZATION_LOCAL_REORDER) { gate::line tmp = allocation[target_line]; allocation[target_line] = allocation[tmptar]; allocation[tmptar] = tmp; } target_line--; } else { tmptar++; insert_swap_gate(circ, index-abs_dist+i, target_line, tmptar); if(operation == LNN_OPTIMIZATION_LOCAL_REORDER) { gate::line tmp = allocation[target_line]; allocation[target_line] = allocation[tmptar]; allocation[tmptar] = tmp; } target_line++; } cur_gate.add_target(target_line); } //now a gate with lnn distance from 0 can be added circ.insert_gate(index) = cur_gate; //swap behind if(operation == LNN_OPTIMIZATION_NAIVE) { for(unsigned i = 0; i< abs(distance); i++) { //invers to the other for loop if(distance>0 ) { insert_swap_gate(circ, index+1+i, target_line, target_line+1 ); target_line++; } else { insert_swap_gate(circ, index+1+i, target_line, target_line-1); target_line--; } } } }
void solver::solveCircuit(circuit C) { if(!C.goodCircuit()) throw "Circuit is not well formed"; getImpedance(C); getIncidence(C); getSources(C); // Need to check sources frequencies, impedace depends on it }
rcbdd store_convert<circuit, rcbdd>( const circuit& circ ) { rcbdd cf; cf.initialize_manager(); cf.create_variables( circ.lines() ); cf.set_chi( cf.create_from_circuit( circ ) ); return cf; }
void solver::getSources(circuit C) { int N = C.nComponents(); v_s = matrix<complex<double> >(N,1); i_s = matrix<complex<double> >(N,1); for(int i=0; i<N; i++) { if(C.circuit_graph.edges[i].link.type == vsource) v_s(i,0).real() = C.circuit_graph.edges[i].link.amplitude; if(C.circuit_graph.edges[i].link.type == csource) i_s(i,0).real() = C.circuit_graph.edges[i].link.amplitude; } }
void print_statistics( std::ostream& os, const circuit& circ, double runtime, const print_statistics_settings& settings ) { std::string runtime_string; if ( runtime != -1 ) { runtime_string = boost::str( boost::format( settings.runtime_template ) % runtime ); } boost::format fmt( settings.main_template ); fmt.exceptions( boost::io::all_error_bits ^ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit ) ); os << fmt % runtime_string % circ.lines() % circ.num_gates() % costs( circ, costs_by_gate_func( ncv_quantum_costs() ) ) % costs( circ, costs_by_gate_func( t_depth_costs() ) ) % costs( circ, costs_by_gate_func( t_costs() ) ) % costs( circ, costs_by_gate_func( h_costs() ) ) % costs( circ, costs_by_gate_func( transistor_costs() ) ) % costs( circ, costs_by_gate_func( sk2013_quantum_costs() ) ); }
void switch_lines(circuit& circ, const circuit& base, gate::line allocation[] ) { //reconfigure gates in base circ foreach( const gate& cg, base) { gate_details gate_d = calculate_gate_details(cg, LNN_OPTIMIZATION_GLOBAL_REORDER, 0, base); gate g = cg; //interferes the current gate the choosen line? if(gate_d.target != allocation[gate_d.target]) { g.remove_target(gate_d.target); g.add_target(allocation[gate_d.target]); } if(gate_d.control != allocation[gate_d.control]) { g.remove_control(gate_d.control); g.add_control(allocation[gate_d.control]); } circ.append_gate() = g; }
unsigned add_line_to_circuit( circuit& circ, const std::string& input, const std::string& output, const constant& c, bool g ) { std::vector<std::string> ins = circ.inputs(); std::vector<std::string> outs = circ.outputs(); std::vector<constant> cs = circ.constants(); std::vector<bool> gar = circ.garbage(); circ.set_lines( circ.lines() + 1u ); ins += input; circ.set_inputs( ins ); outs += output; circ.set_outputs( outs ); cs += c; circ.set_constants( cs ); gar += g; circ.set_garbage( gar ); return circ.lines() - 1u; }
void solver::getImpedance(circuit C) { int N = C.nComponents(); Z = matrix< complex<double> >(N,N); for(int i=0; i<N; i++) Z(i,i) = C.circuit_graph.edges[i].link.impedance; }
std::string store_entry_to_string<circuit>( const circuit& circ ) { return ( boost::format( "%d lines, %d gates" ) % circ.lines() % circ.num_gates() ).str(); }
void write_realization( const circuit& circ, std::ostream& os, const write_realization_settings& settings ) { unsigned oldsize = 0; if ( !settings.header.empty() ) { std::string header = settings.header; boost::algorithm::replace_all( header, "\n", "\n# " ); os << "# " << header << std::endl; } if ( !settings.version.empty() ) { os << ".version " << settings.version << std::endl; } os << ".numvars " << circ.lines() << std::endl; std::vector<std::string> variables( circ.lines() ); for ( unsigned i = 0u; i < circ.lines(); ++i ) { variables[i] = boost::str( boost::format( "x%d" ) % i ); } std::vector<std::string> _inputs( circ.inputs().begin(), circ.inputs().end() ); oldsize = _inputs.size(); _inputs.resize( circ.lines() ); for ( unsigned i = oldsize; i < circ.lines(); ++i ) { _inputs[i] = boost::str( boost::format( "i%d" ) % i ); } std::vector<std::string> _outputs( circ.outputs().begin(), circ.outputs().end() ); oldsize = _outputs.size(); _outputs.resize( circ.lines() ); for ( unsigned i = oldsize; i < circ.lines(); ++i ) { _outputs[i] = boost::str( boost::format( "o%d" ) % i ); } os << ".variables " << boost::algorithm::join( variables, " " ) << std::endl; namespace karma = boost::spirit::karma; namespace ascii = boost::spirit::ascii; os << ".inputs"; //std::ostream_iterator<char> outit( os ); //karma::generate_delimited( outit, *( karma::no_delimit['"' << karma::string] << '"' ), ascii::space, _inputs ); for ( const auto& _input : _inputs ) { std::string quote = ( _input.find( " " ) != std::string::npos ) ? "\"" : ""; os << boost::format( " %s%s%s" ) % quote % _input % quote; } os << std::endl; os << ".outputs"; //karma::generate_delimited( outit, *( karma::no_delimit['"' << karma::string] << '"' ), ascii::space, _outputs ); for ( const auto& _output : _outputs ) { std::string quote = ( _output.find( " " ) != std::string::npos ) ? "\"" : ""; os << boost::format( " %s%s%s" ) % quote % _output % quote; } os << std::endl; std::string _constants( circ.lines(), '-' ); std::transform( circ.constants().begin(), circ.constants().end(), _constants.begin(), constant_to_char() ); std::string _garbage( circ.lines(), '-' ); std::transform( circ.garbage().begin(), circ.garbage().end(), _garbage.begin(), garbage_to_char() ); os << ".constants " << _constants << std::endl << ".garbage " << _garbage << std::endl; for ( const auto& bus : circ.inputbuses().buses() ) { std::vector<std::string> lines; std::transform( bus.second.begin(), bus.second.end(), std::back_inserter( lines ), line_to_variable() ); os << ".inputbus " << bus.first << " " << boost::algorithm::join( lines, " " ) << std::endl; } for ( const auto& bus : circ.outputbuses().buses() ) { std::vector<std::string> lines; std::transform( bus.second.begin(), bus.second.end(), std::back_inserter( lines ), line_to_variable() ); os << ".outputbus " << bus.first << " " << boost::algorithm::join( lines, " " ) << std::endl; } for ( const auto& bus : circ.statesignals().buses() ) { std::vector<std::string> lines; std::transform( bus.second.begin(), bus.second.end(), std::back_inserter( lines ), line_to_variable() ); os << ".state " << bus.first << " " << boost::algorithm::join( lines, " " ) << std::endl; } for ( const auto& module : circ.modules() ) { os << ".module " << module.first << std::endl; write_realization_settings module_settings; module_settings.version.clear(); module_settings.header.clear(); write_realization( *module.second, os, module_settings ); } os << ".begin" << std::endl; std::string cmd; for ( const auto& g : circ ) { cmd = settings.type_label( g ); std::vector<std::string> lines; // Peres is special boost::transform( g.controls(), std::back_inserter( lines ), line_to_variable() ); boost::transform( g.targets(), std::back_inserter( lines ), line_to_variable() ); os << cmd << " " << boost::algorithm::join( lines, " " ); boost::optional<const std::map<std::string, std::string>&> annotations = circ.annotations( g ); if ( annotations ) { std::string sannotations; for ( const auto& p : *annotations ) { sannotations += boost::str( boost::format( " %s=\"%s\"" ) % p.first % p.second ); } os << " #@" << sannotations; } os << std::endl; } os << ".end" << std::endl; }
bool transposition_based_synthesis( circuit& circ, const binary_truth_table& spec, properties::ptr settings, properties::ptr statistics ) { // Settings parsing // Run-time measuring timer<properties_timer> t; if ( statistics ) { properties_timer rt( statistics ); t.start( rt ); } unsigned bw = spec.num_outputs(); circ.set_lines( bw ); copy_metadata( spec, circ ); std::map<unsigned, unsigned> values_map; for ( binary_truth_table::const_iterator it = spec.begin(); it != spec.end(); ++it ) { binary_truth_table::cube_type in( it->first.first, it->first.second ); binary_truth_table::cube_type out( it->second.first, it->second.second ); values_map.insert( std::make_pair( truth_table_cube_to_number( in ), truth_table_cube_to_number( out ) ) ); } // Set of cycles std::vector<std::vector<unsigned> > cycles; while ( !values_map.empty() ) { unsigned start_value = values_map.begin()->first; // first key in values_map std::vector<unsigned> cycle; unsigned target = start_value; do { cycle += target; unsigned old_target = target; target = values_map[target]; values_map.erase( old_target ); // erase this entry } while ( target != start_value ); cycles += cycle; } for ( auto& cycle : cycles ) { unsigned max_distance = 0u; unsigned max_index = 0u; for ( unsigned i = 0u; i < cycle.size(); ++i ) { unsigned first = cycle.at(i); unsigned second = cycle.at( (i + 1u) % cycle.size() ); unsigned distance = hamming_distance( first, second ); if ( distance > max_distance ) { max_distance = distance; max_index = i; } } std::vector<unsigned> tmp; std::copy( cycle.begin() + ( max_index + 1u ), cycle.end(), std::back_inserter( tmp ) ); std::copy( cycle.begin(), cycle.begin() + ( max_index + 1u ), std::back_inserter( tmp ) ); std::copy( tmp.begin(), tmp.end(), cycle.begin() ); std::reverse( cycle.begin(), cycle.end() ); } // TODO create transpositions function for ( auto& cycle : cycles ) { for ( unsigned i = 0u; i < cycle.size() - 1; ++i ) { circuit transposition_circ( spec.num_inputs() ); unsigned first = cycle.at(i); unsigned second = cycle.at( (i + 1) % cycle.size() ); boost::dynamic_bitset<> first_bits( spec.num_inputs(), first ); boost::dynamic_bitset<> second_bits( spec.num_inputs(), second ); transposition_to_circuit( transposition_circ, first_bits, second_bits ); append_circuit( circ, transposition_circ); } } return true; }
bool simple_simulation( boost::dynamic_bitset<>& output, const circuit& circ, const boost::dynamic_bitset<>& input, properties::ptr settings, properties::ptr statistics ) { return simple_simulation( output, circ.begin(), circ.end(), input, settings, statistics ); }
void reverse_circuit( circuit& circ ) { std::reverse( circ.begin(), circ.end() ); }
bool create_simulation_pattern( const pattern& p, const circuit& circ, std::vector<boost::dynamic_bitset<> >& sim, std::map<std::string, boost::dynamic_bitset<> >& init, std::string* error ) { // Initialzustand speichern const bus_collection::map& circStates = circ.statesignals().buses(); for ( const auto& pa : p.initializers() ) { // is there a bus, we need it for the bitwidth bus_collection::map::const_iterator stateIt = circStates.find( pa.first ); if ( stateIt != circStates.end() ) { int busSize = stateIt->second.size(); boost::dynamic_bitset<> initBits( busSize, pa.second ); init.insert( std::make_pair( pa.first, initBits ) ); } } // Set init value to 0 for all remaining state signals for ( const auto& pa : circStates ) { const std::string& statesignal = pa.first; std::map<std::string, boost::dynamic_bitset<> >::const_iterator stateIt = init.find( statesignal ); if ( stateIt == init.end() ) { init.insert( std::make_pair( statesignal, boost::dynamic_bitset<>( pa.second.size() ) ) ); } } std::map<std::string, std::vector<unsigned> > varPlace; std::map<std::string, std::vector<unsigned> > varPlaceIC; std::list<unsigned> usedLines; unsigned numBits = 0; std::vector<std::string> vars; for ( const auto& input_name : p.inputs() ) { // Search in input busses bus_collection::map::const_iterator busIt = circ.inputbuses().buses().find( input_name ); if( busIt != circ.inputbuses().buses().end() ) { const std::vector<unsigned>& busLines = busIt->second; varPlaceIC[input_name] = busLines; for ( unsigned line : busLines ) { usedLines += line; ++numBits; } vars += input_name; } // Search in regular inputs else { std::vector<std::string>::const_iterator itOtherInput = std::find( circ.inputs().begin(), circ.inputs().end(), input_name ); if ( itOtherInput != circ.inputs().end() ) { unsigned line = std::distance( circ.inputs().begin(), itOtherInput ); varPlaceIC[input_name] = std::vector<unsigned>( 1, line ); usedLines.push_back( line ); ++numBits; vars.push_back( input_name ); } // ignore if not found } } // check for multiple defined inputs usedLines.sort(); std::list<unsigned> ul = usedLines; usedLines.unique(); if ( usedLines.size() < ul.size() ) { if( error ) { *error = "At least one primary input is specified multiple times in .inputs."; } return false; } // check, whether all primary inputs are covered and nothing else std::list<unsigned> primaryInputs; boost::push_back( primaryInputs, boost::irange( 0u, circ.lines() ) ); // remove constant lines for ( std::vector<constant>::const_iterator it = circ.constants().begin(); it != circ.constants().end(); ++it ) { if ( *it ) { primaryInputs.remove( std::distance( circ.constants().begin(), it ) ); } } // remove statesignals for ( const auto& pa : circStates ) { for ( unsigned line : pa.second ) { primaryInputs.remove( line ); } } // check if ( primaryInputs != usedLines ) { if ( error ) { *error = "Specified inputs don't match primary inputs of the circuit."; } return false; } for ( const auto& varName : vars ) { std::vector<unsigned> vp; for ( unsigned line : varPlaceIC[varName] ) { vp += std::distance( usedLines.begin(), boost::find( usedLines, line ) ); } varPlace.insert( std::make_pair( varName, vp ) ); } for ( pattern::pattern_vec::const_iterator step = p.patterns().begin(); step != p.patterns().end(); ++step ) { boost::dynamic_bitset<> stepBits(numBits); for( std::vector<unsigned>::const_iterator it2 = step->begin(); it2 != step->end(); ++it2 ) { unsigned input = *it2; const std::vector<unsigned>& lines = varPlace[vars.at( std::distance( step->begin(), it2 ) )]; if ( input >= ( 1u << lines.size() ) ) { if ( error ) { *error = boost::str( boost::format( "In step %d: Input %s has not enough bits to represent the given value." ) % ( std::distance( p.patterns().begin(), step ) + 1u ) % vars.at( std::distance( step->begin(), it2 ) ) ); } return false; } boost::dynamic_bitset<> inputVal( lines.size(), input ); unsigned j = 0u; for ( unsigned line : lines ) { stepBits[line] = inputVal[j++]; } } sim += stepBits; } return true; }