Check a QUBO-to-Hamiltonian mapping by hand¶
Translate a two-variable binary objective into a Pauli operator, then check all four basis states. Complete graph problems and Hamiltonians and observables first. Use the installed environment and run from the repository root.
The objective is minimized:
f(x0, x1) = 0.1 − x0 − 0.5 x1 + 1.25 x0 x1
x0, x1 ∈ {0, 1}
The positive quadratic term makes selecting both variables more expensive. It is part of the objective; a generic QUBO does not separately label that choice infeasible. Graph-to-MIS conversion supplies its own constraint interpretation.
Keep the sign convention explicit¶
The classical conversion uses x = (1+s)/2, where s ∈ {−1,+1}. The Pauli projection uses s = −Z. Combining them gives x = (I−Z)/2, so computational 0 has x=0 and 1 has x=1.
Substitution gives:
H = −0.3375 I + 0.1875 Z0 − 0.0625 Z1 + 0.3125 Z0 Z1
The constant affects reported energy even though it does not change which state minimizes it. Here the coefficients are objective values; no conversion to physical rad/us or hardware pulse amplitude has been specified.
"""Project a typed QUBO problem into a Pauli cost Hamiltonian.
The projection keeps variable order, offset, term coefficients, and source
identity explicit. It prepares the cost operator used by QAOA or VQE without
running an optimizer and without claiming a hardware embedding.
"""
from __future__ import annotations
import json
from cascaqit.algorithms import problem_to_pauli_hamiltonian
from cascaqit.problems import QUBOProblemIR, evaluate_qubo_bitstring
def main() -> None:
"""Build one QUBO, project it, and evaluate a known bitstring."""
problem = QUBOProblemIR.from_terms(
problem_id="lesson.optimization.qubo",
variables=("x0", "x1"),
linear_terms={"x0": -1.0, "x1": -0.5},
quadratic_terms={("x0", "x1"): 1.25},
offset=0.1,
)
hamiltonian = problem_to_pauli_hamiltonian(problem)
payload = {
"track": "optimization_researcher",
"level": "foundation",
"lesson": "qubo_hamiltonian",
"facts": {
"variables": list(problem.variables),
"pauli_coefficients": {
term.observable.name: term.coefficient for term in hamiltonian.terms
},
"basis_objectives": {
bits: evaluate_qubo_bitstring(problem, bits)
for bits in ("00", "01", "10", "11")
},
"term_count": len(hamiltonian.terms),
"hamiltonian_offset": hamiltonian.constant,
"candidate_10_value": evaluate_qubo_bitstring(problem, "10"),
"source_hash_present": len(problem.stable_hash()) == 64,
},
"boundaries": {
"hardware_execution": False,
"cloud_execution": False,
"network_accessed": False,
"credentials_loaded": False,
},
}
print(json.dumps(payload, sort_keys=True))
if __name__ == "__main__":
main()
python3 examples/user/tracks/optimization_researcher/02_foundation_qubo_hamiltonian_en.py
{
"boundaries": {
"cloud_execution": false,
"credentials_loaded": false,
"hardware_execution": false,
"network_accessed": false
},
"facts": {
"basis_objectives": {
"00": 0.1,
"01": -0.4,
"10": -0.9,
"11": -0.1499999999999999
},
"candidate_10_value": -0.9,
"hamiltonian_offset": -0.3375,
"pauli_coefficients": {
"Z(x0)": 0.1875,
"Z(x0)*Z(x1)": 0.3125,
"Z(x1)": -0.0625
},
"source_hash_present": true,
"term_count": 3,
"variables": [
"x0",
"x1"
]
},
"lesson": "qubo_hamiltonian",
"level": "foundation",
"track": "optimization_researcher"
}
Read bitstrings in variables order, with the first character representing x0.
| Bitstring | Binary objective | Hamiltonian basis energy |
|---|---|---|
00 |
0.1 | 0.1 |
01 |
−0.4 | −0.4 |
10 |
−0.9 | −0.9 |
11 |
−0.15 | −0.15 |
The minimum is 10. The output exposes all basis objectives and Pauli coefficients, so the mapping can be checked without trusting the optimizer. A source hash identifies the problem used; it does not prove the conversion correct. No optimization, sampling or embedding runs in this lesson.
Change the cost and check the consequence¶
- Increase only the offset from
0.1to0.6. What changes in the table, operator and minimizing bitstring? - Remove the quadratic term. Which bitstring now minimizes the objective?
- Evaluate the
10Hamiltonian energy usingZ0=-1,Z1=+1. Then reverse those signs and identify the bitstring you actually evaluated.
The offset adds 0.5 to every value and to the Hamiltonian constant; the minimum remains 10. Without the pair cost, 11 has value −1.4 and becomes the minimum. With the original operator, 10 has energy −0.9; reversed signs evaluate 01, whose energy is −0.4. Bit ordering and encoding errors can preserve plausible-looking energies while solving the wrong problem.
Continue with QAOA, where the operator becomes a variational cost rather than a table of four known answers.