Ejemplo n.º 1
0
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++;
        }
    }
}
Ejemplo n.º 2
0
 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() );
 }
Ejemplo n.º 3
0
  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;
  }
Ejemplo n.º 4
0
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() )}
    });
}
Ejemplo n.º 5
0
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();
}
Ejemplo n.º 6
0
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 );
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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--;
            }
        }
    }
}
Ejemplo n.º 9
0
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
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
    }
}
Ejemplo n.º 12
0
  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() ) );
  }
Ejemplo n.º 13
0
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;
    }
Ejemplo n.º 14
0
  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;
  }
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
std::string store_entry_to_string<circuit>( const circuit& circ )
{
  return ( boost::format( "%d lines, %d gates" ) % circ.lines() % circ.num_gates() ).str();
}
Ejemplo n.º 17
0
  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;
  }
Ejemplo n.º 19
0
 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 );
 }
Ejemplo n.º 20
0
 void reverse_circuit( circuit& circ )
 {
   std::reverse( circ.begin(), circ.end() );
 }
Ejemplo n.º 21
0
  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;
  }