Raw File
circuit.hpp
/* RevKit: A Toolkit for Reversible Circuit Design (www.revkit.org)
 * Copyright (C) 2009-2011  The RevKit Developers <revkit@informatik.uni-bremen.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file circuit.hpp
 *
 * @brief Circuit class
 */

#ifndef CIRCUIT_HPP
#define CIRCUIT_HPP

#include <map>

/**
 * For a more convenient use in foreach loops.
 * You can use the name foreach instead of BOOST_FOREACH.
 *
 * @author RevKit
 * @since  1.0
 */
#define foreach BOOST_FOREACH

#include <boost/foreach.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signal.hpp>
#include <boost/variant.hpp>

#include <core/gate.hpp>
#include <core/meta/bus_collection.hpp>




namespace revkit
{


  /**
   * @brief Type for determine whether line is constant or not
   *
   * The following table summarizes the use of constant values
   * in circuit representations.
   *
   * <table border="0">
   *   <tr>
   *     <td class="indexkey">Description</td>
   *     <td class="indexkey">Char representation</td>
   *     <td class="indexkey">Typed value</td>
   *   </tr>
   *   <tr>
   *     <td class="indexvalue">No constant input line</td>
   *     <td align="center" class="indexvalue">'-'</td>
   *     <td class="indexvalue">@code constant() @endcode</td>
   *   </tr>
   *   <tr>
   *     <td class="indexvalue">Constant input line with value 0</td>
   *     <td align="center" class="indexvalue">'0'</td>
   *     <td class="indexvalue">@code constant( 0 ) @endcode</td>
   *   </tr>
   *   <tr>
   *     <td class="indexvalue">Constant input line with value 1</td>
   *     <td align="center" class="indexvalue">'1'</td>
   *     <td class="indexvalue">@code constant( 1 ) @endcode</td>
   *   </tr>
   * </table>
   *
   * @section Example
   * This example demonstrates how to access the constant values.
   * @code
   * constant c = // some constant
   *
   * if ( c ) // checks whether c is set or not
   * {
   *   if ( *c ) // c is checked, checks the value of c
   *   {
   *     std::cout << "constant value 1" << std::endl;
   *   }
   *   else
   *   {
   *     std::cout << "constant value 0" << std::endl;
   *   }
   * }
   * else
   * {
   *   std::cout << "no constant value" << std::endl;
   * }
   * @endcode
   *
   * @author RevKit
   * @since  1.0
   */
  typedef boost::optional<bool> constant;

  /**
   * @brief Represents a circuit
   *
   * A circuit is represented by a list of gates (type gate::vector)
   * and meta information like name, inputs, outputs, constants,
   * and garbage.
   *
   * Via STL like iterators the gates can be accessed and also used
   * in STL and STL like algorithms based on the iterator concept.
   *
   * @section example_circuit_class_1 Example: Creating a circuit with 5 lines
   * @code
   * #include <core/circuit.hpp>
   *
   * ...
   *
   * circuit circ( 5 );
   * @endcode
   *
   * @section example_circuit_class_2 Example: Iterate through all gates in a circuit \p circ with iterators
   * @code
   * for ( circuit::const_iterator itGate = circ.begin(); itGate != circ.end(); ++itGate )
   * {
   *   gate& g = *itGate;
   * }
   * @endcode
   *
   * @section example_circuit_class_3 Example: Iterator through all gates in a circuit with foreach
   * @code
   * #include <boost/foreach.hpp>
   * #define foreach BOOST_FOREACH
   *
   * ...
   *
   * foreach ( gate& g, circ )
   * {
   *   // g can be modified
   * } 
   *
   * foreach ( const gate& g, circ )
   * {
   *   // g cannot be modified
   * } 
   * @endcode
   *
   * @author RevKit
   * @since  1.0
   */
  class standard_circuit
  {
  public:
    /**
     * @brief Default Constructor
     *
     * Creates an empty circuit with zero lines.
     *
     * @author RevKit
     * @since  1.0
     */
    standard_circuit() : lines( 0 ) {}

