Parameterized quantum circuits (PQCs) contain gates with tunable parameters that can be optimized. Instead of using fixed angles, you use symbolic parameters that can be adjusted to find optimal values.
Why use parameters? Fixed angles give you one specific operation. Parameters let you:
Rotation gates (Rx, Ry, Rz) are the primary parameterized gates. Use string names (e.g., "theta") instead of numbers to create parameters, then bind values before execution.
Rotation gates rotate a qubit around the X, Y, or Z axis of the Bloch sphere. Each axis controls different aspects:
Rotates a qubit around the X-axis by angle θ.
[ R_x(\theta) = \begin{pmatrix} \cos(\theta/2) & -i\sin(\theta/2) \ -i\sin(\theta/2) & \cos(\theta/2) \end{pmatrix} ]
[ R_x(\pi/2)|0\rangle = \frac{1}{\sqrt{2}}(|0\rangle - i|1\rangle) ]
from qumat import QuMat import numpy as np backend_config = { 'backend_name': 'qiskit', 'backend_options': {'simulator_type': 'qasm_simulator', 'shots': 1000} } qumat = QuMat(backend_config) qumat.create_empty_circuit(num_qubits=1) qumat.apply_rx_gate(0, angle=np.pi / 2) results = qumat.execute_circuit()
Rotates a qubit around the Y-axis by angle θ.
[ R_y(\theta) = \begin{pmatrix} \cos(\theta/2) & -\sin(\theta/2) \ \sin(\theta/2) & \cos(\theta/2) \end{pmatrix} ]
[ R_y(\pi/2)|0\rangle = \frac{1}{\sqrt{2}}(|0\rangle + |1\rangle) ]
qumat.create_empty_circuit(num_qubits=1) qumat.apply_ry_gate(0, angle=np.pi / 2) # Creates (|0⟩ + |1⟩)/√2 results = qumat.execute_circuit()
Rotates a qubit around the Z-axis by angle θ. Changes phase without affecting probability amplitudes.
[ R_z(\theta) = \begin{pmatrix} e^{-i\theta/2} & 0 \ 0 & e^{i\theta/2} \end{pmatrix} ]
[ R_z(\pi/2)\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle) = \frac{1}{\sqrt{2}}(|0\rangle + i|1\rangle) ]
Probabilities remain: P(|0⟩) = P(|1⟩) = 1/2
qumat.create_empty_circuit(num_qubits=1) qumat.apply_hadamard_gate(0) qumat.apply_rz_gate(0, angle=np.pi / 2) results = qumat.execute_circuit()
Notes: Angles are in radians (π = 180°, π/2 = 90°, π/4 = 45°). Supported across all backends (Qiskit, Cirq, Braket).
Fixed value (angle is set once):
qumat.apply_ry_gate(0, angle=0.5) # Fixed angle
Parameterized (angle can be changed):
qumat.apply_ry_gate(0, angle="theta") # Parameter - can be optimized
Use string names instead of numbers to create parameters:
from qumat import QuMat import numpy as np backend_config = { 'backend_name': 'qiskit', 'backend_options': {'simulator_type': 'qasm_simulator', 'shots': 1000} } qumat = QuMat(backend_config) # Step 1: Create circuit with parameterized gates qumat.create_empty_circuit(num_qubits=2) qumat.apply_ry_gate(0, angle="theta") # String = parameter qumat.apply_rz_gate(0, angle="phi") qumat.apply_rx_gate(1, angle="alpha") # Step 2: Parameters are automatically registered print(list(qumat.parameters.keys())) # ['theta', 'phi', 'alpha'] # Step 3: Bind parameters before execution qumat.bind_parameters({ "theta": np.pi / 4, "phi": np.pi / 2, "alpha": np.pi / 3 }) # Step 4: Execute with bound parameters results = qumat.execute_circuit() # Alternative: Bind during execution (skips step 3) results = qumat.execute_circuit(parameter_values={ "theta": np.pi / 4, "phi": np.pi / 2, "alpha": np.pi / 3 })
Assigns numerical values to symbolic parameters. Must be called before execute_circuit() if parameters are used.
Raises: ValueError if parameter name not found.
# Create circuit with parameters qumat.create_empty_circuit(num_qubits=1) qumat.apply_ry_gate(0, angle="theta") qumat.apply_rz_gate(0, angle="phi") # Bind values to parameters qumat.bind_parameters({"theta": 0.5, "phi": 1.0}) # Now you can execute results = qumat.execute_circuit()
The power of parameterized circuits: optimize parameters to minimize a cost function. The workflow is:
Example:
from qumat import QuMat import numpy as np backend_config = { 'backend_name': 'qiskit', 'backend_options': {'simulator_type': 'qasm_simulator', 'shots': 1000} } qumat = QuMat(backend_config) # Create parameterized circuit once qumat.create_empty_circuit(num_qubits=2) qumat.apply_ry_gate(0, angle="theta") qumat.apply_cnot_gate(0, 1) qumat.apply_rz_gate(1, angle="phi") # Simple optimization loop best_cost = float('inf') best_params = None for iteration in range(10): # Try different parameter values theta = np.random.uniform(0, 2 * np.pi) phi = np.random.uniform(0, 2 * np.pi) # Bind and execute qumat.bind_parameters({"theta": theta, "phi": phi}) results = qumat.execute_circuit() # Compute cost (example: minimize probability of |00⟩) total_shots = sum(results.values()) prob_00 = results.get("00", 0) / total_shots cost = prob_00 # Track best result if cost < best_cost: best_cost = cost best_params = {"theta": theta, "phi": phi} print(f"Best parameters: {best_params}, cost: {best_cost}") # With SciPy optimizer from scipy.optimize import minimize def cost_function(params): theta, phi = params qumat.bind_parameters({"theta": theta, "phi": phi}) results = qumat.execute_circuit() total_shots = sum(results.values()) prob_00 = results.get("00", 0) / total_shots return prob_00 result = minimize(cost_function, [0.5, 0.5], method='COBYLA') print(f"Optimized: {result.x}, cost: {result.fun}")
"theta") in rotation gates to create parameters