Your First Quantum Script
This tutorial walks you through writing a Bell State script with Marqov, submitting it as a job, and viewing the results on the execution dashboard.
By the end, you will have:
- Written a two-task quantum workflow using
@taskand@workflow - Submitted it for execution via the Marqov playground
- Inspected the measurement results on the job dashboard
Prerequisites
- A Marqov account with access to the playground at
/run - Basic familiarity with quantum computing concepts (qubits, gates, measurement)
What is a Bell State?
A Bell State is one of the simplest entangled quantum states. It takes two qubits, applies a Hadamard gate to the first qubit and a CNOT gate between them, producing the state:
|Phi+> = (|00> + |11>) / sqrt(2)When you measure this state, you get either 00 or 11 — never 01 or 10. Each outcome appears roughly 50% of the time. This is the hallmark of quantum entanglement.
Step 1: Create the Bell State Circuit
Marqov provides a built-in bell_state() function, but let’s build it from scratch to understand what is happening.
Open the Marqov playground at /run and paste the following code:
from marqov import task, workflow, Circuit
@task
def create_bell_state():
"""Build a Bell State circuit and return it as a dictionary."""
circuit = Circuit()
circuit.h(0) # Apply Hadamard to qubit 0
circuit.cnot(0, 1) # Apply CNOT with qubit 0 as control, qubit 1 as target
return circuit.to_dict()Let’s break this down:
from marqov import task, workflow, Circuit— imports the decorator system and the backend-agnostic circuit builder.Circuit()— creates an empty quantum circuit. No need to declare qubit count upfront; Marqov infers it from the gates you add.circuit.h(0)— applies a Hadamard gate to qubit 0, putting it into a superposition of|0>and|1>.circuit.cnot(0, 1)— applies a CNOT (controlled-NOT) gate with qubit 0 as the control and qubit 1 as the target. If qubit 0 is|1>, qubit 1 gets flipped.circuit.to_dict()— serializes the circuit so it can be passed between tasks. Marqov tasks communicate via JSON-serializable data.
The @task decorator marks this function as a unit of work. When called inside a workflow, it does not execute immediately — instead, it registers itself in the workflow’s dependency graph.
Step 2: Add a Measurement Task
Now add a second task that takes the circuit and simulates it:
@task
def measure_bell_state(circuit_dict):
"""Measure the Bell State circuit and return counts."""
circuit = Circuit.from_dict(circuit_dict)
# Simulate locally with 1000 shots
from marqov import LocalExecutor
executor = LocalExecutor()
import asyncio
result = asyncio.run(executor.execute(circuit, shots=1000))
return {
"counts": result.counts,
"shots": result.shots,
"_summary": {
"State": "Bell State |Phi+>",
"Qubits": "2",
"Shots": "1000",
},
}Key details:
Circuit.from_dict(circuit_dict)— reconstructs the circuit from the serialized dictionary produced by the first task.LocalExecutor— runs the circuit on a local simulator. No cloud resources are used.result.counts— a dictionary mapping measurement outcomes to their counts, for example{"00": 503, "11": 497}._summary— a special key that Marqov extracts and displays as dashboard cards in the job results page. Any key-value pairs you put here appear as labeled cards at the top of the results view.
Step 3: Compose the Workflow
Tie the two tasks together with a @workflow function:
@workflow
def bell_state_experiment():
circuit = create_bell_state()
result = measure_bell_state(circuit)
return resultWhen you call bell_state_experiment(), Marqov does not execute the tasks. Instead, it traces the function and builds a dependency graph:
Level 0: create_bell_state
Level 1: measure_bell_state (depends on create_bell_state)Marqov sees that measure_bell_state takes circuit as input — which is the output of create_bell_state — and automatically creates the dependency edge.
Complete Script
Here is the full script. Paste this into the playground editor:
from marqov import task, workflow, Circuit
@task
def create_bell_state():
"""Build a Bell State circuit."""
circuit = Circuit()
circuit.h(0)
circuit.cnot(0, 1)
return circuit.to_dict()
@task
def measure_bell_state(circuit_dict):
"""Measure the Bell State circuit."""
circuit = Circuit.from_dict(circuit_dict)
from marqov import LocalExecutor
import asyncio
result = asyncio.run(executor.execute(circuit, shots=1000))
return {
"counts": result.counts,
"shots": result.shots,
"_summary": {
"State": "Bell State |Phi+>",
"Qubits": "2",
"Shots": "1000",
},
}
@workflow
def bell_state_experiment():
circuit = create_bell_state()
result = measure_bell_state(circuit)
return resultStep 4: Submit the Job
- In the playground, click “Run as Job” to submit the script for execution via Temporal.
- A dialog will appear. Select a backend (use local for free simulation) and click Submit.
- You will be redirected to the job status page at
/jobs/{id}.
Step 5: View the Results
Once the job completes, the results page shows several sections:
Summary cards — The key-value pairs from your _summary dict appear at the top. You will see cards for “State”, “Qubits”, and “Shots”.
Execution timeline — A Gantt chart showing when each task started and finished. You will see create_bell_state completing first, followed by measure_bell_state.
Task table — A table listing each task with its execution level, status (completed/failed), and duration.
JSON results — The raw result dictionary, which you can copy or download.
View in Temporal — A link to the Temporal UI where you can inspect the underlying workflow execution, including retries and activity details.
Understanding the Results
Your measurement counts should look something like this:
{
"00": 503,
"11": 497
}Both |00> and |11> appear roughly 50% of the time. The states |01> and |10> should never appear (or appear with negligible frequency due to noise on real hardware). This confirms the Bell State entanglement: measuring one qubit immediately determines the other.
Using the Built-in Bell State
Marqov includes a convenience function that creates the same circuit in one line:
from marqov import bell_state
circuit = bell_state() # Equivalent to Circuit().h(0).cnot(0, 1)This is useful when you want to quickly create common circuits without writing out the gate sequence.
Next Steps
- Building a VQE Optimization — learn how to compose multiple parallel tasks for a real quantum chemistry problem
- Running on Real Hardware — switch from local simulation to cloud simulators and QPUs
- Viewing Results — deep dive into the execution dashboard features