    /**
     * @brief Default Constructor
     *
     * Creates an empty circuit with \p lines lines.
     *
     * @param lines Number of lines
     *
     * @author RevKit
     * @since  1.0
     */
    standard_circuit( unsigned lines ) : lines( lines )
    {
      inputs.resize( lines, "i" );
      outputs.resize( lines, "o" );
      constants.resize( lines, constant() );
      garbage.resize( lines, false );
    }

    /** @cond */
    std::vector<boost::shared_ptr<gate> > gates;
    unsigned lines;

    std::vector<std::string> inputs;
    std::vector<std::string> outputs;
    std::vector<constant> constants;
    std::vector<bool> garbage;

    std::string name;
    bus_collection inputbuses;
    bus_collection outputbuses;
    bus_collection statesignals;
    std::map<const gate*, std::map<std::string, std::string> > annotations;
    /** @endcond */
  };

  class subcircuit;

  /**
   * @brief Generic circuit
   *
   * This circuit can be both standard_circuit or a subcircuit.
   * In the default case it is considered as standard_circuit with
   * no lines.
   *
   * In the following examples are given how to construct different
   * types of circuits.
   *
   * <b>Empty circuit with no lines</b>
   * @code circuit circ; @endcode
   *
   * <b>Empty circuit with 3 lines</b>
   * @code circuit circ( 3 ); @endcode
   *
   * <b>Sub-circuit from \p circ including gates [2,4)</b>
   * @code subcircuit subcirc( circ, 2, 4 ); @endcode
   *
   * @author RevKit
   * @since  1.0
   */
  typedef boost::variant<standard_circuit, subcircuit> circuit_variant;

  /**
   * @brief Represents a sub-circuit
   *
   * A sub-circuit is a <i>window</i> which can be set
   * on top of a standard_circuit. All methods are
   * specialized for the sub-circuit. But the gates are
   * references to the underlying circuit.
   */
  class subcircuit
  {
  public:
    /**
     * @brief Default constructor
     *
     * This constructor creates a sub-circuit from a
     * base which is a standard_circuit and a range of gates
     * [\p from, \p to). Thus, the gate with index \p to is
     * not included.
     *
     * @param base Underlying circuit
     * @param from First gate to be included (starting from 0)
     * @param to First gate to be not included anymore
     *
     * @author RevKit
     * @since  1.0
     */
    subcircuit( standard_circuit& base, unsigned from, unsigned to ) : base( base ), from( from ), to( to ) {}

    /**
     * @brief Default constructor
     *
     * Same as other constructor but takes a generic circuit,
     * which will get casted to a standard_circuit.
     *
     * @param base Underlying circuit (has to be standard_circuit in the variant)
     * @param from First gate to be included (starting from 0)
     * @param to First gate to be not included anymore
     *
     * @author RevKit
     * @since  1.0
     */
    subcircuit( circuit_variant& base, unsigned from, unsigned to ) : base( boost::get<standard_circuit>( base ) ), from( from ), to( to ) {}

    /**
     * @brief Default constructor
     *
     * Same as other constructor but takes a generic circuit,
     * which will get casted to a standard_circuit.
     *
     * @param base Underlying circuit (has to be standard_circuit in the variant)
     * @param from First gate to be included (starting from 0)
     * @param to First gate to be not included anymore
     *
     * @author RevKit
     * @since  1.0
     */
    subcircuit( const circuit_variant& base, unsigned from, unsigned to ) : base( boost::get<standard_circuit>( const_cast<circuit_variant&>( base ) ) ), from( from ), to( to ) {}

    /**
     * @brief Constructor with line filter
     *
     * This constructor creates a sub-circuit from a
     * base which is a standard_circuit and a range of gates
     * [\p from, \p to). Thus, the gate with index \p to is
     * not included.
     *
     * Further a line filter is specified. The vector contains all
     * line indices (starting from 0) which should be accessible.
     *
     * @param base Underlying circuit
     * @param from First gate to be included (starting from 0)
     * @param to First gate to be not included anymore
     * @param filter Line filter
     *
     * @author RevKit
     * @since  1.0
     */
    subcircuit( standard_circuit& base, unsigned from, unsigned to, std::vector<unsigned> filter ) : base( base ), from( from ), to( to ), filter( filter )
    {
      std::sort( this->filter.begin(), this->filter.end() );
      this->filter.resize( std::unique( this->filter.begin(), this->filter.end() ) - this->filter.begin() );
    }

