Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
413d13b
Add integration test
abussy-pasqal May 13, 2026
69799d0
Add trivial solve
abussy-pasqal May 13, 2026
005c047
Split embedding
abussy-pasqal May 13, 2026
b3bcf73
Split drive shaping
abussy-pasqal May 13, 2026
d611694
Split quantum solving
abussy-pasqal May 13, 2026
466544f
Split bitflip
abussy-pasqal May 13, 2026
dd43245
Refacto preprocessing
abussy-pasqal Feb 26, 2026
498d912
Split pre-processing
abussy-pasqal May 13, 2026
1c9d9c9
Add transform
abussy-pasqal May 13, 2026
f68eada
Rename methods.
abussy-pasqal May 13, 2026
0651164
Move blade
abussy-pasqal May 14, 2026
1dce092
Move heuristic
abussy-pasqal May 14, 2026
a53f590
Rename fix
abussy-pasqal May 14, 2026
61c1905
Use new code in old
abussy-pasqal May 14, 2026
e39f980
Use new functions
abussy-pasqal May 14, 2026
cd5f219
Split Optimized drive shaper
abussy-pasqal May 15, 2026
4d47147
Fix typing
abussy-pasqal May 15, 2026
2a61fae
Add new optimized
abussy-pasqal May 15, 2026
5da8742
Replace old optimized drive shaping
abussy-pasqal May 15, 2026
cf70b66
Move greedy
abussy-pasqal May 15, 2026
e43c911
Move decompose
abussy-pasqal May 15, 2026
a0d0a90
fixes of Decomposition
abussy-pasqal May 15, 2026
b602c87
Fix tests
abussy-pasqal May 15, 2026
e0394ea
fix more tests
abussy-pasqal May 15, 2026
747311d
Replace None with empty solution
abussy-pasqal May 18, 2026
292ca6c
Try quboinstance derived instance
abussy-pasqal May 19, 2026
2b8ed82
Small fixes
abussy-pasqal May 20, 2026
e8fd6cf
Clean fixations a bit
abussy-pasqal May 20, 2026
62bf85a
Fix naming for variable fixing
abussy-pasqal May 25, 2026
a772e89
Rename transform to transforms
abussy-pasqal May 25, 2026
9398e5a
Reorganize decomposition
abussy-pasqal May 26, 2026
b4b6d0b
Move algorithms to subfolders
abussy-pasqal May 26, 2026
ed7360b
Fix imports
abussy-pasqal May 26, 2026
6d6adb3
Move solve to solvers
abussy-pasqal May 26, 2026
6dcf816
Fix imports
abussy-pasqal May 26, 2026
523c63a
Rename bitflip
abussy-pasqal May 26, 2026
1735172
Rename solvers
abussy-pasqal May 26, 2026
a370b48
Lint
abussy-pasqal May 26, 2026
3fb345f
Add typing module
abussy-pasqal May 27, 2026
ae179ba
Improve typing
abussy-pasqal May 27, 2026
2d167d4
Add more matrix type check
abussy-pasqal May 27, 2026
ee150eb
Improve typing
abussy-pasqal May 27, 2026
315ae56
Fix integration test
abussy-pasqal May 27, 2026
f3a22e3
Migrate cplex
abussy-pasqal May 27, 2026
a47ee36
Complete integration tests
abussy-pasqal May 28, 2026
9e9e73b
Lint
abussy-pasqal May 28, 2026
d3dcf67
Merge post-processed solutions
abussy-pasqal May 28, 2026
c023bed
Migrate tabu_search
abussy-pasqal May 28, 2026
c4b5293
Migrate simulated annealing
abussy-pasqal May 28, 2026
1dd90ff
Add test for sa+tabu
abussy-pasqal May 28, 2026
dc92928
Remove dummy main.py
abussy-pasqal May 28, 2026
79ff4a3
Move files
abussy-pasqal May 28, 2026
10171ae
Start normalize imports
abussy-pasqal May 28, 2026
bc6a384
Keep moving things
abussy-pasqal May 28, 2026
7cdcbf4
More move
abussy-pasqal May 28, 2026
a83c9ab
More moves
abussy-pasqal May 28, 2026
cbc08dd
More moves in tests
abussy-pasqal May 28, 2026
17319b4
Improve linalg typing
abussy-pasqal May 28, 2026
9d9dcb2
cleaning imports
abussy-pasqal May 28, 2026
e6d8a10
Move every submodule to private
abussy-pasqal May 28, 2026
74dd7b1
make more stuff private
abussy-pasqal May 28, 2026
c3acb7b
add tensor.py
abussy-pasqal May 28, 2026
09f82fc
More imports
abussy-pasqal May 28, 2026
8b8d863
promote types to public
abussy-pasqal May 28, 2026
0968945
More import clean
abussy-pasqal May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ repos:
hooks:
- id: mypy
exclude: examples|docs
args: [--always-false=USE_DOUBLE_PRECISION]
additional_dependencies:
- "qoolqit[extras]>=1.1" # The version in pyproject.toml must match
- "jaxtyping"

