This is a simple implementation of quantum circuitry emulation framework. Some comment's on how it's implemented are on my blog.
Have you ever wondered whether the black-box boolean function
This framework is kind of similar to QisKit but less powerful, so if you want to do something serious with quantum computation use QisKit instead. I wanted to try to implement this myself as a hobby project and I didn't inspect QisKit sources and only learned about it when I was finishing this.
The code is designed as a re-usable and extensible OOP/lazy-evaluation library.
I guess it could be used for educational purposes, or something?
The Deutsch-Jozsa quantum circuit:
That can be implemented (here for simplicity
fromgatesimportBooleanReversibleGate, HadamardGate, TensorProductGate, IdentityGate, CircuitfromqubitsimportQubitArrayfromtypingimportCallable, CollectionclassDeutschOracle(BooleanReversibleGate):
def__init__(self, f: Callable[[bool], bool]):
super().__init__(lambdax, y: (x, y^f(x)))
defdeutsh_algorithm(f: Callable[[bool], bool]) ->Collection[float]:
circuit=Circuit( # lazy declarationHadamardGate(2),
DeutschOracle(f),
TensorProductGate(HadamardGate(1), IdentityGate(1))
)
input_qubits=QubitArray.from_bits([0, 1])
final_pure_state=circuit(input_qubits) # Actual emulation happens herereturnfinal_pure_state.measure() # Get probabilities of observations using Born ruleif__name__=="__main__":
print(deutsh_algorithm(lambdax: False)) # constantprint(deutsh_algorithm(lambdax: True)) # constantprint(deutsh_algorithm(lambdax: x)) # balancedprint(deutsh_algorithm(lambdax: notx)) # balancedThe quantum algorithm will differentiate the balanced and the constant boolean functions using a single pass, something that is impossible on a classical computer. The output from the block above is:
[0.5, 0.5, 0, 0]
[0.5, 0.5, 0, 0]
[ 0, 0, 0.5, 0.5]
[ 0, 0, 0.5, 0.5]
These probabilities correspond to the observations of
Cool video explaing the homemade hardware implementation for this: https://www.youtube.com/watch?v=tHfGucHtLqo
The gates API should be flexible enough to build various gates from the primitives. For example:
fromgatesimportCircuit, HadamardGate, ControlledGate, PauliX, BooleanReversibleGate, \
PhaseShiftGate, Oraclefrommathimportpiasπcnot=ControlledGate(2, PauliX(), at_qubit=1, controlled_by=0)
toffoli=ControlledGate(3, cnot, at_qubit=1, controlled_by=0)
swap=BooleanReversibleGate(lambdax, y: (y, x))
sqrt_not=Circuit(HadamardGate(1), PhaseShiftGate(-π/2), HadamardGate(1))
sqrt_swap=Oracle([
[1, 0, 0, 0],
[0, 0.5+0.5j, 0.5-0.5j, 0],
[0, 0.5-0.5j, 0.5+0.5j, 0],
[0, 0, 0, 1]
])