    /**
     * @brief Constructor with line filter
     *
     * Same as other constructor but takes a generic circuit,
     * which will get casted to a standard_circuit.
     *
     * @param base Underlying circuit (has to be a standard_circuit in the variant)
     * @param from First gate to be included (starting from 0)
     * @param to First gate to be not included anymore
     * @param filter Line filter
     *
     * @author RevKit
     * @since  1.0
     */
    subcircuit( const circuit_variant& base, unsigned from, unsigned to, std::vector<unsigned> filter ) : base( boost::get<standard_circuit>( const_cast<circuit_variant&>( base ) ) ), from( from ), to( to ), filter( filter )
    {
      std::sort( this->filter.begin(), this->filter.end() );
      this->filter.resize( std::unique( this->filter.begin(), this->filter.end() ) - this->filter.begin() );
    }

    /**
     * @brief Deconstructor
     *
     * Deletes all filtered_gate objects in the filter cache
     *
     * @author RevKit
     * @since  1.0
     */
    ~subcircuit()
    {
      std::map<gate*, filtered_gate*>::const_iterator it;
      for ( it = filter_cache.begin(); it != filter_cache.end(); ++it )
      {
        delete it->second;
      }
    }

    /** @cond */
    standard_circuit& base;
    unsigned from;
    unsigned to;
    std::vector<unsigned> filter;
    
    // for the transform_iterator implementation
    std::map<gate*, filtered_gate*> filter_cache;
    /** @endcond */
  };

  /** @cond */
  struct filter_circuit
  {
    typedef gate& result_type;

    filter_circuit() : circ( 0 ) {}
    explicit filter_circuit( subcircuit& circ ) : circ( &circ ) {}

    gate& operator()( gate& g ) const
    {
      if ( !circ )
      {
        return g;
      }
      else
      {
        if ( circ->filter_cache.find( &g ) == circ->filter_cache.end() )
        {
          circ->filter_cache[&g] = new filtered_gate( g, circ->filter );
        }
        return *circ->filter_cache.find( &g )->second;
      }
    }

  private:
    subcircuit* circ;
  };
  /** @endcond */

  /** @cond */
  struct const_filter_circuit
  {
    typedef const gate& result_type;

    const_filter_circuit() : circ( 0 ) {}
    explicit const_filter_circuit( const subcircuit& circ ) : circ( &circ ) {}

    const gate& operator()( const gate& g ) const
    {
      if ( !circ )
      {
        return g;
      }
      else
      {
        // NOTE Works, but avoiding the const_cast would be better
        if ( circ->filter_cache.find( const_cast<gate*>( &g ) ) == circ->filter_cache.end() )
        {
          const_cast<subcircuit*>( circ )->filter_cache[const_cast<gate*>( &g )] = new filtered_gate( const_cast<gate&>( g ), const_cast<subcircuit*>( circ )->filter );
        }
        return *circ->filter_cache.find( const_cast<gate*>( &g ) )->second;
      }
    }

  private:
    const subcircuit* circ;
  };
  /** @endcond */

  /**
   * @brief Main circuit class
   *
   * This class represents a circuit and can be used generically for standard circuits and sub circuits.
   *
   * @author RevKit
   * @since  1.0
   */
  class circuit {
  public:
    /**
     * @brief Default constructor
     *
     * This constructor initializes a standard_circuit with 0 lines, also called an empty circuit.
     * Empty circuits are usually used as parameters for parsing functions, optimization algorithms, etc.
     *
     * @author RevKit
     * @since  1.0
     */
    circuit() {}
    std::map<unsigned, std::string> lines_to_inputs;
    std::vector<std::string> workers;
    std::vector<std::string> anc_zz;
    std::vector<std::string> anc_zg;
    std::vector<std::string> anc_11;
    std::vector<std::string> anc_1g;

