Skip to content

Arithmetic Expressions

View on GitHub

This tutorial demonstrates automatic arithmetic operation management by the synthesis engine. It synthesizes a complex arithmetic expression, where uncomputation procedure, together with initialization and reuse of auxiliary qubits, are all automated. Given different global width or depth constraints results in different circuits.

Define a quantum model that applies some quantum arithmetic operation on QNum variables.

from classiq import (
    Output,
    QBit,
    QNum,
    create_model,
    execute,
    prepare_int,
    qfunc,
    synthesize,
)
from classiq.qmod.symbolic import max


@qfunc
def main(z: Output[QNum]):
    x = QNum("x")
    y = QNum("y")
    prepare_int(2, x)
    prepare_int(1, y)
    z |= (2 * x + y + max(3 * y, 2)) > 4


qmod = create_model(main)

You can try different optimization scenarios, below we introduce two examples: 1. Optimizing over depth and constraining the maximal width to 9 qubits. 2. Optimizing over depth and constraining the maximal width to 12 qubits.

Optimizing over depth and constraining the maximal width to 9 qubits

from classiq import (
    Constraints,
    Preferences,
    set_constraints,
    set_preferences,
    show,
    write_qmod,
)

constraints = Constraints(optimization_parameter="depth", max_width=9)

preferences = Preferences(random_seed=424788457)
qmod = set_constraints(qmod, constraints)
qmod = set_preferences(qmod, preferences)

qprog = synthesize(qmod)
show(qprog)

job = execute(qprog)
result = job.result()
parsed_counts = result[0].value.parsed_counts
print("The result of the arithmetic calculation: ", parsed_counts)


write_qmod(qmod, "arithmetic_demo_9_qubits")
The result of the arithmetic calculation:  [{'z': 1.0}: 2048]

Change the quantum model constraint to treat the second scenario for optimizing over depth and constraining the maximal width to 12 qubits:

constraints = Constraints(optimization_parameter="depth", max_width=12)
qmod = set_constraints(qmod, constraints)

qprog = synthesize(qmod)
show(qprog)

job = execute(qprog)
result = job.result()
parsed_counts = result[0].value.parsed_counts
print("The result of the arithmetic calculation: ", parsed_counts)


write_qmod(qmod, "arithmetic_demo_12_qubits")
The result of the arithmetic calculation:  [{'z': 1.0}: 2048]

### Mathematical Background

The given mathematical expression:

\[z = (2 \cdot x + y + \max(3 \cdot y, 2)) > 4\]

is solved by the automatic arithmetic operation management, optimizing over depth and constraining the maximal width to 9 and 12 qubits, which outputs the value for z.

The parsed_counts result:

  • Optimizing over depth and constraining the maximal width to 9 qubits: [{'z': 1.0}: 2048]

  • Optimizing over depth and constraining the maximal width to 12 qubits: [{'z': 1.0}: 2048]

Both the result are same which verifies the arithmetic expression to be True.

The expected result:

Allocated values:

\[x = 2, \,\,\, y = 1\]

Expression Calculation:

\[2 \cdot x + y = 2 \cdot 2 + 1 = 4 + 1 = 5 \,\,\, 3 \cdot y = 3 \cdot 1 = 3 \,\,\, \max(3 \cdot y, 2) = \max(3, 2) = 3\]

Therefore:

\[2 \cdot x + y + \max(3 \cdot y, 2) = 5 + 3 = 8\]

As \(\(8 > 4 \implies \text{True}\)\)

z is assigned the value True : \(z \implies 1\)