# Cleanup jupyter notebooks
- repo: https://github.com/srstevenson/nb-clean
Expand Down
4 changes: 2 additions & 2 deletions docs/content/classical/cplex_solver/cplex_solving.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ class CplexSolver(BaseClassicalSolver):
def __init__(
self,
instance: QUBOInstance,
config: Optional[Dict[str, Any]] = None
config: Optional[dict[str, Any]] = None
)
```

- **Parameters**:
- `instance` (`QUBOInstance`): QUBO problem containing a square coefficient matrix (`torch.Tensor`).
- `config` (`Optional[Dict[str, Any]]`): Dictionary supporting:
- `config` (`Optional[dict[str, Any]]`): Dictionary supporting:
- `cplex_maxtime` (`float`, default `600.0`): Maximum solve time in seconds.
- `cplex_log_path` (`str`, default `"solver.log"`): Path for CPLEX log output.

Expand Down
Binary file modified docs/tutorial/greedy_demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ dev = [
"jupyter",
"tqdm",
"mypy",
"jaxtyping",
"beartype",
]
doc = [
"mkdocs",
Expand Down
5 changes: 5 additions & 0 deletions pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"defineConstant": {
"USE_DOUBLE_PRECISION": false
}
}
71 changes: 60 additions & 11 deletions qubosolver/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,65 @@
from __future__ import annotations

from importlib import import_module
from qubosolver.types._checks import _RUNTIME_CHECKS

from .data import * # noqa: F403
from .qubo_instance import * # noqa: F403
from .qubo_types import * # noqa: F403
from .config import * # noqa: F403
from .utils import * # noqa: F403
from qubosolver.types import (
bitstring,
bitstrings,
matrix,
tensor,
vector,
vectori,
Bitstring,
Bitstrings,
Matrix,
Tensor,
Vector,
Vectori,
QUBOSolution,
QUBOAnalyzer,
QUBOInstance,
EmbedderType,
DriveType,
LayoutType,
SolutionStatusType,
DensityType,
)
from qubosolver.config import SolverConfig, EmbeddingConfig, DriveShapingConfig

list_of_submodules = [".data", ".utils", ".qubo_instance", ".config"]
__all__ = [
# Submodules
"bitstring",
"bitstrings",
"matrix",
"tensor",
"vector",
"vectori",
# Type Aliases
"Bitstring",
"Bitstrings",
"Matrix",
"Tensor",
"Vector",
"Vectori",
# Classes
"QUBOSolution",
"QUBOAnalyzer",
"QUBOInstance",
# Enums
"EmbedderType",
"DriveType",
"LayoutType",
"SolutionStatusType",
"DensityType",
# Configs
"SolverConfig",
"EmbeddingConfig",
"DriveShapingConfig",
# Functions
]

__all__ = []
for submodule in list_of_submodules:
__all_submodule__ = getattr(import_module(submodule, package="qubosolver"), "__all__")
__all__ += __all_submodule__
if _RUNTIME_CHECKS:
from beartype import BeartypeConf
from beartype.claw import beartype_this_package

beartype_this_package(conf=BeartypeConf(warning_cls_on_decorator_exception=None))
4 changes: 4 additions & 0 deletions qubosolver/_drive_shaping/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from __future__ import annotations

from qubosolver.drive_shaping import heuristic as heuristic
from qubosolver.drive_shaping import optimized as optimized
103 changes: 103 additions & 0 deletions qubosolver/_drive_shaping/device_specs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from __future__ import annotations

import math
import warnings

import qoolqit


def compare_specs(a: dict, b: dict) -> None:
keys_a = set(a.keys())
keys_b = set(b.keys())

if keys_a != keys_b:
only_in_a = keys_a - keys_b
only_in_b = keys_b - keys_a
if only_in_a:
warnings.warn(f"Keys present in a but missing in b: {only_in_a}")
if only_in_b:
warnings.warn(f"Keys present in b but missing in a: {only_in_b}")

for key in keys_a & keys_b:
v1 = a[key]
v2 = b[key]
if v1 is None or v2 is None:
continue
if not math.isclose(float(v1), float(v2)):
warnings.warn(f"Value mismatch for key '{key}': a={v1}, b={v2}")


def pulser_specs(
device: qoolqit.Device, normalize: bool = False, check_against_qoolqit: bool = False
) -> dict[str, float | None]:
pulser_device = device._device
channel = pulser_device.channels["rydberg_global"]
specs: dict[str, float | None] = {}
specs["max_duration"] = (
float(pulser_device.max_sequence_duration)
if pulser_device.max_sequence_duration is not None
else None
)
specs["max_amplitude"] = channel.max_amp
specs["max_abs_detuning"] = channel.max_abs_detuning
specs["min_distance"] = pulser_device.min_atom_distance
specs["max_radial_distance"] = pulser_device.max_radial_distance
specs["min_avg_amp"] = channel.min_avg_amp
specs["dmm_bottom_detuning"] = None

dmm_channels = list(getattr(pulser_device, "dmm_channels", {}).values())
if dmm_channels:
specs["dmm_bottom_detuning"] = getattr(dmm_channels[0], "bottom_detuning", None)

if not normalize:
return specs

def _normalize(name: str, scale: float) -> None:
if specs[name] is not None:
specs[name] /= scale # type: ignore[operator]

r0 = specs["min_distance"]
assert r0 is not None
_normalize("min_distance", r0)
_normalize("max_radial_distance", r0)

C6 = pulser_device.interaction_coeff
J0 = C6 / (r0**6)

_normalize("max_amplitude", J0)
_normalize("max_abs_detuning", J0)
_normalize("min_avg_amp", J0)
_normalize("dmm_bottom_detuning", J0)

# J0 is in rad/us and t in ns, hence the factor 1000
_normalize("max_duration", 1000.0 / J0)

if check_against_qoolqit:
qq_specs = qoolqit_specs(device)
compare_specs(specs, qq_specs)

return specs


def qoolqit_specs(
device: qoolqit.Device, complete_with_pulser: bool = False, check_against_pulser: bool = False
) -> dict[str, float | None]:
specs = device.specs
_pulser_specs = pulser_specs(device, normalize=True)

def import_from_pulser_or_set(name: str, fallback: float | None = None) -> None:
if name in specs.keys():
return
if complete_with_pulser:
specs[name] = _pulser_specs.get(name, fallback)
else:
specs[name] = fallback

# Don't merge, update specific keys that are known not be in Qoolqit specs
import_from_pulser_or_set("min_avg_amp")
import_from_pulser_or_set("dmm_bottom_detuning")

if check_against_pulser:
compare_specs(specs, _pulser_specs)

return specs
Loading