    /**
     * @brief Cast Constructor for a standard_circuit
     *
     * With this constructor the standard_circuit constructor is automatically converted to 
     * a circuit, e.g. by calling
     *
     * @code
     * circuit circ( 3 );
     * @endcode
     *
     * a circuit with 3 lines is created.
     *
     * @param std_circ standard_circuit implementation
     *
     * @author RevKit
     * @since  1.0
     */
    circuit( const standard_circuit& std_circ ) : circ( std_circ ) {}

/**
     * @brief Cast Constructor for a standard_circuit
     *
     * With this constructor the standard_circuit constructor is automatically converted to 
     * a circuit, e.g. by calling
     *
     * @code
     * circuit circ( 3 );
     * @endcode
     *
     * a circuit with 3 lines is created.
     *
     * @param std_circ standard_circuit implementation
     *
     * @author RevKit
     * @since  1.0
     */
    circuit( standard_circuit& std_circ ) : circ( std_circ ) {}
    
    /**
     * @brief Cast Constructor for a subcircuit
     *
     * This constructor is used, so that subcircuits are detected as circuits in
     * algorithms and can passed as circuit parameter to other functions and
     * algorithms.
     *
     * @param sub_circ subcircuit implementation
     *
     * @author RevKit
     * @since  1.0
     */
    circuit( const subcircuit& sub_circ ) : circ( sub_circ ) {}
    
    /**
     * @brief Cast Constructor for a subcircuit
     *
     * This constructor is used, so that subcircuits are detected as circuits in
     * algorithms and can passed as circuit parameter to other functions and
     * algorithms.
     *
     * @param sub_circ subcircuit implementation
     *
     * @author RevKit
     * @since  1.0
     */
    circuit( subcircuit& sub_circ ) : circ( sub_circ ) {}

    /**
     * @brief Copy Constructor
     *
     * This constructor is used by some algorithms, but should not be used directly.
     *
     * It copies the underlying circuit, but it does not
     * copy the signals, so that this information gets lost.
     *
     * @param other Circuit to be copied
     *
     * @author RevKit
     * @since  1.0
     */
    circuit( const circuit& other ) : circ( other.circ ) {}

    /**
     * @brief Mutable iterator for accessing the gates in a circuit
     */
    typedef boost::transform_iterator<filter_circuit, boost::indirect_iterator<std::vector<boost::shared_ptr<gate> >::iterator> > iterator;

    /**
     * @brief Constant iterator for accessing the gates in a circuit
     */
    typedef boost::transform_iterator<const_filter_circuit, boost::indirect_iterator<std::vector<boost::shared_ptr<gate> >::const_iterator> > const_iterator;

    /**
     * @brief Mutable reverse iterator for accessing the gates in a circuit
     */
    typedef boost::transform_iterator<filter_circuit, boost::indirect_iterator<std::vector<boost::shared_ptr<gate> >::reverse_iterator> > reverse_iterator;
    /**
     * @brief Constant reverse iterator for accessing the gates in a circuit
     */
    typedef boost::transform_iterator<const_filter_circuit, boost::indirect_iterator<std::vector<boost::shared_ptr<gate> >::const_reverse_iterator> > const_reverse_iterator;

    /**
     * @brief Returns the number of gates
     *
     * This method returns the number of gates in the circuit.
     * 
     * @return Number of gates
     *
     * @author RevKit
     * @since  1.0
     */
    unsigned num_gates() const;

    /**
     * @brief Sets the number of line
     *
     * This method sets the number of lines of the circuit.
     *
     * Changing this number will not affect the data in the gates.
     * For example: If there is a gate with a control on line 3,
     * and the number of lines is reduced to 2 in the circuit, then
     * the control is still on line 3 but not visible in this circuit.
     *
     * So, changing the lines after already adding gates can lead
     * to invalid gates.
     *
     * @param lines Number of lines
     *
     * @author RevKit
     * @since  1.0
     */
    void set_lines( unsigned lines );

