2013年12月27日 星期五

Quantum addition operation in python and c++

############
###python###
############
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator

def adder_A():
    #Half Adder: inputs q0,q1 -> outputs q2=Sum, q3=Cout#
    # Initialize local simulator
    sim = AerSimulator()

    # Quantum and Classical Registers
    q = QuantumRegister(4, 'q')   # q0=A, q1=B, q2=Sum, q3=Cout
    c = ClassicalRegister(4, 'c')
    qc = QuantumCircuit(q, c)

    # Prepare inputs (using superposition as an example)
    qc.h(q[0])
    qc.h(q[1])

    # Sum = A XOR B (Result stored in q2)
    qc.cx(q[0], q[2])
    qc.cx(q[1], q[2])

    # Cout = A AND B (Using Toffoli gate -> result in q3)
    qc.ccx(q[0], q[1], q[3])

    # Measure all output and intermediate registers
    qc.measure(q, c)

    # Print ASCII circuit diagram
    print("Half Adder Circuit (ASCII):")
    print(qc.draw(output="text"))

    # Execute simulation
    result = sim.run(qc, shots=8192).result()
    counts = result.get_counts()
    print("\nHalf Adder Measurement Results:")
    for k, v in sorted(counts.items()):
        print(f"{k} : {v}")

def adder_B():
    """Full Adder: inputs q0(A), q1(B), q2(Cin) -> q3=Sum, q4=Cout"""
    # Initialize local simulator
    sim = AerSimulator()

    # Quantum and Classical Registers
    # q0=A, q1=B, q2=Cin, q3=Sum (acts as ancilla during calculation), q4=Cout
    q = QuantumRegister(5, 'q')   
    c = ClassicalRegister(5, 'c')
    qc = QuantumCircuit(q, c)

    # Prepare inputs (using superposition as an example)
    qc.h(q[0])
    qc.h(q[1])
    qc.h(q[2])

    # --- Computational Flow (Maintaining Reversibility) ---
    
    # 1) Calculate (A XOR B) and store in q3 (temporary)
    qc.cx(q[0], q[3])
    qc.cx(q[1], q[3])
    # Now q3 = A XOR B

    # 2) Calculate Cin AND (A XOR B), write result to q4 (Cout buffer)
    qc.ccx(q[2], q[3], q[4])
    
    # 3) Calculate (A AND B). If 1, flip q4. 
    # (Since both terms cannot be 1 simultaneously, XOR here acts as OR)
    qc.ccx(q[0], q[1], q[4])
    # Now q4 = (A AND B) OR (Cin AND (A XOR B)) -> Correct Carry Out (Cout)

    # 4) Generate Sum: Add Cin to q3 
    # (q3 was A XOR B; after CX, it becomes A XOR B XOR Cin)
    qc.cx(q[2], q[3])
    # Now q3 = Sum

    # Measure all registers
    qc.measure(q, c)

    # Print ASCII circuit diagram
    print("\nFull Adder Circuit (ASCII):")
    print(qc.draw(output="text"))

    # Execute simulation
    result = sim.run(qc, shots=8192).result()
    counts = result.get_counts()
    print("\nFull Adder Measurement Results:")
    for k, v in sorted(counts.items()):
        print(f"{k} : {v}")

if __name__ == "__main__":
    adder_A()
    adder_B()

#########
###c++###
#########
1. preinstall
sudo apt install -y build-essential wget libtinfo5 libstdc++-12-dev

wget --continue https://github.com/NVIDIA/cuda-quantum/releases/download/0.9.1/install_cuda_quantum_cu12.x86_64
chmod 755 ./install_cuda_quantum_cu12.x86_64
sudo ./install_cuda_quantum_cu12.x86_64 --accept --target /opt/nvidia/cuda-quantum

2. Makefile
TARGET = qpu_client

SRCDIR    = ./source
OBJDIR    = ./obj
BINDIR    = ./bin

CXX         = /opt/nvidia/cudaq/bin/nvq++

CXXFLAGS    = -I/opt/nvidia/cudaq/include --target qpp-cpu -std=c++17 -fPIC -O0 -g
LDFLAGS     = -L/opt/nvidia/cudaq/lib

CXXFILES    = $(notdir $(wildcard $(SRCDIR)/*.cpp))
CXXOBJS        = $(patsubst %.cpp, $(OBJDIR)/%.o, $(CXXFILES))

$(shell mkdir -p $(OBJDIR))
$(shell mkdir -p $(BINDIR))

$(OBJDIR)/%.o : $(SRCDIR)/%.cpp
    $(CXX) -c $(CXXFLAGS) $< -o $@

$(TARGET): $(COBJS) $(CXXOBJS)
    $(CXX) $^ $(LDFLAGS) -o $(BINDIR)/$@

all: $(TARGET)

clean:
    rm -rf $(OBJDIR) $(BINDIR)

3. source
/**
 * Quantum kernel representing a Half Adder circuit.
 * Input bits: q[0], q[1]
 * Output bits: q[2] (Sum), q[3] (Carry Out)
 */
__qpu__ static void half_adder() {
    // Allocate 4 qubits
    cudaq::qvector q(4);

    // Initialize inputs q[0] and q[1] into a superposition of all possible states (00, 01, 10, 11)
    h(q[0]);
    h(q[1]);

    // --- Sum Logic ---
    // Perform XOR operations: q[2] = q[0] ^ q[1]
    cx(q[0], q[2]);
    cx(q[1], q[2]);

    // --- Carry Out (Cout) Logic ---
    // Perform AND operation: q[3] = q[0] & q[1] using a Toffoli gate
    ccx(q[0], q[1], q[3]);

    // Measure all qubits in the Z-basis
    mz(q);
}

int main() {
    // Define the number of times to run the circuit (shots)
    int shot_count = 8192;

    // Sample the quantum kernel
    cudaq::sample_result counts = cudaq::sample(shot_count, half_adder);

    // Output the results
    std::cout << "CUDA-Q Half Adder Results:\n";
    for(auto& [bits, count] : counts) {
        // 'bits' represents the binary string of the measurement outcome
        std::cout << bits << " : " << count << "\n";
    }

    return 0;
}

4. debug
sudo apt install nvidia-cuda-gdb
/usr/bin/cuda-gdb /root/asustor_projects/qpu_client/bin/qpu_client
(cuda-gdb): directory /root/asustor_projects/qpu_client/source
(cuda-gdb): set solib-absolute-prefix /opt/nvidia/cudaq
(cuda-gdb): set solib-search-path /opt/nvidia/cudaq/lib:/opt/nvidia/cudaq/lib64
(cuda-gdb): break qpu_client.cpp:21
(cuda-gdb): run

download:
https://www.mediafire.com/file/2svhpg4eqh1qktm/qpu_py.zip/file
https://www.mediafire.com/file/si1cri8zbmy8dm9/qpu_cpp.zip/file

沒有留言:

張貼留言