> ## 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.

# Postprocessing

> Techniques for postprocessing optimization results.

#### Haiqu.solve\_qubo(problem, p=10, initial\_state=None, alphas=None, betas=None, delta=0.5, shots=1000, device=None, device\_id=None, options=None, use\_packing=False, pack\_size=None, compression=False, compression\_options=None, postprocess\_iterations=5, seed=None, cvar\_alpha=0.1)

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*](problem.md#haiqu.sdk.optimization.qubo.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:

```python theme={null}
>>> result = haiqu.solve_qubo(problem)
```

With more post-processing iterations:

```python theme={null}
>>> result = haiqu.solve_qubo(
...     problem,
...     postprocess_iterations=10,
... )
```

With custom schedules and compression:

```python theme={null}
>>> result = haiqu.solve_qubo(
...     problem,
...     p=100,
...     alphas=my_alphas,
...     betas=my_betas,
...     compression=True,
... )
```

Without CVaR:

```python theme={null}
>>> result = haiqu.solve_qubo(problem, cvar_alpha=None)
```

#### Haiqu.postprocess(counts, problem, postprocess\_iterations=5, seed=None)

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** (*dict* \*\[\**str* *,* *int* *|* *float* *]*) -- Dictionary mapping bitstrings to their measurement counts or probabilities.
    Bitstrings must be in Qiskit's little-endian convention (rightmost bit = qubit 0).
  * **problem** ([*QUBO*](problem.md#haiqu.sdk.optimization.qubo.QUBO)) -- The QUBO problem instance.
  * **postprocess\_iterations** (*int*) -- Maximum number of optimization passes. Defaults to 5.
  * **seed** (*int* *|* *None*) -- 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:

```python theme={null}
>>> counts = {"0101": 100, "1010": 50}
>>> costs, opt_counts = haiqu.postprocess(
...     counts=counts,
...     problem=my_qubo
... )
```

With custom parameters:

```python theme={null}
>>> 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.

- **Parameters:**
  * **counts** (*dict* \*\[\**str* *,* *int* *|* *float* *]*)
  * **problem** ([*QUBO*](problem.md#haiqu.sdk.optimization.qubo.QUBO))
  * **postprocess\_iterations** (*int*)
  * **seed** (*int* *|* *None*)
- **Return type:**
  tuple\[dict\[str, float], dict\[str, int | float]]

#### optimization.cvar\_expectation(problem=None, alpha=1.0, cost\_function=None)

Calculate Conditional Value at Risk (CVaR) expectation value.

This is a utility function for analyzing optimization results.

* **Parameters:**
  * **counts** (*Dict* \*\[\**str* *,* *Union* \*\[\**int* *,* *float* *]* *]*) -- Dictionary mapping bitstrings to counts/probabilities.
    Bitstrings in Qiskit convention (little-endian).
  * **problem** ([*QUBO*](problem.md#haiqu.sdk.optimization.qubo.QUBO)) -- The QUBO problem instance. Required if cost\_function is not provided.
  * **alpha** (*float*) -- CVaR parameter (`0 < alpha <= 1`). Defaults to 1.0 (full expectation).
  * **cost\_function** (*Optional* \*\[\**Callable* *\[* \*\[\**str* *]* *,* *float* *]* *]*) -- 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.

* **Return type:**
  float

#### NOTE

Bitstrings use Qiskit convention: rightmost bit = qubit 0.

#### Examples

Using a QUBO problem:

```python theme={null}
>>> cvar = cvar_expectation(counts, problem=my_qubo, alpha=0.1)
```

Using a custom cost function:

```python theme={null}
>>> def my_cost(bitstring):
...     return sum(int(b) for b in bitstring)
>>> cvar = cvar_expectation(counts, cost_function=my_cost, alpha=0.1)
```
