Quick Examples

  • Using QDD in a program

  • Example : Multiplexed Adder

  • Example : the SHORNUF factoring algorithm


    Using QDD

    Back to Top

    To use QDD, add the following header to your program :

    #include "qdd.h"
    
    And hack up the following Makefile :
    # --- Location of QDD/BDD package installation
    QDDLOC = ..
    
    # --- Location of QDD/BDD library
    LIBDIR = $(QDDLOC)/lib
    
    # --- Location of QDD/BDD package header
    INCDIR = $(QDDLOC)/include
    
    # --- Linker flags for use with QDD (order and location *is* important)
    QDDFLAGS = -lqdd -lbdd -lm -lg++
    
    # --- Compiler flags
    CFLAGS = -g -O3 -Wall
    
    # --- Your C++ compiler
    CPP = g++
    
    all: shornuf
    
    shornuf: shornuf.o
    	$(CPP) shornuf.o -L$(LIBDIR) $(QDDFLAGS) -o shornuf
    
    shornuf.o: shornuf.cc
    	$(CPP) $(CFLAGS) -c shornuf.cc -I$(INCDIR) -o shornuf.o
    


    QDD Example : A multiplexed adder (from QCL)

    Back to Top

    
    void muxaddbit (int a0, int a1, QuantumBit & sel, QuantumBit & b, QuantumBit & ci_sum, QuantumBit & co, QuantumBit & e, int dir) {
    
    // Note that the arguments here are object references.
    // We don't allow QuantumBits/Registers to be copied at all.
    // This helps guarantee quantum consitency in the model.
    
    // We have to cheat to implement reversible operations :(
    
      if (dir > 0) {
    
    // Allocate a single quantum bit M with an initial value of 0.
    
        QuantumBit M(0);
    
    
    // The C++ "^=" operator has been overloaded to be the quantum XOR
    // operator.  The C++ infix "&" allows accumulation of conditions for
    // use in the quantum XOR.  In the following line, if the classical
    // control signal a1 equals 1, then we will conditionally invert the
    // quantum bit M in the quantum state where the quantum bits
    // e and sel are true.
    
    
        if (a1) M ^= e & sel;
    
    // Conditionally invert M if a0=1 when e is true and sel is false.
    
        if (a0) M ^= e & (! sel);
    
    // .. etc 
    
        ci_sum ^= e & M;
        ci_sum ^= e & b;
    
        co  ^= e & M & (! ci_sum);
        co  ^= e & (! M) & b & (! ci_sum);
        co  ^= e & M & b & ci_sum ;
    
    // Undo the operations performed on M
    
        if (a0) M ^= e & (! sel);
    
        if (a1) M ^= e & sel;
    
    // By the time we get here, M should be in a pure state ..
    // in fact, it should be in its original (false) state.
    // (which I could/should have tested for, I guess :)
    
        try {
          M.unMixed();
        }
        catch (QuantumException e) {
    
    // This is really a violation of quantum computing rules .. You cannot
    // "tell" if a bit is in a pure state.  Nonetheless, such tests are 
    // considered necessary during software development .. at least 
    // it helped me :)
    
    
          cerr << "muxaddbit() : Mixed Bits\n" ;
          throw e;
        }
    
    // At this point, C++ helps us do quantum garbage collection (automagically)
    // Since M is in a pure state, we can reuse it later
    
      }
    
      else {
    
    // The reverse operation.
    
        QuantumBit M(0);
    
        if (a1) M ^= e & sel;
    
        if (a0) M ^= e & (! sel);
    
        co  ^= e & M & b & ci_sum ;
        co  ^= e & (! M) & b & (! ci_sum);
        co  ^= e & M & (! ci_sum);
    
        ci_sum ^= e & b;
        ci_sum ^= e & M;
    
        if (a0) M ^= e & (! sel);
    
        if (a1) M ^= e & sel;
    
        try {
          M.unMixed();
        }
        catch (QuantumException e) {
          cerr << "muxaddbit(-1) : Mixed Bits\n" ;
          throw e;
        }
    
      }
    
    }
    


    QDD Example : SHORNUF (based on routine from QCL)

    Back to Top

    
    Integer shornuf(Integer Number) {
    
    // We use g++ BIGNUM Integers to make life easier when factoring really big numbers.
    
      Integer Factor;
      Integer f1,f2;
      Integer A;
      Integer Cv;
      Integer Xv;
    
      int size = ilog2(Number);
    
      cout << "Bits : " << size << "\n";
    
    // Here we allocate a quantum register with size bits.
    
      QuantumRegister F(size);
      Integer Fv;
    
      QuantumRegister X(size);
      Integer Pv;
    
      int attempt = 1;
      int found = 0;
      while ((attempt < 8) && (! found)) {
    
        cout << "Attempt # " << attempt << "\n" ;
    
        do {
          
          A =  (rand(size) % Number) | 3 ;
        
        } while (gcd(Number,A) != 1) ;
    
        cout << "Random A : " << A << "\n";
    
    // Here we set the value of the X register to all zeros.
    
        X.Set(0);
    
    // We then perform an X.Mix() to place the register in a superposition of states.
    
        X.Mix();
                
        F.Set(0);
    
    // Perform Quantum Exponentiation (Wow!)
    
        expn(A,Number,X,F, 1); // F = a^X mod n
    
    // Perform a classical sampling of F.  This collapses the entire quantum
    // state so that it is consistant with the value measured in F.
    
        Fv = F.Sample();
    
    // Measure the period of X.  Unfortunately, a bit of a quantum cheat.
    
        Pv = X.Period();
    
        f1 = gcd((powmod(A,Pv/2,Number) + 1) % Number , Number) ;
        f2 = gcd((powmod(A,Pv/2,Number) + Number - 1) % Number , Number) ;
    
        Xv = X.Sample();
    
        Cv = powmod(A,Xv,Number);
    
        assert(Cv == Fv, "Mismatch");
    
        f1 = gcd(Number,f1);
        f2 = gcd(Number,f2);
    
        Factor = (f1 > f2 ? f1 : f2);
    
        found = (Factor > 1) && (Factor < Number);
    
        attempt++;
    
      }
    
      return(Factor);
    
    }