    /**
     * @brief Returns the number of lines
     *
     * This method returns the number of lines.
     *
     * @return Number of lines
     *
     * @author RevKit
     * @since  1.0
     */
    unsigned lines() const;

    /**
     * @brief Constant begin iterator pointing to gates
     *
     * @return Constant begin iterator
     *
     * @author RevKit
     * @since  1.0
     */
    const_iterator begin() const;
    
    /**
     * @brief Constant end iterator pointing to gates
     *
     * @return Constant end iterator
     *
     * @author RevKit
     * @since  1.0
     */
    const_iterator end() const;
    
    /**
     * @brief Mutable begin iterator pointing to gates
     *
     * @return Mutable begin iterator
     *
     * @author RevKit
     * @since  1.0
     */
    iterator begin();
    
    /**
     * @brief Mutable end iterator pointing to gates
     *
     * @return Mutable end iterator
     *
     * @author RevKit
     * @since  1.0
     */
    iterator end();

    /**
     * @brief Constant begin reverse iterator pointing to gates
     *
     * @return Constant begin reverse iterator
     *
     * @author RevKit
     * @since  1.0
     */
    const_reverse_iterator rbegin() const;
    
    /**
     * @brief Constant end reverse iterator pointing to gates
     *
     * @return Constant end reverse iterator
     *
     * @author RevKit
     * @since  1.0
     */
    const_reverse_iterator rend() const;
    
    /**
     * @brief Mutable begin reverse iterator pointing to gates
     *
     * @return Mutable begin reverse iterator
     *
     * @author RevKit
     * @since  1.0
     */
    reverse_iterator rbegin();
    
    /**
     * @brief Mutable end reverse iterator pointing to gates
     *
     * @return Mutable end reverse iterator
     *
     * @author RevKit
     * @since  1.0
     */
    reverse_iterator rend();

    /**
     * @brief Random access operator for access to gates by index
     *
     * @param index Index of the gate, starting from 0
     * @return constant access to the \p index gate in the circuit
     *
     * @author RevKit
     * @since  1.1
     */
    const gate& operator[]( unsigned index ) const;

    /**
     * @brief Random access operator for access to gates by index
     *
     * @param index Index of the gate, starting from 0
     * @return mutable access to the \p index gate in the circuit
     *
     * @author RevKit
     * @since  1.1
     */
    gate& operator[]( unsigned index );

    /**
     * @brief Inserts a gate at the end of the circuit
     *
     * This method inserts a gate at the end of the circuit.
     *
     * @return Reference to the newly created empty gate
     *
     * @author RevKit
     * @since  1.0
     */
    gate& append_gate();
    
    /**
     * @brief Inserts a gate at the beginning of the circuit
     *
     * This method inserts a gate at the beginning of the circuit.
     *
     * @return Reference to the newly created empty gate
     *
     * @author RevKit
     * @since  1.0
     */
    gate& prepend_gate();
    
    /**
     * @brief Inserts a gate into the circuit
     *
     * This method inserts a gate at an arbitrary position in the circuit
     *
     * @param pos  Position where to insert the gate
     *
     * @return Reference to the newly created empty gate
     *
     * @author RevKit
     * @since  1.0
     */
    gate& insert_gate( unsigned pos );

    /**
     * @brief Removes a gate at a given index
     *
     * If the index is not valid, no gate is removed.
     *
     * @param pos  Index
     *
     * @author RevKit
     * @since  1.0
     */
    void remove_gate_at( unsigned pos );


    /**
    * @brief Allows integration of bitvectors into circuit signals
    *
    * 
    * @param inputs input name
    * @author Adam Holmes
    * @since 1.3
    */
    
    void initialize_inputs( int* input );
    void remove_input( int* input );
    void remove_worker( int* input );
    void initialize_worker( int* id, std::string* name  ); 
    void initialize_ancilla( int* id, std::string* input, int classifier );
    void print_signal( std::string* name, int flag );





