Skip to main content

Haiqu.solve_qubo(problem: QUBO, p: int = 10, initial_state: QuantumCircuit | None = None, alphas: list[float] | None = None, betas: list[float] | None = None, delta: float = 0.5, shots: int = 1000, device: DeviceModel = None, device_id: str = None, options: dict | None = None, use_packing: bool = False, pack_size: int | None = None, compression: bool = False, compression_options: dict | None = None, postprocess_iterations: int = 5, seed: int | None = None, cvar_alpha: float | None = 0.1) → SolverResult

Solve a QUBO optimization problem using Linear Ramp QAOA (LR-QAOA). This high-level method orchestrates the complete LR-QAOA workflow:
  1. Builds LR-QAOA circuit with custom parameter schedules
  2. Optionally compresses the circuit
  3. Executes on specified backend
  4. Post-processes results using Haiqu API
  5. Calculates CVaR expectation
  • Parameters:
    • problem (QUBO) — The QUBO optimization problem to solve.
    • p (int) — Number of QAOA layers. Defaults to 10.
    • initial_state (Optional *[*QuantumCircuit ]) — Custom initial state. Defaults to None (uniform superposition).
    • alphas (Optional *[*list *[*float ] ]) — Cost operator parameters. Defaults to None (linear ramp).
    • betas (Optional *[*list *[*float ] ]) — Mixer operator parameters. Defaults to None (linear ramp).
    • delta (float) — Ramp parameter when alphas/betas not specified. Defaults to 0.5.
    • shots (int) — Number of measurement shots. Defaults to 1000.
    • device (DeviceModel) — Device to execute on. Defaults to None.
    • device_id (str) — Id of the device to execute on. Defaults to None.
    • options (Optional *[*dict ]) — Additional device options.
    • use_packing (bool) — Whether to use circuit packing for efficient device utilization. Defaults to False. Warning: Experimental — packing replicates circuits on unused device qubits to run multiple copies in parallel, which may increase errors for deeper input circuits. For example, a 4-qubit circuit with pack_size=2 and 1000 shots runs two copies in parallel with 500 shots each, yielding 1000 shots of results while only paying for 500 shot executions on the QPU — a 2x cost saving.
    • pack_size (Optional *[*int ]) — Number of circuit copies to pack onto the device. Must be >= 2. Only valid when use_packing=True. If None (default), the backend will pack into at most 2/3 of the device qubits.
    • compression (bool) — Whether to compress the circuit. Defaults to False.
    • compression_options (Optional *[*dict ]) — Compression options dictionary. See method state_compression for details.
    • postprocess_iterations (int) — Maximum number of post-processing passes. Defaults to 5. Controls the number of complete passes through all bits. Higher values may find better local minima but increase runtime. Default of 5 provides good balance between speed and solution quality.
    • seed (Optional *[*int ]) — Random seed for reproducible post-processing results. Defaults to None.
    • cvar_alpha (Optional *[*float ]) — CVaR alpha parameter. None to disable CVaR. Defaults to 0.1.
  • Returns: Complete solution with raw/processed results, costs, and metadata.
  • Return type: SolverResult

NOTE

Bitstrings use Qiskit convention: rightmost bit = qubit 0. Example: “101” means qubit 0=1, qubit 1=0, qubit 2=1.

Examples

Basic usage:
>>> result = haiqu.solve_qubo(problem)
With more post-processing iterations:
>>> result = haiqu.solve_qubo(
...     problem,
...     postprocess_iterations=10,
... )
With custom schedules and compression:
>>> result = haiqu.solve_qubo(
...     problem,
...     p=100,
...     alphas=my_alphas,
...     betas=my_betas,
...     compression=True,
... )
Without CVaR:
>>> result = haiqu.solve_qubo(problem, cvar_alpha=None)

Haiqu.postprocess(counts: dict[str, int | float], problem: QUBO, postprocess_iterations: int = 5, seed: int | None = None) → tuple[dict[str, float], dict[str, int | float]]

Apply post-processing to quantum measurement results using Haiqu API. This method uses the Haiqu API’s optimized postprocessing algorithms to improve quantum optimization results. Requires authentication via login().
  • Parameters:
    • counts — Dictionary mapping bitstrings to their measurement counts or probabilities. Bitstrings must be in Qiskit’s little-endian convention (rightmost bit = qubit 0).
    • problem — The QUBO problem instance.
    • postprocess_iterations — Maximum number of optimization passes. Defaults to 5.
    • seed — Random seed for reproducible results. Defaults to None.
  • Returns:
    • optimized_costs: Dict mapping bitstrings to their costs
    • optimized_counts: Dict mapping bitstrings to aggregated counts
  • Return type: Tuple of (optimized_costs, optimized_counts)

NOTE

Bitstrings use Qiskit convention: rightmost bit = qubit 0. Example: “101” means qubit 0=1, qubit 1=0, qubit 2=1.

Examples

Basic usage:
>>> counts = {"0101": 100, "1010": 50}
>>> costs, opt_counts = haiqu.postprocess(
...     counts=counts,
...     problem=my_qubo
... )
With custom parameters:
>>> costs, opt_counts = haiqu.postprocess(
...     counts=counts,
...     problem=my_qubo,
...     postprocess_iterations=10,
...     seed=42
... )
  • Raises:
    • ValueError — If no API client is available (not logged in).
    • ValidationError — If parameters have incorrect types.

optimization.cvar_expectation(problem: QUBO = None, alpha: float = 1.0, cost_function: Callable[[str], float] | None = None) → float

Calculate Conditional Value at Risk (CVaR) expectation value. This is a utility function for analyzing optimization results.
  • Parameters:
    • counts — Dictionary mapping bitstrings to counts/probabilities. Bitstrings in Qiskit convention (little-endian).
    • problem — The QUBO problem instance. Required if cost_function is not provided.
    • alpha — CVaR parameter (0 < alpha <= 1). Defaults to 1.0 (full expectation).
    • cost_function — Custom cost function. If None, uses problem.cost(). Required if problem is not provided.
  • Returns: CVaR expectation value.
  • Raises: ValueError — If both problem and cost_function are None.

NOTE

Bitstrings use Qiskit convention: rightmost bit = qubit 0.

Examples

Using a QUBO problem:
>>> cvar = cvar_expectation(counts, problem=my_qubo, alpha=0.1)
Using a custom cost function:
>>> def my_cost(bitstring):
...     return sum(int(b) for b in bitstring)
>>> cvar = cvar_expectation(counts, cost_function=my_cost, alpha=0.1)