Skip to Content
DocsTutorialsYour First Quantum Script

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 @task and @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 result

When 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 result

Step 4: Submit the Job

  1. In the playground, click “Run as Job” to submit the script for execution via Temporal.
  2. A dialog will appear. Select a backend (use local for free simulation) and click Submit.
  3. 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

Last updated on