    /**
     * @brief Sets the input names of the lines in a circuit
     *
     * This method sets the input names of the lines in a circuit.
     * This is useful for functions when writing them to a file,
     * printing them, or creating images.
     *
     * @param inputs Input names
     *
     * @author RevKit
     * @since  1.0
     */
    void set_inputs( const std::vector<std::string>& inputs );
//    void set_workers( const std::vector<std::string>& inputs );
//    void set_ancilla_zg( const std::vector<std::string>& inputs );
//    void set_ancilla_zz( const std::vector<std::string>& inputs );
//    void set_ancilla_1g( const std::vector<std::string>& inputs );
//    void set_ancilla_11( const std::vector<std::string>& inputs );


    /* 
    * @brief Adds new garbage signals to the circuit
    *
    * This method creates ancilla signals by declaring them as garbage signals.
    * 
    *
    
    void zero_to_garbage( std::vector<int>& inputs );
    void one_to_garbage( std::vector<int>& inputs );
    void zero_to_zero( std::vector<int>& inputs );
    void one_to_one( std::vector<int>& inputs );
    */



    
    /**
     * @brief Returns the input names of the lines in a circuit
     *
     * This method returns the input names of the lines in a circuit.
     * This is useful for functions when writing them to a file,
     * printing them, or creating images.
     *
     * @return Input names
     *
     * @author RevKit
     * @since  1.0
     */
    const std::vector<std::string>& inputs() const;
//    const std::vector<std::string>& get_workers() const;
//    const std::vector<std::string>& anc_zg() const;
//    const std::vector<std::string>& anc_zz() const;
//    const std::vector<std::string>& anc_1g() const;
//    const std::vector<std::string>& anc_11() const;
    
    /**
     * @brief Sets the output names of the lines in a circuit
     *
     * This method sets the output names of the lines in a circuit.
     * This is useful for functions when writing them to a file,
     * printing them, or creating images.
     *
     * @param outputs Output names
     *
     * @author RevKit
     * @since  1.0
     */
    void set_outputs( const std::vector<std::string>& outputs );
    
    /**
     * @brief Returns the output names of the lines in a circuit
     *
     * This method returns the output names of the lines in a circuit.
     * This is useful for functions when writing them to a file,
     * printing them, or creating images.
     *
     * @return Output names
     *
     * @author RevKit
     * @since  1.0
     */
    const std::vector<std::string>& outputs() const;
    
    /**
     * @brief Sets the constant input line specifications
     *
     * This method sets the constant input line specification.
     *
     * Lines are by default not constant. If less values are given
     * than lines exist, the last ones will be not constant. If more
     * values are given than lines exist, they will be truncated.
     *
     * @sa constant
     *
     * @param constants Constant Lines
     *
     * @author RevKit
     * @since  1.0
     */
    void set_constants( const std::vector<constant>& constants );
    
    /**
     * @brief Returns the constant input line specification
     *
     * This method returns the constant input line specification.
     *
     * @return Constant input line specification
     *
     * @author RevKit
     * @since  1.0
     */
    const std::vector<constant>& constants() const;
    
    /**
     * @brief Sets whether outputs are garbage or not
     *
     * If an output is garbage it means, that the resulting
     * output value is not necessary for the function.
     *
     * Lines are by default not garbage. If less values are given
     * than lines exist, the last ones will be not garbage. If more
     * values are given than lines exist, they will be truncated.
     *
     * @param garbage Garbage line specification
     *
     * @author RevKit
     * @since  1.0
     */
    void set_garbage( const std::vector<bool>& garbage );
    
    /**
     * @brief Returns whether outputs are garbage or not
     *
     * This method returns the garbage line specification.
     *
     * @return Garbage output line specification
     *
     * @author RevKit
     * @since  1.0
     */
    const std::vector<bool>& garbage() const;
    
    /**
     * @brief Sets a name of the circuit
     *
     * Sets a name for the circuit which is empty
     * initially.
     *
     * @param name Name
     *
     * @author RevKit
     * @since  1.0
     */
    void set_circuit_name( const std::string& name );
    
