> ## Documentation Index
> Fetch the complete documentation index at: https://docs.haiqu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Ising

Haiqu's Orchestration Engine Cuts Quantum Cloud Costs for Utility-Scale Quantum Dynamics Simulation by 350×

This notebook demonstrates how to use Haiqu to achieve a 350× cost reduction in quantum cloud computing bill. For concreteness, it uses a utility-scale quantum dynamics simulation of the 2D transverse-field Ising model on 127 qubits ([Nature Article](https://www.nature.com/articles/s41586-023-06096-3)). By leveraging proprietary algorithms and orchestration, Haiqu reduces the quantum processor runtime from 4 hours to under 1 minute and quantum cloud bill from \~\\$10,000 to ~\\$30.

Why the tranverse-field ising model?
Universal behavior: Many physical systems and optimization problems—including scheduling, routing, and other combinatorial tasks—can be mapped onto Ising-type Hamiltonians.
Classically intractable: In the regime where interaction terms compete, quantum dynamics can generate strong entanglement that quickly overwhelms scalable classical simulation methods.

How does Haiqu perform?

At 127 qubits and a two-qubit gate depth of 15
(710 CNOTs), the evolution circuit exceeds the reach of brute-force
classical simulation. Haiqu handles this regime with ease.

Haiqu's runtime engine achieves the same the accuracy as reported by IBM, but at a fraction of the time and cost:
41 seconds (Haiqu) vs. 4 hours (IBM) and
\$33 (Haiqu) versus \$11,520 (IBM) (350× cost reduction).

Having a bug or an issue?

Submit feedback

Initialize the notebook

Import the necessary libraries, setup credentials, initialize the Haiqu SDK, load the device, and show the connectivity map.

```python theme={null}
## Import and Setup
import matplotlib.pyplot as plt
import numpy as np
from qiskit.quantum_info import SparsePauliOp
from haiqu.sdk import haiqu
from utils.utils import make_ising_evolution_circuit, load_json_data, show_device_connectivity

# Load configurations
config = load_json_data("utils/config.json")
device_execution = any(config["device_credentials"].values())

# Initialize Haiqu
haiqu.login(**{k: v for k, v in config["haiqu"].items() if v})
haiqu.init(config["experiment"]["name"])

# Show the device connectivity
device = haiqu.get_device(config["processor"]["name"])
coupling_map = device.coupling_map
show_device_connectivity(coupling_map=coupling_map)

if device_execution:
    print(f"Executing circuits on {device.id}")
else:
    print("Loading existing results from cache")
```

Define the simulation

The transverse-field Ising Hamiltonian

$$
H = H_{\text{int}} + H_{\text{field}}
$$

consists of two terms. The interaction term

$$
H_{\text{int}} = -J \sum_{\langle i,j \rangle} Z_i Z_j ,
$$

couples neighboring spins with strength $J$, favoring alignment along $\hat{z}$. The field term

$$
H_{\text{field}} = h \sum_{i=0}^{N-1} X_i ,
$$

randomizes alignment along $\hat{z}$ by pushing spins towards $\hat{x}$ with a transverse field strength $h$.

Because $H_{\text{int}}$ and $H_{\text{field}}$ do not commute, $H$ cannot be directly mapped onto quantum processors. To address this, the evolution circuit is approximated as a sequence of $m = t/\Delta t$ discrete steps with duration $\Delta t$:

$$
\begin{aligned}
U(t) 
&= e^{-iHt} \\
&= e^{-i (H_{\text{int}} + H_{\text{field}}) t} \\
% &\approx e^{-i H_{\text{field}} \Delta t} \, e^{-i H_{\text{int}} \Delta t}.
&\approx \left(e^{-i H_{\text{field}} \Delta t}\, e^{-i H_{\text{int}} \Delta t}\right)^m.
\end{aligned}
$$

```python theme={null}
# Define the circuit
config["circuit"] = {
    "num_qubits": 127,
    "shots": 10_000,
    "num_steps": 5,
    "transverse_field_params": [[0.0], [0.1], [0.2], [0.3], [0.5], [0.7], [0.8], [1.0], [1.2], [1.3], [1.4], [1.5], [1.5708]]
}
parameterized_circuit = make_ising_evolution_circuit(
    num_qubits=config["circuit"]["num_qubits"], 
    num_steps=config["circuit"]["num_steps"], 
    backend_coupling_map=coupling_map
)
```

The average system magnetization

$M = \frac{1}{N} \sum_{i=0}^{N-1} Z_i$

sums over individual spins on qubit $i$

$$
\begin{aligned}
Z_0 &= Z \otimes I \otimes \cdots \\
Z_1 &= I \otimes Z \otimes I \otimes \cdots \\
Z_2 &= I \otimes I \otimes Z \otimes I \otimes \cdots \\
Z_i &= I \otimes \cdots \otimes Z \otimes \cdots \otimes I.
\end{aligned}
$$

for number of qubits $N$, identity operator $I$, and Pauli-Z operator $Z$.

```python theme={null}
paulis = []
for i in range(config["circuit"]["num_qubits"]):
    pauli_string = ["I"] * config["circuit"]["num_qubits"]
    pauli_string[i] = "Z"
    paulis.append("".join(pauli_string))

coeffs = [1 / config["circuit"]["num_qubits"]] * len(paulis)
list_observables = [SparsePauliOp(paulis, coeffs)]
```

Define and run scenarios

Four scenarios are considered:

1. Ideal - Simulated noise-free baseline results.
2. Noisy - Run on quantum processor without error mitigation.
3. IBM   - Run on quantum processor with IBM error mitigation (Sparse Pauli-Lindblad Noise Learning + ZNE + PEA).
4. Haiqu - Run on quantum processor with Haiqu proprietary error mitigation and orchestration engine.

Results are compared in terms of quality (closeness to ideal) and efficiency (resource utilization).

```python theme={null}
def run_scenario_ideal(config, circuit, observables):
    """
    Scenario 1: Ideal - Results with no noise.
    """
    results = load_json_data(
        f"{config['experiment']['cached_folder']}/ideal.json"
    )

    return {
        "scenario_name": "Ideal",
        "scenario_description": "Results with no noise",
        "magnetization": results[0][0],
        "runtime_minutes": None,
        "runtime_bill": None,
    }


def run_scenario_noisy(config, circuit, observables):
    """
    Scenario 2: Noisy - Raw results from quantum processor without error mitigation.
    """
    if device_execution:
        results = haiqu.run(
            circuit,
            parameters=config["circuit"]["transverse_field_params"],
            observables=observables,
            shots=config["circuit"]["shots"],
            device_id=config["processor"]["name"],
            options=config["device_credentials"],
        ).result()
    else:
        results = load_json_data(f"{config['experiment']['cached_folder']}/noisy.json")["results"]

    runtime_minutes = 38 / 60  # For cached job.

    return {
        "scenario_name": "Noisy",
        "scenario_description": "Raw results from quantum processor without error mitigation",
        "magnetization": results[0][0],
        "runtime_minutes": runtime_minutes,
        "runtime_bill": runtime_minutes * config["processor"]["usd_per_minute"],
    }


def run_scenario_mitigated_ibm(config, circuit, observables):
    """
    Scenario 3: Error Mitigated IBM - Results using IBM's error mitigation methods.
    """
    # Results and runtime from IBM Nature Article: https://www.nature.com/articles/s41586-023-06096-3
    results = load_json_data(f"{config['experiment']['cached_folder']}/ibm.json")
    runtime_minutes = 4 * 60  # See IBM paper.
    
    return {
        "scenario_name": "IBM",
        "scenario_description": (
            "Results using IBM's error mitigation methods "
            "(Sparse Pauli-Lindblad Noise Learning + ZNE)"
        ),
        "magnetization": results[0][0],
        "runtime_minutes": runtime_minutes,
        "runtime_bill": runtime_minutes * config["processor"]["usd_per_minute"],
    }


def run_scenario_mitigated_haiqu(config, circuit, observables):
    """
    Scenario 4: Error Mitigated Haiqu - Results using Haiqu's error mitigation.
    """
    if device_execution:
        results = haiqu.run(
            circuit,
            parameters=config["circuit"]["transverse_field_params"],
            observables=observables,
            shots=config["circuit"]["shots"],
            device_id=config["processor"]["name"],
            options=config["device_credentials"],
            use_mitigation=True,
        ).result()
    else:
        results = load_json_data(f"{config['experiment']['cached_folder']}/haiqu.json")["results"]

    runtime_minutes = 41 / 60  # For cached job.

    return {
        "scenario_name": "Haiqu",
        "scenario_description": "Results using Haiqu's error mitigation",
        "magnetization": results[0][0],
        "runtime_minutes": runtime_minutes,
        "runtime_bill": runtime_minutes * config["processor"]["usd_per_minute"],
    }
```

```python theme={null}
# Run all scenarios and collect results
scenario_ideal = run_scenario_ideal(config, parameterized_circuit, list_observables)
scenario_noisy = run_scenario_noisy(config, parameterized_circuit, list_observables)
scenario_ibm = run_scenario_mitigated_ibm(config, parameterized_circuit, list_observables)
scenario_error_mitigated = run_scenario_mitigated_haiqu(config, parameterized_circuit, list_observables)

# Create summary array with all scenario results
scenarios_summary = [
    scenario_ideal,
    scenario_noisy,
    scenario_ibm,
    scenario_error_mitigated
]

# Display the summary
import pandas as pd
summary_df = pd.DataFrame(scenarios_summary)
summary_df
```

Learn from results

💡 Good to Know: Average magnetization decrease with increasing transverse field strength $h$ as spins are pushed towards $\hat{x}$ and randomized along the measurement axis $\hat{z}$. The solution obtained with Haiqu matches the one obtained by IBM. Both improve quality versus the noisy benchmark.

```python theme={null}
markers = ["x", "o", "s", "d"]
linestyles = [":", "--", "--", "-"]

plt.figure()

for i, scenario in enumerate(scenarios_summary):
    try:
        x = np.asarray(config["circuit"]["transverse_field_params"]).ravel()
        y = np.asarray(scenario["magnetization"]).ravel()
        plt.plot(x, y, label=scenario["scenario_name"], marker=markers[i % len(markers)], linestyle=linestyles[i % len(linestyles)] )
    except Exception:
        print(f"Error plotting {scenario['scenario_name']}")

plt.xlabel("Transverse Field Strength $h$")
plt.ylabel("Magnetization")
plt.legend()
plt.tight_layout()
haiqu.log(plt, name="result")
```

💡 Good to Know: Haiqu's algorithmic and orchestration engine reduces the time to solution from 4h to 41s and the cost of solution from \~\$10,000 to \~\$30 compared to IBM's implementation. This is enabled through the use of proprietary lightweight, high-efficiency error mitigation algorithms and orchestration.

```python theme={null}
labels = []
costs = []

for scenario in scenarios_summary:
    if scenario["runtime_bill"] is not None:
        labels.append(scenario["scenario_name"])
        costs.append(scenario["runtime_bill"])

plt.figure()
plt.bar(labels, costs)
plt.yscale("log")
plt.ylabel("Quantum Cloud Bill ($)")
plt.tight_layout()
haiqu.log(plt, name="performance")
```

Get in Touch

Documentation portal [docs.haiqu.ai](https://docs.haiqu.ai)

Contact Support [feedback.haiqu.ai](https://feedback.haiqu.ai)

Follow Us on LinkedIn latest news on [LinkedIn](https://www.linkedin.com/company/haiquai/)

Visit Our Website Learn more about Haiqu Inc. on [haiqu.ai](https://haiqu.ai)

Business Inquiries Contact us at [info@haiqu.ai](mailto:info@haiqu.ai)
