Fix binary encoding: use ceil(log2(n_k)) qubits per bucket instead of ceil(log2(n_k+1))#55
Draft
Copilot wants to merge 4 commits intoexact-cover-hubofrom
Draft
Fix binary encoding: use ceil(log2(n_k)) qubits per bucket instead of ceil(log2(n_k+1))#55Copilot wants to merge 4 commits intoexact-cover-hubofrom
Copilot wants to merge 4 commits intoexact-cover-hubofrom
Conversation
Co-authored-by: havahol <5363644+havahol@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add BucketExactCover problem class with IO support
Implement BucketExactCover HUBO problem class with IO support
Mar 19, 2026
…ain_hubo.tex Eq. 10 Co-authored-by: havahol <5363644+havahol@users.noreply.github.com>
Copilot
AI
changed the title
Implement BucketExactCover HUBO problem class with IO support
Fix binary encoding: use ceil(log2(n_k)) qubits per bucket instead of ceil(log2(n_k+1))
Mar 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The previous implementation allocated
ceil(log2(n_k + 1))qubits per bucket, implicitly reserving an index for a "null route". Since the problem structure guarantees exactly one route is selected per bucket, the correct formula perdocs/main_hubo.tex§5.2 (Eq. 10) isceil(log2(n_k))— no null slot needed.Core fix
__init__):max(1, ceil(log2(n_k)))— saves 1 qubit for any bucket wheren_kis a power of 2_decode:idx = v % n_k; route = bucket_columns[k][idx]— direct modular map into[0, n_k), no null-route guardcreate_circuit: samev % n_kdecode in bothcost_valsandcov_valsbuild loopsTest updates
For the 7-column test problem (bucket 0: 3 routes, bucket 1: 4 routes):
N_qubits: 4 → was 5 (bucket 1 now needsceil(log2(4))=2qubits, not 3)"0010"(c0+c4),"1001"(c1+c5),"0111"(c2+c6)"0000"decodes to c0+c3 (a real but order-violating route pair), replacing the former all-zeros "null route" which no longer has meaningOriginal prompt
Implement
BucketExactCoverproblem class with IO supportMathematical specification
The full mathematical derivation is in
docs/main_hubo.texon theexact-cover-hubobranch. Read this file carefully before implementing. Key sections:q_m = (1 - Z_m)/2, multi-qubit Z-rotation via CNOT-ladder + RZ)Existing code to read first
qaoa/problems/base_problem.py—Problembase class (inherit from this directly)qaoa/problems/qubo_problem.py—QUBOclass (reference for circuit construction style)qaoa/problems/exactcover_problem.py—ExactCoverclass (the drop-in replacement target; mirror its interface)qaoa/utils/qaoaIO.py— IO infrastructure to extendunittests/test_problems.py— existing test patterns to followNew file:
qaoa/problems/bucketexactcover_problem.pyImplement
class BucketExactCover(Problem).Constructor signature (note:
num_bucketsis required, not optional):Bucket extraction:
columns[:num_buckets, :]is the boat-assignment block.rbelongs to bucketkifcolumns[k, r] == 1.num_bucketsentries).num_bucketsrows) are ignored — they cannot be selected in any feasible solution.self._bucket_columns[k].Binary encoding per bucket:
khasn_k = len(self._bucket_columns[k])columns.b_k = ceil(log2(n_k + 1))qubits (minimum 1 qubit even ifn_k == 1).b_k-bit binary stringzencodes integerv = sum_j 2^j * z_j.idx = v % (n_k + 1). Ifidx == 0→ no column selected (null route). Ifidx ∈ [1, n_k]→ global column indexself._bucket_columns[k][idx - 1]is selected.N_qubits = sum_k b_k. Qubits are laid out bucket-by-bucket: firstb_0qubits for bucket 0, thenb_1for bucket 1, etc.cost(string) -> float:x(length = number of valid columns, indexed in order ofself._valid_columns).-(weights_used @ x + penalty_factor * sum((Y_orders @ x - 1)**2))whereY_orders = columns[num_buckets:, :][:, valid_column_indices].scale_problem=True, weights and penalty are already scaled inself.weightsandself.penalty_factor.ExactCover.cost(): negated (QAOA maximizes).unscaled_cost(string) -> float:cost()but always usesself._original_weightsandself._original_penalty_factor.isFeasible(string) -> bool:x. ReturnTrueiffY_orders @ x == ones(N_orders)(usenp.allclosewithatol=1e-7), or ifself.allow_infeasible.create_circuit():docs/main_hubo.tex). For each bucketkand each function value slot (all2^b_kbinary strings of lengthb_k), evaluate the cost and penalty contributions at that point using the modular wrapping decoding.q_m = (1 - Z_m)/2for each qubit (Eq. 33). Collect Pauli-Z monomials and their coefficientsbeta_T.abs(beta_T) < 1e-10.Tof degreed:d == 0: skip (constant term, no gate needed).d == 1: addRZ(2 * gamma * beta_T, qubit).d > 1: implement using CNOT-ladder + RZ + reverse CNOT-ladder. Specifically: CNOT fromT[0]toT[1], CNOT fromT[1]toT[2], ..., CNOT fromT[d-2]toT[d-1], thenRZ(2 * gamma * beta_T, T[d-1]), then reverse CNOTs.Parameter("x_gamma")forgamma(same name as inQUBO.create_circuit()).|+>^n) and mixer are handled by the QAOA framework.self.circuitand retur...This pull request was created from Copilot chat.
📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.