    /**
     * @brief Returns the name of the circuit
     *
     * Returns the name of the circuit which is empty
     * initially.
     *
     * @return Name of the circuit
     *
     * @author RevKit
     * @since  1.0
     */
    const std::string& circuit_name() const;

    /** 
     * @brief Constant access to the input buses
     * 
     * This method gives constant access to the input
     * buses.
     * 
     * @return Input bus collection
     *
     * @author RevKit
     * @since  1.1
     */
    const bus_collection& inputbuses() const;

    /** 
     * @brief Mutable access to the input buses
     * 
     * This method gives mutable access to the input
     * buses.
     * 
     * @return Input bus collection
     *
     * @author RevKit
     * @since  1.1
     */
    bus_collection& inputbuses();

    /** 
     * @brief Constant access to the output buses
     * 
     * This method gives constant access to the output
     * buses.
     * 
     * @return Output bus collection
     *
     * @author RevKit
     * @since  1.1
     */
    const bus_collection& outputbuses() const;

    /** 
     * @brief Mutable access to the output buses
     * 
     * This method gives mutable access to the output
     * buses.
     * 
     * @return Output bus collection
     *
     * @author RevKit
     * @since  1.1
     */
    bus_collection& outputbuses();

    /** 
     * @brief Constant access to the state signals
     * 
     * This method gives constant access to the state
     * signals.
     * 
     * @return State signal collection
     *
     * @author RevKit
     * @since  1.1
     */
    const bus_collection& statesignals() const;

    /** 
     * @brief Mutable access to the state signals
     * 
     * This method gives mutable access to the state
     * signals.
     * 
     * @return State signal collection
     *
     * @author RevKit
     * @since  1.1
     */
    bus_collection& statesignals();

    /**
     * @brief Returns whether the circuit is a sub-circuit or not
     *
     * Both standard_circuit and subcircuit are used in the context as a circuit
     * in other algorithms. To determine what kind of circuit it is, this method
     * returns \p true if the circuit is a sub-circuit, \p false otherwise.
     *
     * @return true, if circuit is a sub-circuit, \p false otherwise
     *
     * @author RevKit
     * @since  1.0
     */
    bool is_subcircuit() const;

    /**
     * @brief Returns the filter of a sub-circuit
     *
     * This method returns a pair <i>(l, f)</i>.
     * In case the circuit is sub-circuit restricted on the lines,
     * \em l is the original number of lines of the base circuit
     * and \em f is the filter, i.e. a vector of lines which are
     * used for the sub-circuit. In other cases \em s is always 0
     * and \em f is empty.
     *
     * @return Pair of information about the sub-circuit's base or \em empty pair
     *
     * @author RevKit
     * @since  1.0
     */
    std::pair<unsigned, std::vector<unsigned> > filter() const;

    /**
     * @brief Returns the offset of the circuit (sub-circuit)
     *
     * For a standard_circuit, the offset is always 0, but for a
     * sub-circuit, the offset is the index of the starting gate
     * in respect to its base circuit.
     *
     * @return Offset of the circuit
     *
     * @author RevKit
     * @since  1.0
     */
    unsigned offset() const;

    /**
     * @brief Adds a module to the circuit
     *
     * This function adds a module to the circuit. It does
     * not create a gate calling the module, but the module
     * itself as a reference for further use, e.g. with append_module.
     *
     * This method uses smart pointer to a circuit wich already
     * exists and is managed by another object. If it cannot
     * be assured that the module is saved, the method
     * add_module(const std::string&, const circuit&) should be used.
     *
     * @param name Name of the module
     * @param module Reference to an existing module
     *
     * @author RevKit
     * @since  1.1
     */
    void add_module( const std::string& name, const boost::shared_ptr<circuit>& module );
    
    /** 
     * @brief Adds a module to the circuit
     *
     * This function adds a module to the circuit. It does
     * not create a gate calling the module, but the module
     * itself as a reference for further use, e.g. with append_module.
     *
     * In this method the module is copied first and thus assured
     * that is managed by this circuit.
     * 
     * @param name Name of the module
     * @param module Module to be copied
     *
     * @author RevKit
     * @since  1.1
     */
    void add_module( const std::string& name, const circuit& module );
    
