Copyright (c) 2019- Beit, Beit.Tech, Beit.Inc
Quasar is a utility tool to simplify writing quantum assembly code. It helps translate high level if statements into a sequence of controlled quantum commands. It can be easily integrated with IBM Qiskit, Google Cirq or OpenQASM.
Express your thoughts in a high-level way, let Quasar take care about details.
Features
At the beginning of each program the Program object has to be created
Single qubit object can be created as follow
An initial value for a qubit can also be provided
qubit_1 = prgm.Qubit( 1 )
Many qubits can be created in one statement
qubits = prgm.Qubits( [ 0, 1, 0, 1, 0, 1, 0, 1 ] )
Instructions are composed either with += and + operators
prgm += X( qubit_0 ) + Y( qubit_1 ) + Z( qubits[0] )
Or with a list syntax
prgm += [ X( qubit_0 ) , H( qubit_1 ) , Z( qubits[0] ) ]
Quasar simplifies writing if statements. It looks almost like in any high-level programming language
If( ... ).Then( ... )
If( ... ).Then( ... ).Else( ... )
For example
If( All( qubit_1 ) ).Then(
X( qubit_0 )
)
Inside an if statements some functions can be used
Any( qubits: List[ Qubit ] ) -> Bool, at least one qubit has to be set to 1
If( Any( qubits[0], qubits[1], qubits[2] ) )
Zero( qubits: List[ Qubit ] ) -> Bool, all qubits have to be set to 0
If( Zero( qubits[0], qubits[1], qubits[2] ) )
All( qubits: List[ Qubit ] ) -> Bool, all qubits has to be set to 1
If( All( qubits[0], qubits[1], qubits[2] ) )
Match( qubits : List[ Qubit ], mask: List[int] ) -> Bool, all qubits has to be set as in a mask
If( Match( [qubits[0], qubits[1], qubits[2], qubits[3]], mask=[1, 0, 1, 0] ) )
To simplify writing Grover algorithm If(...).Flip() statement is provided. Flip make phase inversion for all states which satisfy the condition.
If( All( qubits[0], qubits[1], qubits[2] ).Flip()
Installation and Requirements
Quasar is a single python file script. It does not have any non-standard dependencies. It is required to have python >= 3.7
Extension
To generate an assembly code in your own format just define an implementation of the IQAsmFormatter class
Quasar to IBM Qiskit intagration
# Quasar from quasar import All, H, If, Program, Quasar, X prgm = Program() q_bits = prgm.Qubits([0, 0]) c_bits = prgm.CBits(2) prgm += X(q_bits[0]) prgm += If(All(q_bits[0])).Then( H(q_bits[1]) ) # Quasar -> OpenQASM qasm_str = Quasar().to_qasm_str(prgm) # OpenQASM -> Qiskit from qiskit import execute, Aer, QuantumCircuit circuit = QuantumCircuit.from_qasm_str(qasm_str) result = execute(circuit, Aer.get_backend('statevector_simulator')).result() print(result.get_statevector(circuit, decimals=3))
Syntax examples
from quasar import All, If, Not, Program, Quasar, X def example_nested_if() -> None: prgm = Program() q_vars = prgm.Qubits(32 * [0]) prgm += If(All([q_vars[1], q_vars[2], q_vars[3], q_vars[4]])).Then( X(q_vars[3]) + If(Not(All(q_vars[4]))).Then( X(q_vars[5]) + X(q_vars[6]) ).Else( If(All(q_vars[7])).Then( [X(q_vars[8]), X(q_vars[9])] ).Else( [X(q_vars[10]), X(q_vars[11])] ) ) ).Else( If(Not(All(q_vars[11]))).Then( X(q_vars[12]) + X(q_vars[13]) ).Else( If(All(q_vars[14])).Then( X(q_vars[15]) + X(q_vars[16]) + If(Not(All(q_vars[17]))).Then( X(q_vars[18]) + X(q_vars[19]) ).Else( If(All(q_vars[20])).Then( [X(q_vars[21]), X(q_vars[22])] ).Else( [X(q_vars[23]), X(q_vars[24])] ) ) ).Else( If(Not(All(q_vars[25]))).Then( X(q_vars[26]) + X(q_vars[27]) ).Else( If(All(q_vars[28])).Then( [X(q_vars[29]), X(q_vars[30])] ).Else( [X(q_vars[31])] ) ) ) ) ) print(Quasar().to_qasm_str(prgm)) example_nested_if()
from quasar import All, CX, If, Measurement, Program, Quasar def example_measurement() -> None: prgm = Program() q_vars = prgm.Qubits([1, 0, 1, 0, 0]) c_vars = prgm.CBits(5) prgm += ( CX(q_vars[0], q_vars[1]) + If(All(q_vars[1])).Then( If(All(q_vars[2])).Then( CX(q_vars[3], q_vars[4]) ) ) + Measurement(q_vars[0], c_vars[0]) ) print(Quasar().to_qasm_str(prgm)) example_measurement()
from typing import Callable, List from math import asin, pi, sqrt from quasar import All, ASTNode, CX, Flip, H, If, Match, Measurement, Program, Quasar, Qubit, Zero def example_grover() -> None: def Grover( qubits: List[Qubit], predicate: ASTNode ) -> Program: prgm = Program() for qubit in qubits: prgm += H(qubit) # IBM QisKit http://tiny.cc/wn7uaz #number_of_iters : Callable[[int], int] = \ # lambda size: int(sqrt(2 ** size)) # arxiv http://tiny.cc/mo7uaz number_of_iters : Callable[[int], int] = \ lambda size: int(pi / 4 / asin(sqrt(1 / (2 ** size)))) for _ in range(number_of_iters(len(qubits))): prgm += If(predicate).Flip() for qubit in qubits: prgm += H(qubit) prgm += If(Zero(qubits)).Flip() for qubit in qubits: prgm += H(qubit) prgm += Flip(qubits) return prgm prgm = Program() qubits = prgm.Qubits([0, 0, 0]) prgm += Grover(qubits, predicate=Match(qubits, mask=[0, 1, 0])) print(Quasar().to_qasm_str(prgm)) example_grover()
from typing import List from math import pi from quasar import All, CNot, If, H, Phase, Program, Quasar, Qubit def example_fourier() -> None: def Fourier( qubits: List[Qubit] ) -> Program: prgm = Program() length = len(qubits) for i in range(length): prgm += H(qubits[i]) for j in range(2, length + 1 - i): prgm += If(All(qubits[i + j - 1])).Then( Phase(qubits[i], 2 * pi / (2 ** j)) ) for i in range(length // 2): prgm += CNot(qubits[i], qubits[length - i - 1]) prgm += CNot(qubits[length - i - 1], qubits[i]) prgm += CNot(qubits[i], qubits[length - i - 1]) return prgm prgm = Program() qubits = prgm.Qubits([0, 1]) prgm += Fourier(qubits) print(Quasar().to_qasm_str(prgm)) example_fourier()
License
MIT