### State Result Output Example Source: https://docs.quantinuum.com/guppy/guppylang/examples/state_results.html Example output showing state distributions for quantum shots. ```text [1.+0.j 0.+0.j 0.+0.j 0.+0.j] -> 0.5, [0.+0.j 0.+0.j 0.+0.j 1.+0.j] -> 0.5 [1.+0.j 0.+0.j 0.+0.j 0.+0.j] -> 0.5, [0.+0.j 0.+0.j 0.+0.j 1.+0.j] -> 0.5 [1.+0.j 0.+0.j 0.+0.j 0.+0.j] -> 0.5, [0.+0.j 0.+0.j 0.+0.j 1.+0.j] -> 0.5 ``` -------------------------------- ### Install Guppy Source: https://docs.quantinuum.com/guppy-v1.x/getting_started.html Commands to install the guppylang package using pip or uv. ```bash pip install guppylang ``` ```bash uv add guppylang ``` -------------------------------- ### QAOA MaxCut Implementation Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/8cd74d4a3387f04017834a077b26209e/qaoa_maxcut_example.ipynb This example demonstrates the full workflow for solving a MaxCut problem using QAOA, including graph definition and circuit execution. ```python import networkx as nx import numpy as np from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp from qiskit.primitives import Estimator from scipy.optimize import minimize # 1. Define the graph n = 4 G = nx.Graph() G.add_nodes_from(range(n)) G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)]) # 2. Define the QAOA circuit def create_qaoa_circ(G, theta): n = G.number_of_nodes() p = len(theta) // 2 gamma = theta[:p] beta = theta[p:] qc = QuantumCircuit(n) qc.h(range(n)) for i in range(p): for edge in G.edges(): qc.rzz(2 * gamma[i], edge[0], edge[1]) for node in range(n): qc.rx(2 * beta[i], node) return qc # 3. Define the cost Hamiltonian def get_cost_operator(G): pauli_list = [] for edge in G.edges(): pauli_str = ['I'] * G.number_of_nodes() pauli_str[edge[0]] = 'Z' pauli_str[edge[1]] = 'Z' pauli_list.append((''.join(pauli_str[::-1]), 1)) return SparsePauliOp.from_list(pauli_list) # 4. Optimization estimator = Estimator() cost_op = get_cost_operator(G) def cost_func(theta): qc = create_qaoa_circ(G, theta) job = estimator.run(qc, cost_op, shots=1024) return job.result().values[0] res = minimize(cost_func, x0=[1.0, 1.0], method='COBYLA') print(res) ``` -------------------------------- ### QAOA MaxCut Implementation Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/8cd74d4a3387f04017834a077b26209e/qaoa_maxcut_example.ipynb This example demonstrates the full workflow for solving a MaxCut problem using QAOA, including defining the graph, constructing the cost Hamiltonian, and running the optimization. ```python import networkx as nx import numpy as np from qiskit import QuantumCircuit, Aer, execute from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp from scipy.optimize import minimize # Define the graph n = 4 G = nx.Graph() G.add_nodes_from(range(n)) G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)]) # Define the cost Hamiltonian def get_cost_operator(G): pauli_list = [] for i, j in G.edges(): pauli_str = ['I'] * len(G.nodes()) pauli_str[i] = 'Z' pauli_str[j] = 'Z' pauli_list.append((''.join(pauli_str[::-1]), 1)) return SparsePauliOp.from_list(pauli_list) # Define the QAOA circuit def create_qaoa_circ(G, theta): n = len(G.nodes()) p = len(theta) // 2 gamma = theta[:p] beta = theta[p:] qc = QuantumCircuit(n) qc.h(range(n)) for i in range(p): # Cost layer for edge in G.edges(): qc.rzz(2 * gamma[i], edge[0], edge[1]) # Mixer layer for node in G.nodes(): qc.rx(2 * beta[i], node) qc.measure_all() return qc # Optimization def objective(theta): qc = create_qaoa_circ(G, theta) backend = Aer.get_backend('qasm_simulator') counts = execute(qc, backend, shots=1024).result().get_counts() # Calculate expectation value cost = 0 for bitstring, count in counts.items(): # Simple cost calculation for MaxCut c = 0 for i, j in G.edges(): if bitstring[i] != bitstring[j]: c += 1 cost += c * count return -cost / 1024 res = minimize(objective, [0.1, 0.1], method='COBYLA') print(res) ``` -------------------------------- ### QAOA MaxCut Implementation Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/8cd74d4a3387f04017834a077b26209e/qaoa_maxcut_example.ipynb This example shows the complete workflow for solving MaxCut using QAOA, including graph definition, Hamiltonian construction, and circuit execution. ```python import networkx as nx import numpy as np from qiskit import QuantumCircuit, Aer, execute from qiskit.circuit import Parameter from qiskit.quantum_info import SparsePauliOp from scipy.optimize import minimize # 1. Define the graph n = 4 G = nx.Graph() G.add_nodes_from(range(n)) G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)]) # 2. Define the MaxCut Hamiltonian def get_maxcut_hamiltonian(G): pauli_list = [] for u, v in G.edges(): pauli_str = ['I'] * G.number_of_nodes() pauli_str[u] = 'Z' pauli_str[v] = 'Z' pauli_list.append((''.join(pauli_str[::-1]), 1)) return SparsePauliOp.from_list(pauli_list) H = get_maxcut_hamiltonian(G) # 3. Define the QAOA circuit def qaoa_circuit(params, G, H): p = len(params) // 2 gammas = params[:p] betas = params[p:] qc = QuantumCircuit(G.number_of_nodes()) qc.h(range(G.number_of_nodes())) for i in range(p): # Cost layer for u, v in G.edges(): qc.rzz(2 * gammas[i], u, v) # Mixer layer for node in G.nodes(): qc.rx(2 * betas[i], node) return qc # 4. Optimization def objective(params): qc = qaoa_circuit(params, G, H) # ... (execution and expectation value calculation omitted for brevity) return 0 # Placeholder # Initial guess params = np.random.rand(2 * 1) result = minimize(objective, params, method='COBYLA') ``` -------------------------------- ### Importing necessary Guppy and Selene modules Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/3c803f4ffccf99bd6355366e3731e1f9/state_results.ipynb Initial setup for the Guppy environment, including imports for quantum primitives, debugging tools, and the Quest simulator. ```python from guppylang import guppy from guppylang.std.builtins import array from guppylang.std.debug import state_output from guppylang.std.quantum import qubit, discard, discard_array, cx, h, measure, x from hugr.qsystem.result import QsysResult from selene_sim import build, Quest import numpy as np np.set_printoptions(precision=4, suppress=True, linewidth=120) ``` -------------------------------- ### QAOA Optimization Output Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/qaoa_maxcut_example.html Example output from the QAOA optimizer execution. ```text Optimizer status: Return from COBYLA because the trust region radius reaches its lower bound. Objective evaluations: 77 Optimized energy: 5.0995 Cost angles: [1.736 2.63 4.751] Mixer angles: [4.831 2.361 2.2 ] ``` -------------------------------- ### Emulator Result Output Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/adaptive-qpe.html Example output returned by the emulator. ```text EmulatorResult(results=[QsysShot(entries=[('eigenvalue', 2.3679925580437398)])]) ``` -------------------------------- ### Define and compare angles Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/std/angles.html Examples of creating angle instances and comparing them to pi. ```python angle(1/2) == pi / 2 # True: both represent π/2 radians (90°) angle(1) == pi # True: both represent π radians (180°) angle(2) == angle(0) # False: a full turn is not identified with zero ``` -------------------------------- ### Executing the runtime experiment Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/random_numbers.html Execution call and expected output for the runtime randomness example. ```python run(main) ``` ```text 0.95 ``` -------------------------------- ### Executing the pre-compiled experiment Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/random_numbers.html Execution call and expected output for the pre-compiled randomness example. ```python run(main) ``` ```text 1.04 ``` -------------------------------- ### Eager measurement implementation Source: https://docs.quantinuum.com/guppy/_downloads/012ca9e4b50e69c1a1c98f9da4bfc534/deferred_measurement.ipynb An example of measuring qubits immediately using the standard measure function. ```python N = guppy.nat_var("N") @guppy @no_type_check def eager_read(qs: array[qubit, N] @ owned) -> None: for q in qs: result("t", measure(q)) # forces immediate measurement of q # [... more quantum operations ...] eager_read.check() ``` -------------------------------- ### Allocate Qubits with Comptime Argument Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/comptime.html This example shows how to fix the static size inference issue by annotating the argument with @comptime. ```python @guppy def allocate_qarray2(n: nat @comptime) -> array[qubit, n]: return array(qubit() for _ in range(n)) allocate_qarray2.check(); ``` -------------------------------- ### Measuring qubits using Option arrays Source: https://docs.quantinuum.com/guppy/guppylang/examples/t_factory.html This example shows how to use an array of Option types to selectively measure qubits by swapping them with nothing() and cleaning up the remaining options. ```python n = guppy.nat_var("n") @guppy def measure_mask( qs: array[Option[qubit], n], mask: array[bool, n] @ owned ) -> array[int, n]: """Measure all qubits in `qs` with a corresponding `True` index in `mask`.""" res = array(-1 for _ in range(n)) idx = 0 for m in mask: if m and qs[idx].is_some(): # `take` swaps an optional value with nothing(). q = qs[idx].take() res[idx] = int(measure(q.unwrap())) idx += 1 return res @guppy def main() -> None: qs = array(some(qubit()) for _ in range(3)) mask = array(True, False, True) measure_mask(qs, mask) # We need to consume the array of options at some point, as it can't be leaked. for q_opt in qs: if q_opt.is_some(): q = q_opt.unwrap() discard(q) else: q_opt.unwrap_nothing() main.compile(); ``` -------------------------------- ### run() Source: https://docs.quantinuum.com/guppy/_modules/guppylang/emulator/instance.html Executes the configured emulator instance. ```APIDOC ## run() -> EmulatorResult ### Description Runs the emulator instance and returns the results. By default, it runs one shot, which can be configured via other methods. ``` -------------------------------- ### guppylang.std.iter.range(start, stop, step) Source: https://docs.quantinuum.com/guppy-v1.x/api/generated/guppylang.std.iter.range.html An iterator that yields a sequence of integers starting from 'start' up to 'stop' with a given 'step'. ```APIDOC ## guppylang.std.iter.range(start, stop, step) ### Description An iterator that yields a sequence of integers. The i-th yielded number is start + i * step. Numbers are yielded as long as they are < stop (if step >= 0) or > stop (if step < 0). ### Parameters - **start** (int) - Optional - The starting value of the sequence (defaults to 0). - **stop** (int) - Required - The exclusive upper bound of the sequence. - **step** (int) - Optional - The increment value (defaults to 1). ``` -------------------------------- ### Example output of Bell state circuit Source: https://docs.quantinuum.com/guppy-v1.x/faqs.html The expected output format when running the Bell state circuit example. ```text Counter({(('c', '11'),): 505, (('c', '00'),): 495}) ``` -------------------------------- ### run() Source: https://docs.quantinuum.com/guppy/api/generated/guppylang.emulator.EmulatorInstance.html Executes the configured emulator instance and returns the results. ```APIDOC ## run() ### Description Runs the emulator instance with the current configuration and returns an EmulatorResult object. ### Returns - **EmulatorResult** - The results of the quantum program execution. ``` -------------------------------- ### State Counts Output Source: https://docs.quantinuum.com/guppy/guppylang/examples/state_results.html Example output of the state counts dictionary. ```json {0: 58, 1: 42} ``` -------------------------------- ### Configuration Methods Source: https://docs.quantinuum.com/guppy/api/generated/guppylang.emulator.EmulatorInstance.html Fluent methods for configuring the emulator instance parameters. ```APIDOC ## Configuration Methods - **with_shots(value: int)**: Sets the number of shots to run. - **with_n_qubits(value: int)**: Sets the number of qubits available. - **with_seed(value: int | None)**: Sets the random seed. - **with_error_model(value: ErrorModel)**: Sets the device error model. - **with_timeout(value: datetime.timedelta | None)**: Sets the execution timeout. - **with_n_processes(value: int)**: Sets the number of parallel processes. ``` -------------------------------- ### Importing Guppylang and dependencies Source: https://docs.quantinuum.com/guppy/_downloads/a27643da68ff409a315ec337af493ee9/t_factory.ipynb Initializes the environment with necessary Guppylang modules and simulation tools. ```python import numpy as np from guppylang.decorator import guppy from guppylang.std.angles import angle, pi from guppylang.std.builtins import array, owned, comptime from guppylang.std.option import Option, nothing, some from guppylang.std.debug import state_result from guppylang.std.quantum import ( cz, discard, h, measure, qubit, ry, rz, ) from selene_sim import build, Quest from hugr.qsystem.result import QsysResult np.set_printoptions(precision=4, suppress=True, linewidth=120) ``` -------------------------------- ### range(start[, stop, step]) Source: https://docs.quantinuum.com/guppy/api/generated/guppylang.std.iter.html Creates an iterator that yields a sequence of integers. ```APIDOC ## range(start[, stop, step]) ### Description An iterator that yields a sequence of integers. ### Parameters - **start** (int) - Required - The starting value of the sequence. - **stop** (int) - Optional - The end value of the sequence. - **step** (int) - Optional - The increment value. ``` -------------------------------- ### Create a GuppyLibrary Source: https://docs.quantinuum.com/guppy-v1.x/v1_migration.html Comparison of GuppyLibrary instantiation between version 0.x and 1.0. ```python from guppylang import guppy # Create a GuppyLibrary from # three function definitions lib = guppy.library( first_func, second_func, third_func, ) ``` ```python from guppylang.library import GuppyLibrary # Create a GuppyLibrary from # three function definitions lib = GuppyLibrary.from_members( first_func, second_func, third_func, ) ``` -------------------------------- ### Simulation Results Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/postselect.html Example output from the simulation showing successful and discarded shots. ```text Counter({(('parity', '0'),): 968, (('exit: Postselected: FT prep failed', '1'),): 23, (('parity', '1'),): 9}) ``` -------------------------------- ### Define Main Execution Function Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/6ee65218d0380c03ac1e93fb33e2b9f1/canonical-qpe.ipynb Sets up the main entry point for the QPE program, including state preparation and measurement collection. ```python @guppy def main() -> None: state = prepare_trivial_eigenstate() measured = array(qubit() for _ in range(4)) phase_estimation(measured, state) # state qubits are not measured so have to be explicitly discarded discard_array(state) # Create a result from the measured array output("c", collect_measurements(measure_array(measured))) ``` -------------------------------- ### barrier(*args) Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/std/platform.html Barrier to guarantee that all operations before the barrier are completed before operations after the barrier are started. ```APIDOC ## barrier(*args) ### Description Barrier to guarantee that all operations before the barrier are completed before operations after the barrier are started. ### Parameters - **args** (any) - Optional - Arbitrary inputs to be synchronized. ``` -------------------------------- ### Load and execute a pytket circuit with symbolic parameters Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/guppylang/CHANGELOG.html Demonstrates loading a pytket circuit with symbolic parameters using guppy.load_pytket and executing it within a guppy-decorated function. ```python from guppylang import guppy from guppylang.std.angles import pi from guppylang.std.quantum import qubit, rx, discard from pytket import Circuit from sympy import Symbol a = Symbol("alpha") circ = Circuit(1, 1) circ.Rx(a, 0) circ.Measure(0, 0) rx_func = guppy.load_pytket("rx", circ, use_arrays=False) @guppy def perform_rx_flip() -> int: """Perform an X gate as Rx(q, pi)""" q = qubit() res = int(rx_func(q, pi)) discard(q) return res perform_rx_flip.check() ``` -------------------------------- ### Emulator panic traceback Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/postselect.html Example of the EmulatorError traceback generated when a panic is triggered during simulation. ```text --------------------------------------------------------------------------- EmulatorError Traceback (most recent call last) Cell In[6], line 18 15 data = measure_array(steane_q.data_qs) 16 output("parity", parity_check(collect_measurements(data))) ---> 18 run(main) Cell In[4], line 31, in run(main_def) 24 def run(main_def: GuppyFunctionDefinition) -> Counter: 25 res = ( 26 main_def.emulator(n_qubits=8) 27 .stabilizer_sim() 28 .with_seed(42) 29 .with_shots(1000) 30 .with_error_model(error_model) ---> 31 .run() 32 ) 34 return res.collated_counts() File /app/.venv/lib/python3.12/site-packages/guppylang/emulator/instance.py:264, in EmulatorInstance.run(self, **args) 259 if args: 260 raise EntrypointArgValueError( 261 "This entrypoint takes no runtime arguments, but got: " 262 + ", ".join(f"`{name}`" for name in args) 263 ) --> 264 return self._collect_results(self._run_instance()) 266 validate_record(self._arg_specs, args) 267 provider = ArgProvider() File /app/.venv/lib/python3.12/site-packages/guppylang/emulator/instance.py:327, in EmulatorInstance._collect_results(self, result_stream) 323 shot_results.append(tag, value) 324 except Exception as e: # noqa: BLE001 325 # In this case, casting a wide net on exceptions is 326 # suitable. --> 327 raise EmulatorError( 328 completed_shots=EmulatorResult(all_results), 329 failing_shot=shot_results, 330 underlying_exception=e, 331 ) from None 332 all_results.append(shot_results) 333 return EmulatorResult(all_results) EmulatorError: Panic (#1001): Invalid data index in physical_h ``` -------------------------------- ### Define Main Execution Function Source: https://docs.quantinuum.com/guppy/_downloads/6ee65218d0380c03ac1e93fb33e2b9f1/canonical-qpe.ipynb Sets up the main entry point for the QPE program, including state preparation, measurement, and result registration. ```python @guppy def main() -> None: state = prepare_trivial_eigenstate() measured = array(qubit() for _ in range(4)) phase_estimation(measured, state) # state qubits are not measured so have to be explicitly discarded discard_array(state) # Create a result from the measured array result("c", measure_array(measured)) ``` -------------------------------- ### Initialize and use the platform RNG Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/random.html Demonstrates creating an RNG instance with a seed, generating random integers, and discarding the instance. ```python from guppylang import guppy from guppylang.std.qsystem.random import RNG @guppy def qsystem_rng() -> None: rng = RNG(123) x = rng.random_int() y = rng.random_int_bounded(10) rng.discard() qsystem_rng.check() ``` -------------------------------- ### run(**args) Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/emulator/instance.html Runs the emulator instance with constant runtime arguments. ```APIDOC ### Method `run(**args: ArgValue)` ### Description Run the emulator instance and return the results. By default runs one shot, which can be configured with `with_shots()`. If the entrypoint takes runtime arguments, their values must be passed as keyword arguments. ### Parameters - **args** (Mapping[str, ArgValue]) - Optional - Keyword arguments for the entrypoint. Supported types are bool, signed int, float, and arrays of those types. ``` -------------------------------- ### Postselection in Guppy Source: https://docs.quantinuum.com/guppy/_downloads/b5677b47cb1cb033026c8ab09b0ff336/postselect.ipynb Example of using postselection to discard shots when an error is detected during state preparation. ```python @guppy def main() -> None: steane_q = ft_zero() # Measure the data qubits data = measure_array(steane_q.data_qs) result("parity", parity_check(data)) run(main) ``` -------------------------------- ### Importing required libraries Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/6ee65218d0380c03ac1e93fb33e2b9f1/canonical-qpe.ipynb Initial imports for Guppylang and pytket modules required for the QPE implementation. ```python from guppylang import guppy from guppylang.std.angles import pi from guppylang.std.quantum import qubit, h, crz, x, measure_array, discard_array, collect_measurements from guppylang.std.builtins import output, array from guppylang.std.mem import mem_swap from pytket.circuit import DiagonalBox, QControlBox from pytket.passes import AutoRebase from pytket import OpType import numpy as np ``` -------------------------------- ### Python Type Hinting Example Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/static.html Standard Python function demonstrating optional type annotations. ```python def python_function(x: float) -> str: # float and str are type annotations return f"The value of x is {x}" ``` -------------------------------- ### Prepare states with pytket Source: https://docs.quantinuum.com/guppy/guppylang/examples/swap_test.html Creates a pytket circuit with StatePreparationBox gates for two quantum states. ```python # Define two StatePreparationBox(es) by passing the amplitudes for |S> and |W> as numpy arrays w_state = 1 / np.sqrt(3) * np.array([0, 1, 1, 0, 1, 0, 0, 0]) s_state = 1 / np.sqrt(7) * np.array([0] + [1] * 7) w_state_box = StatePreparationBox(w_state) s_state_box = StatePreparationBox(s_state) # Build a pytket Circuit with 7 qubits pytket_circ = Circuit() ancilla = pytket_circ.add_q_register("a", 1) w_qubits = pytket_circ.add_q_register("w", 3) s_qubits = pytket_circ.add_q_register("s", 3) # Append the state preparation subroutines to the empty circuit pytket_circ.add_gate(w_state_box, list(w_qubits)) pytket_circ.add_gate(s_state_box, list(s_qubits)) ``` ```text [StatePreparationBox s[0], s[1], s[2]; StatePreparationBox w[0], w[1], w[2]; ] ``` -------------------------------- ### guppylang.std.platform.barrier Source: https://docs.quantinuum.com/guppy-v1.x/api/generated/guppylang.std.platform.barrier.html A synchronization primitive used to enforce execution order by ensuring all operations before the barrier complete before those after it start. ```APIDOC ## guppylang.std.platform.barrier(*args) -> None ### Description Barrier to guarantee that all operations before the barrier are completed before operations after the barrier are started. ### Parameters - **args** (variadic) - Optional - Arguments associated with the barrier operation. ``` -------------------------------- ### Array element status output Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/data_types/arrays.html The expected output results from the safe array element management example. ```text [('init', 0), ('after_take', 1), ('after_put', 0)] ``` -------------------------------- ### build(package: Package, n_qubits: int, arg_specs: Sequence[EntrypointArgSpec] = ()) -> EmulatorInstance Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/emulator/builder.html Constructs an EmulatorInstance from a compiled package, specifying qubit allocation and argument schemas. ```APIDOC ### Method `build(package: Package, n_qubits: int, arg_specs: Sequence[EntrypointArgSpec] = ()) -> EmulatorInstance` ### Description Builds an executable EmulatorInstance using the provided compiled HUGR package and configuration settings. ### Parameters - **package** (Package) - The compiled HUGR package to build the emulator from. - **n_qubits** (int) - The number of qubits to allocate for the emulator instance. - **arg_specs** (Sequence[EntrypointArgSpec]) - Optional runtime argument schema for the entrypoint, used for validation. ### Returns - **EmulatorInstance** - An instance ready to execute the compiled program. ``` -------------------------------- ### Importing Guppy and Selene dependencies Source: https://docs.quantinuum.com/guppy/_downloads/3c803f4ffccf99bd6355366e3731e1f9/state_results.ipynb Initializes the environment by importing necessary Guppy modules, Selene simulator components, and configuring NumPy output. ```python from guppylang import guppy from guppylang.std.builtins import array from guppylang.std.debug import state_result from guppylang.std.quantum import qubit, discard, discard_array, cx, h, measure, x from hugr.qsystem.result import QsysResult from selene_sim import build, Quest import numpy as np np.set_printoptions(precision=4, suppress=True, linewidth=120) ``` -------------------------------- ### Guppy Type Inference Failure Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/static.html Example where the compiler cannot infer the type of a variable, requiring an explicit annotation. ```python from guppylang.std.option import nothing @guppy def foo() -> None: q = nothing() q.unwrap_nothing() foo.check() ``` ```text Error: Cannot infer type (at :5:8) | 3 | @guppy 4 | def foo() -> None: 5 | q = nothing() | ^^^^^^^^^ Cannot infer type variables in expression of type | `Option[?T]` Guppy compilation failed due to 1 previous error ``` -------------------------------- ### Define a Guppy Enum Method Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/decorator.html Example of attaching a method to a Guppy enum using the @guppy decorator. ```python @guppy def method_on_enum(self: MyEnum) -> int: return 1 ``` -------------------------------- ### emulator(n_qubits: int | None = None, builder: EmulatorBuilder | None = None, libs: list[Package] | None = None) -> EmulatorInstance Source: https://docs.quantinuum.com/guppy/_modules/guppylang/defs.html Compiles the function for emulation with the selene-sim emulator. It builds the HUGR package using the provided configuration or a default one. ```APIDOC ## emulator(n_qubits, builder, libs) ### Description Compiles the function for emulation with the selene-sim emulator. It calls compile() to get the HUGR package and then builds it using the provided EmulatorBuilder configuration or a default one. ### Parameters - **n_qubits** (int | None) - Optional - The number of qubits to allocate for the function. - **builder** (EmulatorBuilder | None) - Optional - An optional EmulatorBuilder to use for building the emulator instance. - **libs** (list[Package] | None) - Optional - An optional list of additional HUGR packages to link with the compiled function. ### Returns - **EmulatorInstance** - An instance that can be used to run the function in an emulator. ``` -------------------------------- ### Importing necessary modules Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/a27643da68ff409a315ec337af493ee9/t_factory.ipynb Initializes the environment by importing required Guppylang modules and setting NumPy print options. ```python import numpy as np from guppylang.decorator import guppy from guppylang.std.angles import angle, pi from guppylang.std.builtins import array, owned from guppylang.std.option import Option, nothing, some from guppylang.std.debug import state_output from guppylang.std.quantum import ( cz, discard, h, measure, qubit, ry, rz, Measurement, ) from guppylang.std.platform import output from selene_sim import build, Quest from hugr.qsystem.result import QsysResult np.set_printoptions(precision=4, suppress=True, linewidth=120) ``` -------------------------------- ### Initialize graph state builder Source: https://docs.quantinuum.com/guppy/_downloads/4944715cbe6bc65e3f14e3cd5d5343cc/ghz_and_graph.ipynb Starts the definition of a function to build a graph state from a NetworkX graph object. ```python def build_graph_state(graph: nx.Graph) -> GuppyFunctionDefinition: edges = list(graph.edges) ``` -------------------------------- ### Allocate Qubits with Runtime Argument Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/comptime.html This example demonstrates a failure when attempting to allocate an array with a size that is not statically known. ```python from guppylang.std.num import nat @guppy def allocate_qarray1(n: nat) -> array[qubit, n]: return array(qubit() for _ in range(n)) allocate_qarray1.check(); ``` ```text Error: Array comprehension with nonstatic size (at :5:16) | 3 | @guppy 4 | def allocate_qarray1(n: nat) -> array[qubit, n]: 5 | return array(qubit() for _ in range(n)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer the size of this array comprehension ... Note: | 4 | def allocate_qarray1(n: nat) -> array[qubit, n]: 5 | return array(qubit() for _ in range(n)) | -------- since the number of elements yielded by this iterator is not | statically known Guppy compilation failed due to 1 previous error ``` -------------------------------- ### Configure Emulator Instance Settings Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/emulator/instance.html Fluent methods for configuring emulator parameters. These methods return a new instance with the updated configuration. ```python def with_n_qubits(self, value: int) -> Self: """Set the number of qubits available in the emulator instance.""" return replace(self, _n_qubits=value) def with_shots(self, value: int) -> Self: """Set the number of shots to run for each execution. Defaults to 1.""" return self._with_option(_shots=value) def with_simulator(self, value: Simulator) -> Self: """Set the simulation backend used for running the emulator instance. Defaults to statevector simulation.""" return self._with_option(_simulator=value) def with_runtime(self, value: Runtime) -> Self: """Set the runtime used for executing the emulator instance. Defaults to SimpleRuntime.""" return self._with_option(_runtime=value) def with_error_model(self, value: ErrorModel) -> Self: """Set the device error model used for the emulator instance. Defaults to IdealErrorModel (no errors).""" return self._with_option(_error_model=value) def with_event_hook(self, value: EventHook) -> Self: """Set the event hook used for the emulator instance. Defaults to NoEventHook.""" return self._with_option(_event_hook=value) def with_verbose(self, value: bool) -> Self: """Set whether to print verbose output during the emulator execution. Defaults to False.""" return self._with_option(_verbose=value) def with_progress_bar(self, value: bool = True) -> Self: """Set whether to display a progress bar during the emulator execution. Defaults to False.""" return self._with_option(_display_progress_bar=value) def with_timeout(self, value: datetime.timedelta | None) -> Self: """Set the timeout for the emulator execution. Defaults to None (no timeout).""" return self._with_option(_timeout=value) def with_seed(self, value: int | None) -> Self: """Set the random seed for the emulator instance. Defaults to None.""" new_options = replace(self._options, _seed=value) # TODO flaky stateful, remove when selene simplifies new_options._simulator.random_seed = value out = replace(self, _options=new_options) return out def with_shot_offset(self, value: int) -> Self: """Set the offset for the shot numbers, shot counts will begin at this offset. Defaults to 0. This is useful for running multiple emulator instances in parallel.""" return self._with_option(_shot_offset=value) def with_shot_increment(self, value: int) -> Self: """Set the value to increment shot numbers by for each repeated run. Defaults to 1.""" return self._with_option(_shot_increment=value) ``` -------------------------------- ### run Source: https://docs.quantinuum.com/guppy-v1.x/api/generated/guppylang.emulator.EmulatorInstance.html Executes the emulator instance with the provided runtime arguments. By default, it runs one shot, but this can be configured using with_shots(). ```APIDOC ## run(**args) ### Description Runs the emulator instance and returns the results. If the entrypoint takes runtime arguments, their values must be passed as keyword arguments. ### Parameters - **args** (int | float | bool | Sequence[int] | Sequence[float] | Sequence[bool]) - Optional - Runtime arguments for the entrypoint. ### Response - **EmulatorResult** - The result of the emulator execution. ``` -------------------------------- ### Guppy Type Mismatch Error Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/static.html Example of a Guppy function that fails compilation due to a return type mismatch. ```python @guppy def bad_function(x: int) -> int: # Return incorrect type return (x, x) bad_function.check() # Check fails! ``` ```text Error: Type mismatch (at :4:11) | 2 | def bad_function(x: int) -> int: 3 | # Return incorrect type 4 | return (x, x) | ^^^^^^ Expected expression of type `int`, got `(int, int)` Guppy compilation failed due to 1 previous error ``` -------------------------------- ### Run Emulator for Quantum Phase Estimation Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/f4ed911d9c22577717e647f9cdde039a/adaptive-qpe.ipynb Initializes an emulator with two qubits and a fixed seed to execute the quantum phase estimation circuit. ```python emulator = main.emulator(n_qubits=2).with_seed(2) emulator.run() ``` -------------------------------- ### Expected output for Max-Cut distribution Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/qaoa_maxcut_example.html Example output showing the expected energy and probability distribution by cut value. ```text Expected energy from sampled distribution: 5.0995 Probability of optimal colorings: 0.4015 Probability by cut value: cut=1: 0.0005 cut=2: 0.0175 cut=3: 0.0425 cut=4: 0.1625 cut=5: 0.3755 cut=6: 0.4015 ``` -------------------------------- ### Example output of success rate calculation Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/repeat-until-success.html Sample output showing the results of the experimental success rate calculation. ```text Analytic rate: 0.625 ------------------- Shots: 100 ------------------- Average attempts: 1.49 Predicted rate: 0.6711409395973155 ------------------ Shots: 1000 ------------------- Average attempts: 1.545 Predicted rate: 0.6472491909385113 ------------------ Shots: 10000 ------------------ Average attempts: 1.5842 Predicted rate: 0.6312334301224592 ``` -------------------------------- ### GuppyCompilableProgram.compile_entrypoint Source: https://docs.quantinuum.com/guppy-v1.x/api/defs.html Compiles an execution entrypoint to a HUGR package. ```APIDOC ## compile_entrypoint() ### Description Compile an execution entrypoint to a HUGR package. ### Returns - **Package** - The compiled package object. ### Raises - **GuppyError** - If the entrypoint has arguments. ``` -------------------------------- ### Emulator Configuration Methods Source: https://docs.quantinuum.com/guppy/_modules/guppylang/emulator/instance.html Methods to configure the emulator instance settings. ```APIDOC ## Configuration Methods ### with_simulator(value: Simulator) -> Self Sets the simulation backend. Defaults to statevector. ### with_runtime(value: Runtime) -> Self Sets the execution runtime. Defaults to SimpleRuntime. ### with_error_model(value: ErrorModel) -> Self Sets the device error model. Defaults to IdealErrorModel. ### with_event_hook(value: EventHook) -> Self Sets the event hook. Defaults to NoEventHook. ### with_verbose(value: bool) -> Self Sets verbose output. Defaults to False. ### with_progress_bar(value: bool = True) -> Self Sets progress bar display. Defaults to False. ### with_timeout(value: datetime.timedelta | None) -> Self Sets execution timeout. Defaults to None. ### with_seed(value: int | None) -> Self Sets the random seed. ### with_shot_offset(value: int) -> Self Sets the shot number offset. Defaults to 0. ### with_shot_increment(value: int) -> Self Sets the shot increment value. Defaults to 1. ### with_n_processes(value: int) -> Self Sets the number of parallel processes. Defaults to 1. ``` -------------------------------- ### Example state distribution output Source: https://docs.quantinuum.com/guppy-v1.x/api/emulator.html Represents the uniform distribution over basis states returned by the state distribution analysis. ```python [TracedState(probability=0.5, state=array([1.+0.j, 0.+0.j])), TracedState(probability=0.5, state=array([0.+0.j, 1.+0.j]))] ``` -------------------------------- ### Import standard library functions Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/functions.html Standard quantum operations are available via the guppylang.std.quantum module. ```python # Import quantum operation functions from the guppylang standard library from guppylang.std.quantum import measure, h, qubit ``` -------------------------------- ### Panic Function Usage Source: https://docs.quantinuum.com/guppy/_downloads/b5677b47cb1cb033026c8ab09b0ff336/postselect.ipynb Example of using the panic function to raise an error and halt simulation when an invalid index is provided. ```python @guppy def physical_h(q: SteaneQubit, data_idx: int) -> None: if data_idx >= 7: ``` -------------------------------- ### Execute Main Program with Postselection Source: https://docs.quantinuum.com/guppy-v1.x/_downloads/b5677b47cb1cb033026c8ab09b0ff336/postselect.ipynb Defines the main program to verify Steane state preparation using parity checks and executes it. ```python @guppy def main() -> None: steane_q = ft_zero() # Measure the data qubits data = measure_array(steane_q.data_qs) output("parity", parity_check(collect_measurements(data))) run(main) ``` -------------------------------- ### Demonstrate implicit discard leakage error Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/ownership.html An example of a function that fails the Guppy check because an allocated qubit is not consumed or returned. ```python @guppy def implicit_discard() -> None: q = qubit() # Allocated qubit is not consumed h(q) implicit_discard.check() # Check fails :( ``` ```text Error: Drop violation (at :3:4) | 1 | @guppy 2 | def implicit_discard() -> None: 3 | q = qubit() # Allocated qubit is not consumed | ^ Variable `q` with non-droppable type `qubit` is leaked Help: Make sure that `q` is consumed or returned to avoid the leak Guppy compilation failed due to 1 previous error ``` -------------------------------- ### Emulator Configuration and Build Logic Source: https://docs.quantinuum.com/guppy-v1.x/_modules/guppylang/defs.html Internal method for constructing an emulator instance, handling qubit allocation, and linking necessary utility plugins. ```python def _emulator( self, mod: Package, n_qubits: int | None = None, builder: EmulatorBuilder | None = None, libs: list[Package] | None = None, platform: Platform = "helios", ) -> EmulatorInstance: """Build an emulator instance from a compiled package.""" if libs is not None: mod = mod.link(*libs) if builder is None: builder = EmulatorBuilder().with_platform(platform) if arg_specs := self._entrypoint_arg_specs(): from selene_argreader_plugin import ArgReaderPlugin wrap_entrypoint_with_args(mod, [spec.name for spec in arg_specs]) builder = builder.link_utility(ArgReaderPlugin()) qubits = n_qubits if ( isinstance(self.wrapped, RawFunctionDef) and self.wrapped.metadata is not None ): hinted_qubits = self.wrapped.metadata.get_expected_qubits() if qubits is None: qubits = hinted_qubits elif hinted_qubits is not None and qubits < hinted_qubits: raise EmulatorBuildError( ValueError( f"Number of qubits requested ({qubits}) is insufficient to " "cover the maximum number of qubits hinted on the " f"entrypoint ({hinted_qubits})." ) ) if qubits is None: from guppylang.decorator import expected_qubits raise EmulatorBuildError( ValueError( "Number of qubits to be used must be specified, either as an " f"argument to `{self.emulator.__name__}` or hinted on the " "entrypoint function using the decorator " f"`@{expected_qubits.__name__}`." ) ) return builder.build(mod, n_qubits=qubits, arg_specs=arg_specs) ``` -------------------------------- ### Parameterize quantum programs with generics Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/static.html Example of using generics to define a quantum repetition code for an arbitrary number of qubits. ```python from guppylang.std.quantum import qubit, cx, measure_array, Measurement @guppy def rep_code(q: array[qubit, n]) -> array[Measurement, n]: a = array(qubit() for _ in range(n)) for i in range(n - 1): cx(q[i], a[i]) cx(q[i + 1], a[i]) return measure_array(a) rep_code.check() ``` -------------------------------- ### Importing a Qiskit circuit into Guppy Source: https://docs.quantinuum.com/guppy-v1.x/faqs.html Demonstrates converting a Qiskit circuit to pytket and registering it as a Guppy function using guppy.load_pytket. ```python from guppylang import guppy from guppylang.std.quantum import measure_array, collect_measurements from qiskit import QuantumCircuit from pytket.extensions.qiskit.qiskit_convert import qiskit_to_tk # Define a simple Bell state circuit in Qiskit. qc = QuantumCircuit(2) qc.h(0) qc.cx(0, 1) # Convert Qiskit to pytket. pytket_circ = qiskit_to_tk(qc) # Register the pytket Circuit as a Guppy function. bell_func = guppy.load_pytket("circ_func", pytket_circ) # We can now use bell_func as a subroutine in a larger Guppy program. @guppy def main() -> None: qs = array(qubit() for _ in range(2)) bell_func(qs) measurements = measure_array(qs) output("c", collect_measurements(measurements)) sim_result_bell_circuit = ( main.emulator(n_qubits=2).with_seed(4242).with_shots(1000).run() ) print(sim_result_bell_circuit.collated_counts()) ``` -------------------------------- ### Guppy Variable Type Inconsistency Source: https://docs.quantinuum.com/guppy-v1.x/language_guide/static.html Example of a Guppy function that fails because a variable is assigned different types in different branches. ```python @guppy def bad_function(b: bool) -> int: if b: x = 4 else: x = True return int(x) # x has different types depending on b bad_function.check() # Check fails! ``` ```text Error: Different types (at :7:15) | 5 | else: 6 | x = True 7 | return int(x) # x has different types depending on b | ^ Variable `x` may refer to different types Notes: | 3 | if b: 4 | x = 4 | - This is of type `int` 5 | else: 6 | x = True | - This is of type `bool` Guppy compilation failed due to 1 previous error ``` -------------------------------- ### TracedState.__init__ Source: https://docs.quantinuum.com/guppy-v1.x/api/generated/guppylang.emulator.TracedState.html Initializes a new instance of the TracedState class. ```APIDOC ## __init__(probability: float, state: T) ### Description Initializes a new TracedState object with a given probability and state. ### Parameters - **probability** (float) - The probability of this state in the mix. - **state** (T) - The state vector of remaining qubits after tracing out. ``` -------------------------------- ### Define the QPE main function Source: https://docs.quantinuum.com/guppy-v1.x/guppylang/examples/canonical-qpe.html Defines the entry point for the QPE program, including state preparation, phase estimation, and measurement collection. ```guppy @guppy def main() -> None: state = prepare_trivial_eigenstate() measured = array(qubit() for _ in range(4)) phase_estimation(measured, state) # state qubits are not measured so have to be explicitly discarded discard_array(state) # Create a result from the measured array output("c", collect_measurements(measure_array(measured))) ``` -------------------------------- ### Lazy measurement implementation Source: https://docs.quantinuum.com/guppy/_downloads/012ca9e4b50e69c1a1c98f9da4bfc534/deferred_measurement.ipynb An example demonstrating the use of lazy_measure, which may result in compilation errors if not handled correctly with the result function. ```python @guppy @no_type_check def lazy_read(qs: array[qubit, N] @ owned) -> None: for q in qs: result("t", lazy_measure(q)) # [... more quantum operations ...] lazy_read.check() ```