View on GitHub
Open this notebook in GitHub to run it yourself
- Exponentiation and Pauli Operators.
- Arithmetics and numeric assignment.
- The
within_applystatement. - The
bindstatement.
Exercise 7
- Exponentiation and Pauli Operators
Pauli Enum acting in the correct set of qubits.
This exercise uses the Suzuki-Trotter function to find the evolution of H=0.5XZXX + 0.25YIZI + 0.3 XIZY (captured as a literal value for the Pauli operator), with the evolution coefficient being 3, the order being 2, and using 4 repetitions.
See suzuki_trotter.
To complete this exercise, allocate q and invoke the suzuki_trotter quantum function:
HINT
HINT
suzuki_trotter(
…,
evolution_coefficient=3,
repetitions=4,
order=2,
qbv=q,
)
…,
evolution_coefficient=3,
repetitions=4,
order=2,
qbv=q,
)
Output:
Exercise 8
- Basic Arithmetics
Exercise 8a
Create this quantum program:- Initialize variables
x=2,y=7and computeres = x + y. - Initialize variables
x=2,y=7and computeres = x * y. - Initialize variables
x=2,y=7,z=1and computeres = x * y - z.
- Use the
|=operators to perform out-of-place assignment of arithmetic expressions. - To initialize the variables, use the
|=to assgin it with a numerical value.
Output:
Exercise 8b
- Declare
xto be a 2-qubit numeric variable andya 3-qubit numeric variable. - Use
prepare_stateto initializexto an equal superposition of0and2, andyto an equal superposition of1,2,3, and6(see prepare_state).
- Compute
res = x + y.
Output:
Exercise 9
- Within-Apply
V within the context of another function U, and afterward uncompute U to release auxiliary qubits storing intermediate results.
See within apply.
Exercise 9a
This exercise useswithin-apply to compute an arithmetic expression in steps.
Use the within_apply operation to calculate res = x + y + z from a two-variable addition building block with these steps:
- Add
xandy - Add the result to
z - Uncompute the result of the first operation
x=3, y=5, z=2.
Hints:
- Use a temporary variable.
- Use the function syntax of numeric assignment.
Output:
Exercise 9b
Why usewithin-apply and not just write three concatenated functions?
To understand the motivation, create another arithmetic circuit.
This time, however, set the Classiq synthesis engine to optimize on the circuit’s number of qubits; i.e., its width.
Determine constraints inside synthesis with Constraints. (See here).
Perform the operation res = w + x + y + z, where w is initialized to 4 and the rest as before:
- Add
xandy(as part of thewithin_applyoperation) - Add the result to
z(as part of thewithin_applyoperation) - Uncompute the result of the first operation (as part of the
within_applyoperation) - Add the result of the second operation to
w.
Output:
Bonus: Use a Single Arithmetic Expression
What happens when you don’t manually decompose this expression? Use the Classiq arithmetic engine to calculateres |= x + y + z + w and optimize for width.
Look at the resulting quantum program.
Can you identify the computation and uncomputation blocks? What else do you notice?
Output:
Exercise 10
- In-place Arithmetics
Exercise 10a
- Conditional Computation
QNum[n, UNSIGNED, f] uses n qubits to represent non-negative values, with f of those bits after the binary point — so QNum[3, UNSIGNED, 3] covers the range in steps of .
The goal is to evaluate the following piecewise function over a superposition of fixed-point inputs:
The provided code skeleton puts x into a uniform superposition of all values in via the Hadamard transform, and pre-allocates res to hold the result.
Fill in the body of main to evaluate f(x) into res:
- Compute a boolean quantum variable representing the condition
x < 0.5. - Use
controlwithstmt_blockandelse_blockto apply the correct formula toresdepending on the branch.
res inside each branch, use inplace_xor(expression, res).
You will learn in Exercise 10b exactly why this is needed instead of the familiar |= operator.
Note: Python does not allow assignment operators (|=, ^=, +=) inside lambda expressions.
Factor the in-place computation out to a named @qfunc function and call it from the control lambda.
Output:
Exercise 10b
- In-place Assignment
|= inside the control block?
The out-of-place operator |= requires its target to be uninitialized — it allocates a fresh set of qubits to store the result. In the code above, res is pre-allocated before the control block, so it is already initialized.
Using res |= expression inside a branch lambda would fail: Qmod does not allow allocation into an already-initialized variable.
In-place operators. The in-place operators write into an existing initialized variable without allocating new qubits:
inplace_xor(expression, target)— computesexpressionand XORs it bit-by-bit intotarget(equivalent totarget ^= expression)inplace_add(expression, target)— computesexpressionand adds it arithmetically intotarget(equivalent totarget += expression)
control block because they never try to allocate an uninitialized variable.
They also avoid allocating a separate result register per branch — both branches share the single pre-allocated res, saving qubits.
Since res is initialized to zero before the control block, inplace_xor and inplace_add produce the same result here (XOR with zero and ADD with zero are equivalent).
They would differ if res had a non-zero initial value, or for multi-bit values where carries (ADD) and bit-by-bit XOR diverge.
See numeric assignment.
Exercise: Modify your Exercise 10a solution to use inplace_add instead of inplace_xor and verify that you get the same measurement results.
Output:
Exercise 11
- A State-preparation Algorithm
Binding
Thebind operation smoothly converts between different quantum types and splits or slices bits when necessary.
Here is an example:
Output:
bind operation splits the 3-qubit variable x into the 2-qubit and single-qubit lsb and msb variables, respectively.
After the bind operation:
- The
lsbandmsbvariables can be operated on separately. - The
xvariable returns to its uninitialized state and can no longer be used.
bind operation concatenates the variables back to the res output variable.
For this exercise, fill in the missing code parts in the above snippet and use the control statement to manually generate the 3-qubit probability distribution: [1/8, 1/8, 1/8 - sqrt(3)/16, 1/8 + sqrt(3)/16, 1/8, 1/8, 1/8, 1/8].
The following sequence of operations generates it:
- Perform the Hadamard transform on all three qubits.
- Apply a
pi/3rotation on the LSB conditioned by the MSB being and the second-to-last MSB being .
prepare_state function.
Solutions
Exercise 7
Output:
Key takeaway: Qmod supports Pauli operator expressions as a native type for specifying sparse Hamiltonians.suzuki_trotterimplements time evolution under such a Hamiltonian by interleaving the exponentials of individual Pauli terms approximating . Theorderandrepetitionsparameters control the accuracy of the approximation.
Exercise 8
Output:
Key takeaway: The|=operator performs out-of-place numeric assignment: it allocates a fresh quantum register to store the result of the arithmetic expression. Complex expressions combining+,*, and-are fully supported and evaluated quantum-mechanically.
Output:
Key takeaway: Quantum arithmetic operates over superpositions simultaneously. Whenxandyeach encode a superposition of values,res |= x + yproduces a superposition of all corresponding sums, being one for each pair of input values. This is the computational parallelism that quantum arithmetic provides.
Exercise 9
Output:
Key takeaway:within_applyautomates the uncomputation pattern: it runs thewithinblock, then theapplyblock, then automatically reverses thewithinblock freeing the qubits held by temporary variables. Without it, temporaries stay initialized for the rest of the circuit, permanently occupying qubits. Note: becausewithinandapplymust be Python lambdas, and expressions, such as|=, cannot appear in a lambda, useassign(expression, target)as the functional equivalent.
Output:
Key takeaway: Qubit reuse is only possible when temporary variables are properly uncomputed.within_applyenables the synthesizer to reclaim freed qubits for subsequent operations. The synthesis optimization on width (OptimizationParameter.WIDTH) makes this reuse explicit: the same qubits appear in different logical roles at different points in the circuit.
Exercise 10a
Output:
Key takeaway: Piecewise quantum functions are implemented by computing a boolean condition into an auxiliary qubit (aux |= x < 0.5) and usingcontrolwithstmt_blockandelse_blockto select the appropriate formula. Becausexis in a superposition, the model evaluates both branches in parallel: each computational basis state follows the branch dictated by its own value ofx.
Exercise 10b
Output:
Key takeaway: In-place operators (inplace_xor,inplace_add) are necessary when writing into a pre-initialized variable inside a quantum operator likecontrol. The out-of-place|=cannot be used there becauseresis initialized at the beginning of the quantum program. In-place operators also avoid allocating a separate result register per branch — both branches share the single pre-allocatedres, saving qubits. When the target starts at zero,inplace_xorandinplace_addgive identical results; they diverge for non-zero initial values or when arithmetic carries differ from bitwise XOR.
Exercise 11
Output:
Key takeaway: Thebindoperation casts and splits quantum variables into different quantum types. In this example, after thebindstatement, the variablexis split into two different quantum types: a qubitlsband a quantum numbermsb. Sincemsbis a quantum number, it is possible to perform numeric operations with it, such as compare it to an integer,as it is done inside thecontroloperation.