Skip to content

Phase 1 implementation of DQI - #90

Open
jf-kong wants to merge 4 commits into
mainfrom
dqi
Open

Phase 1 implementation of DQI#90
jf-kong wants to merge 4 commits into
mainfrom
dqi

Conversation

@jf-kong

@jf-kong jf-kong commented May 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a Phase 1 implementation of Decoded Quantum Interferometry (DQI), the non-variational quantum optimisation algorithm of Jordan et al., Optimization by Decoded Quantum Interferometry, arXiv:2408.08292 (v5), Nature 646:831–836 (2025).

DQI takes a max-LIN / max-XOR-SAT instance over GF(2) and produces samples concentrated on near-optimal solutions. This is a fundamentally different paradigm from the QAOA/XQAOA path that the rest of qiboopt is built on, so it lives in a sibling src/qiboopt/dqi/ module rather than as a method on QUBO.

What's added

New package src/qiboopt/dqi/ with:

  • MaxXORSAT (max_xorsat.py) — problem class wrapping (B, s) with helpers for evaluating Hamming distance to the target.
  • optimal_weights (weights.py) — principal eigenvector of the tridiagonal matrix from Theorem 3.4 / Eq. 70 of the paper.
  • weighted_dicke_amplitudes / dicke_circuit (dicke.py) — brute-force amplitude-encoded weighted Dicke superposition on the error register.
  • dqi_circuit (circuit.py) — full m + n qubit DQI circuit following §8.1.2: weighted Dicke prep → Z^{s_i} phasing → CNOT network for B^T y → in-circuit syndrome decoder → Hadamard transform on the solution register.
  • SyndromeDecoder / LUTDecoder / get_decoder (decoders/) — pluggable decoder API, with a brute-force lookup-table decoder as the Phase 1 implementation.
  • DQISolver (solver.py) — end-to-end solver with error-register post-selection on |0^m⟩, plus is_dqi_exact and decoder_success_probability diagnostics that make LUT-collision behaviour observable.
  • Sphinx page at doc/source/api-reference/dqi.rst, registered in the API index.
  • scipy ^1.13 added as a direct dependency (used by the tridiagonal eigenproblem in weights.py).
  • qiboopt.dqi re-exported from the top-level package.

Tests added for circuit construction, decoders, Dicke prep, MaxXORSAT, the weight vector, and end-to-end solver behaviour.

Phase 1 limitations (called out in the docs)

  • Practical only for m + n ≤ 16 on a state-vector simulator.
  • Brute-force Dicke prep materialises a dense 2^m × 2^m unitary and is hard-capped at m = 12. Replacing this with a count-register + Bärtschi–Eidenbenz construction is left to a future phase.
  • No solve_dqi entry point on QUBO; most QUBOs are not faithfully expressible as max-LIN, and we don't want to imply a generic-dense speedup.

Out of scope for this PR

  • Non-LUT decoders (BP, Gauss–Jordan, greedy).
  • Count-register Dicke prep.
  • Noise-model studies.

@jf-kong
jf-kong requested review from a team, mho291 and shangtai May 7, 2026 08:11
@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (9272c82) to head (2612617).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##              main       #90    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            4        13     +9     
  Lines          660       998   +338     
==========================================
+ Hits           660       998   +338     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/qiboopt/__init__.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/__init__.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/circuit.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/decoders/__init__.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/decoders/base.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/decoders/lut.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/dicke.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/max_xorsat.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/solver.py 100.00% <100.00%> (ø)
src/qiboopt/dqi/weights.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@shangtai shangtai linked an issue May 7, 2026 that may be closed by this pull request

@shangtai shangtai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR.

I have left some comments especially for the documentations part.

1. Prepare the weighted Dicke superposition
:math:`\sum_{k=0}^{\ell} w_k \ket{D^m_k}` on the error register, where
:math:`w` is the principal eigenvector of the tridiagonal matrix
:math:`A^{(m, \ell, 0)}` of paper Eq. 70.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:math:`A^{(m, \ell, 0)}` of paper Eq. 70.
:math:`A^{(m, \ell, 0)}` of Eq. 70 in the paper.

decoder-success branches.
5. Apply :math:`H^{\otimes n}` on the solution register.
6. Measure both registers; **post-select** shots whose error register
reads :math:`\ket{0^m}` (paper Fig. 4 caption: "postselect on

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we mention Fig. 4, or section 10.3 on Imperfect decoding?

diagnostics.

**Where DQI helps.** DQI gives a provable polynomial speedup on the Optimal
Polynomial Intersection (OPI) family (Section 6 of arXiv:2408.08292) and

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we include a link to the paper here?


**Phase 1 scope.** Currently implemented: :class:`MaxXORSAT` problem class,
optimal weight vector, weighted Dicke-state preparation, DQI circuit, the
brute-force lookup-table decoder, and end-to-end :class:`DQISolver`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
brute-force lookup-table decoder, and end-to-end :class:`DQISolver`.
brute-force lookup-table (LUT) decoder, and end-to-end :class:`DQISolver`.

- Practical only for ``m + n <= 16`` on a state-vector simulator.
- The brute-force amplitude-encoded Dicke prep materialises a dense
:math:`2^m \times 2^m` unitary and is hard-capped at ``m = 12``.
Replacing this with a count-register + Bartschi-Eidenbenz construction

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we include a reference here?

Comment thread src/qiboopt/dqi/dicke.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we can simplify the code using qibo.models.encodings.dicke_state?


.. math::

A_{k, k+1} = A_{k+1, k} = \sqrt{(k + 1)(m - k)},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our convention is slightly different from the paper, our k+1 is their k. Should we leave a remark?



def test_lut_is_exact_false_when_collisions():
"""The reviewer's example: m=3, n=2, ell=2 with B=[[1,0],[0,1],[1,1]]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""The reviewer's example: m=3, n=2, ell=2 with B=[[1,0],[0,1],[1,1]]
"""For this test, m=3, n=2, ell=2 with B=[[1,0],[0,1],[1,1]]

Comment thread tests/test_dqi_solver.py
"""DQI's post-selected output puts more weight on the brute-force optimum
than uniform sampling would.

The original buggy implementation passed a "best of N shots" test

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these comments from debugging?

Comment thread tests/test_dqi_solver.py


def test_colliding_lut_marks_inexact():
"""Reviewer's example: m=3, n=2, ell=2, B=[[1,0],[0,1],[1,1]] has 7

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment from interacting with Reviewer agent?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimization by Decoded Quantum Interferometry

2 participants