    /** 
     * @brief Returns all modules in the circuit
     * 
     * This method returns a map of all modules, whereby the
     * keys are the names of the modules.
     * 
     * @return Map of modules
     *
     * @author RevKit
     * @since  1.1
     */
    const std::map<std::string, boost::shared_ptr<circuit> >& modules() const;

    /** 
     * @brief Returns the annotation for one gate and one key
     *
     * This method returns the value for one particular annotation for
     * a given gate. If no annotation with that key exists, the a default
     * value is given. 
     *
     * @param g Gate
     * @param key Key of the annotation
     * @param default_value Default value, in case the key does not exist
     * 
     * @return Value of the annotation or the default value
     *
     * @author RevKit
     * @since  1.1
     */
    const std::string& annotation( const gate& g, const std::string& key, const std::string& default_value = std::string() ) const;

    /** 
     * @brief Returns all annotations for a given gate
     *
     * This method returns all annotations for a given gate. For the
     * purpose of efficiency, this method returns an optional data type
     * containing the property map. So, first check whether there are
     * items by assierting the optional, and then go through the map
     * by dereferencing the optional:
     * @code
     * boost::optional<const std::map<std::string, std::string>& > annotations = circ.annotations( g );
     *
     * if ( annotations )
     * {
     *   // annotations exists
     *   typedef std::pair<std::string, std::string> pair_t;
     *   foreach ( const pair_t& p, *annotations )
     *   {
     *     const std::string& key = p.first;
     *     const std::string& value = p.second;
     *     // do something with key and value
     *   }
     * }
     * @endcode
     * 
     * @param g Gate
     * 
     * @return Map of annotations encapsulated in an optional
     *
     * @author RevKit
     * @since  1.1
     */
    boost::optional<const std::map<std::string, std::string>& > annotations( const gate& g ) const;

    /** 
     * @brief Annotates a gate
     * 
     * With this method a gate can be annotated using a key and a value.
     * If there is an annotation with the same key, it will be overwritten.
     *
     * @param g Gate
     * @param key Key of the annotation
     * @param value Value of the annotation
     *
     * @author RevKit
     * @since  1.1
     */
    void annotate( const gate& g, const std::string& key, const std::string& value );

    // SIGNALS
    /**
     * @brief Signal which is emitted after adding a gate
     *
     * The gate is always empty, since when adding a gate to the
     * circuit an empty gate is returned as reference and then
     * further processed by functions such as append_toffoli.
     */
    boost::signal<void(gate&)> gate_added;

    /** @cond */
    operator circuit_variant&()
    {
      return circ;
    }

    operator const circuit_variant&() const
    {
      return circ;
    }
    /** @endcond */
  private:
    /** @cond */
    circuit_variant circ;
    std::map<std::string, boost::shared_ptr<circuit> > _modules;
    /** @endcond */
  };


  extern circuit global_circuit;
  extern bool LLVM_IR;
  extern int registerCount;

  class qint{
    public:
        static circuit circ;
        std::vector<qint*> reg;
        std::string name;
    	int id;
        qint();
        qint(int num);
    	qint operator[] (const int index);
  };

  class qbit : public qint{
    public:
        qbit();
        qbit(bool flag);
        qbit(int num);
        qbit(int length, int width);
  };

  class zero_to_garbage : public qint{
    public:
    	zero_to_garbage();
    	zero_to_garbage(int num);
    	zero_to_garbage(int length, int width);
  };

  class zero_to_zero : public qint{
    public:
        zero_to_zero();
        zero_to_zero(int num);
        zero_to_zero(int length, int width);
  };

  class one_to_garbage : public qint{
    public:
        one_to_garbage();
        one_to_garbage(int num);
        one_to_garbage(int length, int width);
  };


  class one_to_one : public qint{
    public:
        one_to_one();
        one_to_one(int num);
        one_to_one(int length, int width);
  };



}

#endif /* CIRCUIT_HPP */
back to top