from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import execute, Aer
from QArithmetic import add

# Registers and circuit.
a = QuantumRegister(4)
b = QuantumRegister(5)
ca = ClassicalRegister(4)
cb = ClassicalRegister(5)
qc = QuantumCircuit(a, b, ca, cb)

# Numbers to add.
qc.x(a[1]) # a = 01110
qc.x(a[2])
qc.x(a[3])
qc.x(b[0]) # b = 01011
qc.x(b[1])
qc.x(b[3])

# Add the numbers, so |a>|b> to |a>|a+b>.
add(qc, a, b, 4)

# Measure the results.
qc.measure(a, ca)
qc.measure(b, cb)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

from QArithmetic import sub

# Registers and circuit.
a = QuantumRegister(5)
b = QuantumRegister(5)
ca = ClassicalRegister(5)
cb = ClassicalRegister(5)
qc = QuantumCircuit(a, b, ca, cb)

# Numbers to subtract.
qc.x(a[1]) # a = 01110
qc.x(a[2])
qc.x(a[3])
qc.x(b[0]) # b = 01011
qc.x(b[1])
qc.x(b[3])

# Add the numbers, so |a>|b> to |a>|a-b>.
sub(qc, a, b, 5)

# Measure the results.
qc.measure(a, ca)
qc.measure(b, cb)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

from QArithmetic import mult

# Registers and circuit.
a = QuantumRegister(2)
b = QuantumRegister(2)
m = QuantumRegister(4)
cm = ClassicalRegister(4)
qc = QuantumCircuit(a, b, m, cm)

# Numbers to multiply.
qc.x(a[1]) # a = 10 = 2
qc.x(b[0]) # b = 11 = 3
qc.x(b[1])

# Multiply the numbers, so |a>|b>|m=0> to |a>|b>|a*b>.
mult(qc, a, b, m, 2)

# Measure the result.
qc.measure(m, cm)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))


from QArithmetic import div

# Registers and circuit.
a = QuantumRegister(4)
b = QuantumRegister(4)
c = QuantumRegister(2)
ca = ClassicalRegister(4)
cb = ClassicalRegister(4)
cc = ClassicalRegister(2)
qc = QuantumCircuit(a,b,c,ca,cb,cc)

# Inputs.
qc.x(a[0]) # a = 0011
qc.x(a[1])
qc.x(b[3]) # b = 1000

# Divide a by b.
div(qc, a, b, c, 2)

# Measure.
qc.measure(a, ca)
qc.measure(b, cb)
qc.measure(c, cc)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

from QArithmetic import power
from qiskit.providers.aer import QasmSimulator

# Registers and circuit
a = QuantumRegister(2)
b = QuantumRegister(2)
m = QuantumRegister(6)
ca = ClassicalRegister(2)
cb = ClassicalRegister(2)
cm = ClassicalRegister(6)
qc = QuantumCircuit(a, b, m, ca, cb, cm)

# Inputs.
qc.x(a[1]) # a = 10
qc.x(b[1]) # b = 10

# Raise a to the b power.
power(qc, a, b, m)

# Measure.
qc.measure(a, ca)
qc.measure(b, cb)
qc.measure(m, cm)

#Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))


from QArithmetic import bitwise_and

# Registers and circuit.
a = QuantumRegister(4)
b = QuantumRegister(4)
c = QuantumRegister(4)
ca = ClassicalRegister(4)
cb = ClassicalRegister(4)
cc = ClassicalRegister(4)
qc = QuantumCircuit(a, b, c, ca, cb, cc)

# Inputs
qc.x(a[1]) # a =1010
qc.x(a[3])
qc.x(b[0]) # b = 1011
qc.x(b[1])
qc.x(b[3])

# Take the bitwise AND.
bitwise_and(qc, a, b, c, 4)

# Measure.
qc.measure(a, ca)
qc.measure(b, cb)
qc.measure(c, cc)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

from QArithmetic import bitwise_or

# Registers and circuit.
a = QuantumRegister(4)
b = QuantumRegister(4)
c = QuantumRegister(4)
ca = ClassicalRegister(4)
cb = ClassicalRegister(4)
cc = ClassicalRegister(4)
qc = QuantumCircuit(a, b, c, ca, cb, cc)

# Input.
qc.x(a[1]) # a = 1010
qc.x(a[3])
qc.x(b[0]) # b = 1011
qc.x(b[1])
qc.x(b[3])

# Take the bitwise OR.
bitwise_or(qc, a, b, c, 4)

# Measure.
qc.measure(a, ca)
qc.measure(b, cb)
qc.measure(c, cc)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

from QArithmetic import bitwise_xor

# Registers and circuit.
a = QuantumRegister(4)
b = QuantumRegister(4)
c = QuantumRegister(4)
ca = ClassicalRegister(4)
cb = ClassicalRegister(4)
cc = ClassicalRegister(4)
qc = QuantumCircuit(a, b, c, ca, cb, cc)

# Input.
qc.x(a[1]) # a = 1010
qc.x(a[3])
qc.x(b[0]) # b = 1011
qc.x(b[1])
qc.x(b[3])

# Take the bitwise XOR.
bitwise_xor(qc, a, b, c, 4)

# Measure.
qc.measure(a, ca)
qc.measure(b, cb)
qc.measure(c, cc)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

from QArithmetic import bitwise_not

# Registers and circuit.
a = QuantumRegister(4)
b = QuantumRegister(4)
ca = ClassicalRegister(4)
cb = ClassicalRegister(4)
qc = QuantumCircuit(a, b, ca, cb)

# Input.
qc.x(a[1]) # a =  1010
qc.x(a[3])

# Take the bitwise NOT.
bitwise_not(qc, a, b, 4)

# Measure.
qc.measure(a, ca)
qc.measure(b, cb)

# Simulate the circuit.
backend_sim = Aer.get_backend('qasm_simulator')
job_sim = execute(qc, backend_sim)
result_sim = job_sim.result()

print(result_sim.get_counts(qc))

