qilisdk 0.1.6__tar.gz → 0.1.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. {qilisdk-0.1.6 → qilisdk-0.1.7}/.gitignore +2 -0
  2. qilisdk-0.1.7/.python-version +1 -0
  3. {qilisdk-0.1.6 → qilisdk-0.1.7}/CHANGELOG.md +117 -0
  4. {qilisdk-0.1.6 → qilisdk-0.1.7}/PKG-INFO +74 -24
  5. {qilisdk-0.1.6 → qilisdk-0.1.7}/README.md +61 -15
  6. {qilisdk-0.1.6 → qilisdk-0.1.7}/pyproject.toml +30 -17
  7. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/analog/__init__.py +1 -2
  8. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/analog/hamiltonian.py +1 -68
  9. qilisdk-0.1.7/src/qilisdk/analog/schedule.py +482 -0
  10. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/backends/backend.py +5 -1
  11. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/backends/cuda_backend.py +9 -5
  12. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/backends/qutip_backend.py +23 -12
  13. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/core/__init__.py +4 -0
  14. qilisdk-0.1.7/src/qilisdk/core/interpolator.py +406 -0
  15. qilisdk-0.1.7/src/qilisdk/core/parameterizable.py +131 -0
  16. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/core/variables.py +150 -7
  17. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/digital/circuit.py +1 -0
  18. qilisdk-0.1.7/src/qilisdk/digital/circuit_transpiler.py +46 -0
  19. qilisdk-0.1.7/src/qilisdk/digital/circuit_transpiler_passes/__init__.py +18 -0
  20. qilisdk-0.1.7/src/qilisdk/digital/circuit_transpiler_passes/circuit_transpiler_pass.py +36 -0
  21. qilisdk-0.1.7/src/qilisdk/digital/circuit_transpiler_passes/decompose_multi_controlled_gates_pass.py +216 -0
  22. qilisdk-0.1.7/src/qilisdk/digital/circuit_transpiler_passes/numeric_helpers.py +82 -0
  23. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/digital/gates.py +12 -2
  24. {qilisdk-0.1.6/src/qilisdk/speqtrum → qilisdk-0.1.7/src/qilisdk}/experiments/__init__.py +13 -2
  25. {qilisdk-0.1.6/src/qilisdk/speqtrum → qilisdk-0.1.7/src/qilisdk}/experiments/experiment_functional.py +90 -2
  26. {qilisdk-0.1.6/src/qilisdk/speqtrum → qilisdk-0.1.7/src/qilisdk}/experiments/experiment_result.py +16 -0
  27. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/sampling.py +8 -1
  28. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/time_evolution.py +6 -2
  29. qilisdk-0.1.7/src/qilisdk/functionals/variational_program.py +138 -0
  30. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/speqtrum/speqtrum.py +360 -130
  31. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/speqtrum/speqtrum_models.py +108 -19
  32. qilisdk-0.1.7/src/qilisdk/utils/openfermion/__init__.py +38 -0
  33. qilisdk-0.1.6/src/qilisdk/core/algorithm.py → qilisdk-0.1.7/src/qilisdk/utils/openfermion/__init__.pyi +2 -3
  34. qilisdk-0.1.7/src/qilisdk/utils/openfermion/openfermion.py +45 -0
  35. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/visualization/schedule_renderers.py +16 -8
  36. qilisdk-0.1.7/uv.lock +3563 -0
  37. qilisdk-0.1.6/.python-version +0 -1
  38. qilisdk-0.1.6/src/qilisdk/analog/linear_schedule.py +0 -121
  39. qilisdk-0.1.6/src/qilisdk/analog/schedule.py +0 -507
  40. qilisdk-0.1.6/src/qilisdk/core/parameterizable.py +0 -75
  41. qilisdk-0.1.6/src/qilisdk/functionals/variational_program.py +0 -80
  42. qilisdk-0.1.6/uv.lock +0 -3188
  43. {qilisdk-0.1.6 → qilisdk-0.1.7}/.pre-commit-config.yaml +0 -0
  44. {qilisdk-0.1.6 → qilisdk-0.1.7}/LICENCE +0 -0
  45. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/__init__.py +0 -0
  46. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/__init__.pyi +0 -0
  47. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/_logging.py +0 -0
  48. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/_optionals.py +0 -0
  49. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/analog/exceptions.py +0 -0
  50. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/backends/__init__.py +0 -0
  51. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/backends/__init__.pyi +0 -0
  52. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/core/exceptions.py +0 -0
  53. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/core/model.py +0 -0
  54. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/core/qtensor.py +0 -0
  55. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/core/result.py +0 -0
  56. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/cost_functions/__init__.py +0 -0
  57. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/cost_functions/cost_function.py +0 -0
  58. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/cost_functions/model_cost_function.py +0 -0
  59. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/cost_functions/observable_cost_function.py +0 -0
  60. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/digital/__init__.py +0 -0
  61. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/digital/ansatz.py +0 -0
  62. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/digital/exceptions.py +0 -0
  63. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/__init__.py +0 -0
  64. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/functional.py +0 -0
  65. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/functional_result.py +0 -0
  66. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/sampling_result.py +0 -0
  67. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/time_evolution_result.py +0 -0
  68. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/functionals/variational_program_result.py +0 -0
  69. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/logging_config.yaml +0 -0
  70. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/optimizers/__init__.py +0 -0
  71. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/optimizers/optimizer.py +0 -0
  72. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/optimizers/optimizer_result.py +0 -0
  73. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/optimizers/scipy_optimizer.py +0 -0
  74. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/py.typed +0 -0
  75. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/settings.py +0 -0
  76. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/speqtrum/__init__.py +0 -0
  77. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/speqtrum/__init__.pyi +0 -0
  78. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/speqtrum/keyring.py +0 -0
  79. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/__init__.py +0 -0
  80. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/openqasm2.py +0 -0
  81. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/serialization.py +0 -0
  82. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/visualization/PlusJakartaSans-SemiBold.ttf +0 -0
  83. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/visualization/__init__.py +0 -0
  84. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/visualization/circuit_renderers.py +0 -0
  85. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/visualization/style.py +0 -0
  86. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/utils/visualization/themes.py +0 -0
  87. {qilisdk-0.1.6 → qilisdk-0.1.7}/src/qilisdk/yaml.py +0 -0
@@ -22,3 +22,5 @@ wheels/
22
22
  # Sphinx documentation
23
23
  docs/_build/*
24
24
  docs/code/api/*
25
+ sphinx-verbose.log
26
+ sphinx.log
@@ -0,0 +1 @@
1
+ 3.13
@@ -1,3 +1,120 @@
1
+ # qilisdk 0.1.7 (2025-12-04)
2
+
3
+ ## Features
4
+
5
+ - SpeQtrum's synchronous client now runs every request through a shared HTTPX client that refreshes bearer tokens automatically, ensuring submissions, listings, and polling continue seamlessly after 401s while still applying the SDK user agent. API failures now raise a dedicated SpeQtrum error that includes the message returned by the service and is logged in a human-friendly way, and job detail payloads, logs, and results are decoded defensively so malformed base64 no longer crashes the SDK. ([PR #94](https://github.com/qilimanjaro-tech/qilisdk/pulls/94))
6
+ - Added a ``QiliSDK`` to ``OpenFermion`` converter. This allows to translate ``QubitOperator`` from ``OpenFermion`` to ``QiliSDK``'s ``Hamiltonian`` Objects and vice versa.
7
+
8
+ This optional can be installed using ``pip install qilisdk[openfermion]``.
9
+
10
+ here is an example of the usage:
11
+ ```python
12
+ from openfermion.hamiltonians import jellium_model
13
+ from openfermion.transforms import fourier_transform, jordan_wigner
14
+ from openfermion.utils import Grid
15
+
16
+ from qilisdk.utils.openfermion import openfermion_to_qilisdk, qilisdk_to_openfermion
17
+
18
+ # Let's look at a very small model of jellium in 1D.
19
+ grid = Grid(dimensions=1, length=3, scale=1.0)
20
+ spinless = True
21
+
22
+ # Get the momentum Hamiltonian.
23
+ momentum_hamiltonian = jellium_model(grid, spinless)
24
+ momentum_qubit_operator = jordan_wigner(momentum_hamiltonian)
25
+ momentum_qubit_operator.compress()
26
+
27
+ # Fourier transform the Hamiltonian to the position basis.
28
+ position_hamiltonian = fourier_transform(momentum_hamiltonian, grid, spinless)
29
+ position_qubit_operator = jordan_wigner(position_hamiltonian)
30
+ position_qubit_operator.compress()
31
+
32
+ qilisdk_ham = openfermion_to_qilisdk(position_qubit_operator)
33
+ openfermion_ham = qilisdk_to_openfermion(qilisdk_ham)
34
+ ```
35
+ ([PR #96](https://github.com/qilimanjaro-tech/qilisdk/pulls/96))
36
+ - Raised the SDK baseline to Python 3.11 and aligned the local version file, mypy config, CI tests, docs build, and publishing workflow up to Python 3.13. Linux and Windows installs use customized NumPy and SciPy, linked to Intel's high-performance oneAPI Math Kernel Library (Intel MKL). ([PR #99](https://github.com/qilimanjaro-tech/qilisdk/pulls/99))
37
+ - Constraint-aware execution now threads through sampling, time evolution, variational programs, and optimizer loops, rejecting parameter sets that violate declared constraints; tests and serialization use the new APIs.
38
+
39
+ ```python
40
+ from qilisdk.core import GreaterThanOrEqual, Parameter
41
+ from qilisdk.functionals import Sampling, VariationalProgram
42
+
43
+ # Constrain theta >= phi for a variational run; violations short-circuit the optimizer step.
44
+ theta = Parameter("theta", 0.4, bounds=(0, 1))
45
+ phi = Parameter("phi", 0.3, bounds=(0, 1))
46
+ constraints = [GreaterThanOrEqual(theta, phi)]
47
+
48
+ vp = VariationalProgram(
49
+ functional=Sampling(...),
50
+ optimizer=...,
51
+ cost_function=...,
52
+ parameter_constraints=constraints,
53
+ )
54
+ ```
55
+ ([PR #100](https://github.com/qilimanjaro-tech/qilisdk/pulls/100))
56
+ - Rebuilt analog scheduling around a single, flexible `Schedule`/`Interpolator`: `LinearSchedule` is removed, coefficients can be defined as callables or time intervals with step/linear interpolation, max-time rescaling, shared parameter tracking, and updated visualization/backends.
57
+
58
+ Centralized parameter management in `Parameterizable` so Hamiltonians, circuits, schedules, and gates all inherit consistent parameter getters/setters, constraint checking, and validation; variables add comparison helpers, caching, and math maps.
59
+
60
+ ```python
61
+ from qilisdk.analog import Schedule, X, Z
62
+ from qilisdk.analog.schedule import Interpolation
63
+ from qilisdk.core import Parameter
64
+
65
+ T = 10.0
66
+ schedule = Schedule(
67
+ hamiltonians={"driver": X(0), "problem": Z(0)},
68
+ coefficients={
69
+ # Interval syntax expands to sampled points; callables can reference time directly.
70
+ "driver": {(0, T): lambda t: 1 - t / T},
71
+ "problem": {(0, T): lambda t: t / T},
72
+ },
73
+ dt=0.5,
74
+ interpolation=Interpolation.LINEAR,
75
+ )
76
+ schedule.scale_max_time(Parameter("T_max", 8.0))
77
+ schedule.draw()
78
+ ```
79
+ ([PR #100](https://github.com/qilimanjaro-tech/qilisdk/pulls/100))
80
+ - Introduced the first version of the `CircuitTranspiler` alongside the `DecomposeMultiControlledGatesPass` that decomposes any multi-controlled single-qubit gate, enabling both CUDA and QuTiP backends to execute circuits containing such constructs. The pass is wired directly into both backends today while the full transpiler pipeline is staged for future expansion. ([PR #101](https://github.com/qilimanjaro-tech/qilisdk/pulls/101))
81
+
82
+ ## Bugfixes
83
+
84
+ - Fixed `Schedule.add_hamiltonian` so time-dependent coefficient functions populate every discrete time step.
85
+
86
+ Added regression tests to cover function-driven schedules and validate that only parameters appear in the generated coefficients. ([PR #95](https://github.com/qilimanjaro-tech/qilisdk/pulls/95))
87
+
88
+ ## Improved Documentation
89
+
90
+ - Documentation refresh across the project:
91
+
92
+ - README now links to the hosted docs and the SpeQtrum snippet walks through building a circuit, logging in, picking a device, and submitting a `Sampling` job.
93
+ - Digital fundamentals gained a rendered circuit figure, QuTiP execution example for `HardwareEfficientAnsatz`, a clarified measurement note, and a new “build your own ansatz” walkthrough with code.
94
+ - Analog fundamentals had their operator headings cleaned up, and the shared custom CSS now ships Plus Jakarta Sans, gradient headers, and dark-mode inline-code styling; the circuit diagram image is tracked under `_static/`.
95
+ - The `time_evolution.ipynb` example notebook was stripped of bulky outputs/metadata to keep the repo lightweight.
96
+ - Installation docs call out CUDA GPU requirements and defer hands-on content to a brand-new Quickstart guide (added to the index) that hosts the digital and analog walkthroughs plus backend-specific notes.
97
+ - Backend fundamentals now highlight how to install optional extras and link back to the Installation guide for details.
98
+
99
+ ([PR #97](https://github.com/qilimanjaro-tech/qilisdk/pulls/97))
100
+ - Removed `main` branch from documentation. Sorted tags by descending order. (latest is first) ([PR #104](https://github.com/qilimanjaro-tech/qilisdk/pulls/104))
101
+ - Docs publishing now points the root of the site to the latest release docs and keeps "main" as a clearly labeled development build, with the version picker reorganized into separate Releases and Development sections so visitors land on the most current tag while still finding the dev docs easily. ([PR #109](https://github.com/qilimanjaro-tech/qilisdk/pulls/109))
102
+ - Fixed a display bug in which inline code blocks in headers were invisible. This was due to the previous rule only accounting for "a" elements in headers and not ".pre" span elements. The reason there was a ".pre" block in the header is because of a broken class link, which will be fixed along with others in a different PR. ([PR #114](https://github.com/qilimanjaro-tech/qilisdk/pulls/114))
103
+ - Fixed a number of broken/missing API links in the docs and in general made the docs consistent with the API reference.
104
+
105
+ Also:
106
+ - Remove references to optimize() since it has since been moved into execute()
107
+ - Fixed a broken output box
108
+ - Fixed several lists that weren't displaying correctly
109
+ - Removed an unused import from a code block in core.rst
110
+ - Various other typos, such as missing "a"s before certain terms (keeping consistency with previous uses of said terms)
111
+ - Wrapped some very long lines (as per the style throughout the rest of the files) ([PR #120](https://github.com/qilimanjaro-tech/qilisdk/pulls/120))
112
+
113
+ ## Misc
114
+
115
+ - [PR #104](https://github.com/qilimanjaro-tech/qilisdk/pulls/104), [PR #106](https://github.com/qilimanjaro-tech/qilisdk/pulls/106)
116
+
117
+
1
118
  # qilisdk 0.1.6 (2025-10-31)
2
119
 
3
120
  ## Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qilisdk
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: QiliSDK is a Python framework for writing digital and analog quantum algorithms and executing them across multiple quantum backends. Its modular design streamlines the development process and enables easy integration with a variety of quantum platforms.
5
5
  Project-URL: Homepage, https://github.com/qilimanjaro-tech/qilisdk
6
6
  Project-URL: Documentation, https://qilimanjaro-tech.github.io/qilisdk/
@@ -10,35 +10,39 @@ Project-URL: Changelog, https://github.com/qilimanjaro-tech/qilisdk/blob/main/CH
10
10
  Author-email: Qilimanjaro Quantum Tech <info@qilimanjaro.tech>
11
11
  License-File: LICENCE
12
12
  Keywords: analog quantum computing,digital quantum computing,qilimanjaro,quantum computing
13
- Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Development Status :: 4 - Beta
14
14
  Classifier: Environment :: Console
15
15
  Classifier: Intended Audience :: Developers
16
16
  Classifier: Intended Audience :: Science/Research
17
17
  Classifier: License :: OSI Approved :: Apache Software License
18
18
  Classifier: Operating System :: POSIX :: Linux
19
19
  Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.10
21
20
  Classifier: Programming Language :: Python :: 3.11
22
21
  Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
23
  Classifier: Topic :: Scientific/Engineering
24
24
  Classifier: Topic :: Scientific/Engineering :: Physics
25
25
  Classifier: Topic :: Scientific/Engineering :: Quantum Computing
26
- Requires-Python: >=3.10
26
+ Requires-Python: >=3.11
27
27
  Requires-Dist: dill>=0.3.9
28
28
  Requires-Dist: loguru>=0.7.3
29
29
  Requires-Dist: matplotlib>=3.10.7
30
- Requires-Dist: numpy>=1.26.4
30
+ Requires-Dist: mkl-service>=2.4.2; sys_platform != 'darwin'
31
+ Requires-Dist: numpy>=2.2.0
31
32
  Requires-Dist: pydantic-settings>=2.11.0
32
33
  Requires-Dist: pydantic>=2.12.3
33
34
  Requires-Dist: ruamel-yaml>=0.18.16
34
- Requires-Dist: scipy>=1.15.3
35
+ Requires-Dist: scipy<1.16.3,>=1.15; sys_platform != 'darwin'
36
+ Requires-Dist: scipy>=1.16.3; sys_platform == 'darwin'
35
37
  Provides-Extra: cuda
36
- Requires-Dist: cuda-quantum-cu12==0.12.0.post1; extra == 'cuda'
38
+ Requires-Dist: cuda-quantum-cu12==0.13.0; extra == 'cuda'
39
+ Provides-Extra: openfermion
40
+ Requires-Dist: openfermion>=1.7.1; extra == 'openfermion'
37
41
  Provides-Extra: qutip
38
42
  Requires-Dist: qutip-qip>=0.4.1; extra == 'qutip'
39
- Requires-Dist: qutip>=5.2.1; extra == 'qutip'
43
+ Requires-Dist: qutip>=5.2.2; extra == 'qutip'
40
44
  Provides-Extra: speqtrum
41
- Requires-Dist: httpx>=0.28.1; extra == 'speqtrum'
45
+ Requires-Dist: httpx==0.28.1; extra == 'speqtrum'
42
46
  Requires-Dist: keyring>=25.6.0; extra == 'speqtrum'
43
47
  Requires-Dist: keyrings-alt>=5.0.2; extra == 'speqtrum'
44
48
  Description-Content-Type: text/markdown
@@ -48,6 +52,7 @@ Description-Content-Type: text/markdown
48
52
  [![Python Versions](https://img.shields.io/pypi/pyversions/qilisdk.svg)](https://pypi.org/project/qilisdk/)
49
53
  [![PyPI Version](https://img.shields.io/pypi/v/qilisdk.svg)](https://pypi.org/project/qilisdk/)
50
54
  [![License](https://img.shields.io/pypi/l/qilisdk.svg)](#license)
55
+ [![Docs](https://img.shields.io/badge/docs-latest-pink.svg)](https://qilimanjaro-tech.github.io/qilisdk/main/index.html)
51
56
 
52
57
  **QiliSDK** is a Python framework for writing digital and analog quantum algorithms and executing them across multiple quantum backends. Its modular design streamlines the development process and enables easy integration with a variety of quantum platforms.
53
58
 
@@ -202,18 +207,27 @@ print("Optimal Parameters:", result.optimal_parameters)
202
207
  QiliSDK includes a client for interacting with Qilimanjaro's SpeQtrum platform. This module supports secure login and a unified interface for both digital circuits and analog evolutions:
203
208
 
204
209
  ```python
205
- from qilisdk.speqtrum import SpeQtrum
210
+ from qilisdk.backends import CudaBackend, CudaSamplingMethod
211
+ from qilisdk.digital import Circuit, H, M
206
212
  from qilisdk.functionals import Sampling
213
+ from qilisdk.speqtrum import SpeQtrum
214
+
215
+
216
+ # Build a single-qubit circuit
217
+ circuit = Circuit(nqubits=1)
218
+ circuit.add(H(0))
219
+ circuit.add(M(0))
207
220
 
208
221
  # Login to QaaSBackend with credentials (or use environment variables)
209
222
  # This only needs to be run once.
210
- SpeQtrum.login(username="your_username", apikey="your_apikey")
223
+ SpeQtrum.login(username="YOUR_USERNAME", apikey="YOUR_APIKEY")
211
224
 
212
225
  # Instantiate QaaSBackend
213
226
  client = SpeQtrum()
214
227
 
215
- # # Execute a pre-built circuit (see Digital Quantum Circuits section)
216
- job_id = client.submit(Sampling(circuit, 1000), device="cuda_state_vector")
228
+ # Execute a pre-built circuit (see Digital Quantum Circuits section)
229
+ # make sure to select the device (you can list available devices using ``client.list_devices()``)
230
+ job_id = client.submit(Sampling(circuit, 1000), device="SELECTED_DEVICE")
217
231
  print("job id:", job_id)
218
232
  print("job status:", client.get_job(job_id).status)
219
233
  print("job result:", client.get_job(job_id).result)
@@ -241,18 +255,17 @@ print("CUDA Backend Results:", results)
241
255
 
242
256
  ### Time Evolution using Qutip
243
257
 
244
- For analog simulations, the new `TimeEvolution` and `Schedule` classes allow you to simulate time-dependent quantum dynamics. The following example uses a linear schedule to interpolate between two Hamiltonians on a Qutip backend:
258
+ For analog simulations, the `TimeEvolution` and unified `Schedule` classes allow you to simulate time-dependent quantum dynamics. The following example uses callable coefficients defined over an interval to interpolate between two Hamiltonians on a Qutip backend:
245
259
 
246
260
  ```python
247
- import numpy as np
248
261
  from qilisdk.analog import Schedule, X, Z, Y
249
262
  from qilisdk.core import ket, tensor_prod
250
263
  from qilisdk.backends import QutipBackend
251
264
  from qilisdk.functionals import TimeEvolution
252
265
 
253
266
  # Define total time and timestep
254
- T = 100
255
- steps = np.linspace(0, T, T)
267
+ T = 100.0
268
+ dt = 0.1
256
269
  nqubits = 1
257
270
 
258
271
  # Define Hamiltonians
@@ -260,13 +273,14 @@ Hx = sum(X(i) for i in range(nqubits))
260
273
  Hz = sum(Z(i) for i in range(nqubits))
261
274
 
262
275
  # Build a time‑dependent schedule
263
- schedule = Schedule(T)
264
-
265
- # Add hx with a time‐dependent coefficient function
266
- schedule.add_hamiltonian(label="hx", hamiltonian=Hx, schedule=lambda t: 1 - steps[t] / T)
267
-
268
- # Add hz similarly
269
- schedule.add_hamiltonian(label="hz", hamiltonian=Hz, schedule=lambda t: steps[t] / T)
276
+ schedule = Schedule(
277
+ hamiltonians={"hx": Hx, "hz": Hz},
278
+ coefficients={
279
+ "hx": {(0.0, T): lambda t: 1 - t / T},
280
+ "hz": {(0.0, T): lambda t: t / T},
281
+ },
282
+ dt=dt,
283
+ )
270
284
 
271
285
  # draw the schedule
272
286
  schedule.draw()
@@ -418,6 +432,42 @@ print("Reconstructed Circuit:")
418
432
  restored_circuit.draw()
419
433
  ```
420
434
 
435
+ ### OpenFermion Integration
436
+
437
+ `QiliSDK` can translate ``QubitOperator`` objects from ``OpenFermion`` to ``QiliSDK``'s ``Hamiltonian`` Objects and vice versa.
438
+
439
+ This code is available under an optional dependency that can be installed using ``pip install qilisdk[openfermion]``.
440
+
441
+ here is an example of the usage:
442
+ ```python
443
+ from openfermion.hamiltonians import jellium_model
444
+ from openfermion.transforms import fourier_transform, jordan_wigner
445
+ from openfermion.utils import Grid
446
+
447
+ from qilisdk.utils.openfermion import openfermion_to_qilisdk, qilisdk_to_openfermion
448
+
449
+ # Let's look at a very small model of jellium in 1D.
450
+ grid = Grid(dimensions=1, length=3, scale=1.0)
451
+ spinless = True
452
+
453
+ # Get the momentum Hamiltonian.
454
+ momentum_hamiltonian = jellium_model(grid, spinless)
455
+ momentum_qubit_operator = jordan_wigner(momentum_hamiltonian)
456
+ momentum_qubit_operator.compress()
457
+
458
+ # Fourier transform the Hamiltonian to the position basis.
459
+ position_hamiltonian = fourier_transform(momentum_hamiltonian, grid, spinless)
460
+ position_qubit_operator = jordan_wigner(position_hamiltonian)
461
+ position_qubit_operator.compress()
462
+
463
+ qilisdk_ham = openfermion_to_qilisdk(position_qubit_operator)
464
+ openfermion_ham = qilisdk_to_openfermion(qilisdk_ham)
465
+
466
+ ```
467
+
468
+
469
+
470
+
421
471
  ---
422
472
 
423
473
  ## Development
@@ -3,6 +3,7 @@
3
3
  [![Python Versions](https://img.shields.io/pypi/pyversions/qilisdk.svg)](https://pypi.org/project/qilisdk/)
4
4
  [![PyPI Version](https://img.shields.io/pypi/v/qilisdk.svg)](https://pypi.org/project/qilisdk/)
5
5
  [![License](https://img.shields.io/pypi/l/qilisdk.svg)](#license)
6
+ [![Docs](https://img.shields.io/badge/docs-latest-pink.svg)](https://qilimanjaro-tech.github.io/qilisdk/main/index.html)
6
7
 
7
8
  **QiliSDK** is a Python framework for writing digital and analog quantum algorithms and executing them across multiple quantum backends. Its modular design streamlines the development process and enables easy integration with a variety of quantum platforms.
8
9
 
@@ -157,18 +158,27 @@ print("Optimal Parameters:", result.optimal_parameters)
157
158
  QiliSDK includes a client for interacting with Qilimanjaro's SpeQtrum platform. This module supports secure login and a unified interface for both digital circuits and analog evolutions:
158
159
 
159
160
  ```python
160
- from qilisdk.speqtrum import SpeQtrum
161
+ from qilisdk.backends import CudaBackend, CudaSamplingMethod
162
+ from qilisdk.digital import Circuit, H, M
161
163
  from qilisdk.functionals import Sampling
164
+ from qilisdk.speqtrum import SpeQtrum
165
+
166
+
167
+ # Build a single-qubit circuit
168
+ circuit = Circuit(nqubits=1)
169
+ circuit.add(H(0))
170
+ circuit.add(M(0))
162
171
 
163
172
  # Login to QaaSBackend with credentials (or use environment variables)
164
173
  # This only needs to be run once.
165
- SpeQtrum.login(username="your_username", apikey="your_apikey")
174
+ SpeQtrum.login(username="YOUR_USERNAME", apikey="YOUR_APIKEY")
166
175
 
167
176
  # Instantiate QaaSBackend
168
177
  client = SpeQtrum()
169
178
 
170
- # # Execute a pre-built circuit (see Digital Quantum Circuits section)
171
- job_id = client.submit(Sampling(circuit, 1000), device="cuda_state_vector")
179
+ # Execute a pre-built circuit (see Digital Quantum Circuits section)
180
+ # make sure to select the device (you can list available devices using ``client.list_devices()``)
181
+ job_id = client.submit(Sampling(circuit, 1000), device="SELECTED_DEVICE")
172
182
  print("job id:", job_id)
173
183
  print("job status:", client.get_job(job_id).status)
174
184
  print("job result:", client.get_job(job_id).result)
@@ -196,18 +206,17 @@ print("CUDA Backend Results:", results)
196
206
 
197
207
  ### Time Evolution using Qutip
198
208
 
199
- For analog simulations, the new `TimeEvolution` and `Schedule` classes allow you to simulate time-dependent quantum dynamics. The following example uses a linear schedule to interpolate between two Hamiltonians on a Qutip backend:
209
+ For analog simulations, the `TimeEvolution` and unified `Schedule` classes allow you to simulate time-dependent quantum dynamics. The following example uses callable coefficients defined over an interval to interpolate between two Hamiltonians on a Qutip backend:
200
210
 
201
211
  ```python
202
- import numpy as np
203
212
  from qilisdk.analog import Schedule, X, Z, Y
204
213
  from qilisdk.core import ket, tensor_prod
205
214
  from qilisdk.backends import QutipBackend
206
215
  from qilisdk.functionals import TimeEvolution
207
216
 
208
217
  # Define total time and timestep
209
- T = 100
210
- steps = np.linspace(0, T, T)
218
+ T = 100.0
219
+ dt = 0.1
211
220
  nqubits = 1
212
221
 
213
222
  # Define Hamiltonians
@@ -215,13 +224,14 @@ Hx = sum(X(i) for i in range(nqubits))
215
224
  Hz = sum(Z(i) for i in range(nqubits))
216
225
 
217
226
  # Build a time‑dependent schedule
218
- schedule = Schedule(T)
219
-
220
- # Add hx with a time‐dependent coefficient function
221
- schedule.add_hamiltonian(label="hx", hamiltonian=Hx, schedule=lambda t: 1 - steps[t] / T)
222
-
223
- # Add hz similarly
224
- schedule.add_hamiltonian(label="hz", hamiltonian=Hz, schedule=lambda t: steps[t] / T)
227
+ schedule = Schedule(
228
+ hamiltonians={"hx": Hx, "hz": Hz},
229
+ coefficients={
230
+ "hx": {(0.0, T): lambda t: 1 - t / T},
231
+ "hz": {(0.0, T): lambda t: t / T},
232
+ },
233
+ dt=dt,
234
+ )
225
235
 
226
236
  # draw the schedule
227
237
  schedule.draw()
@@ -373,6 +383,42 @@ print("Reconstructed Circuit:")
373
383
  restored_circuit.draw()
374
384
  ```
375
385
 
386
+ ### OpenFermion Integration
387
+
388
+ `QiliSDK` can translate ``QubitOperator`` objects from ``OpenFermion`` to ``QiliSDK``'s ``Hamiltonian`` Objects and vice versa.
389
+
390
+ This code is available under an optional dependency that can be installed using ``pip install qilisdk[openfermion]``.
391
+
392
+ here is an example of the usage:
393
+ ```python
394
+ from openfermion.hamiltonians import jellium_model
395
+ from openfermion.transforms import fourier_transform, jordan_wigner
396
+ from openfermion.utils import Grid
397
+
398
+ from qilisdk.utils.openfermion import openfermion_to_qilisdk, qilisdk_to_openfermion
399
+
400
+ # Let's look at a very small model of jellium in 1D.
401
+ grid = Grid(dimensions=1, length=3, scale=1.0)
402
+ spinless = True
403
+
404
+ # Get the momentum Hamiltonian.
405
+ momentum_hamiltonian = jellium_model(grid, spinless)
406
+ momentum_qubit_operator = jordan_wigner(momentum_hamiltonian)
407
+ momentum_qubit_operator.compress()
408
+
409
+ # Fourier transform the Hamiltonian to the position basis.
410
+ position_hamiltonian = fourier_transform(momentum_hamiltonian, grid, spinless)
411
+ position_qubit_operator = jordan_wigner(position_hamiltonian)
412
+ position_qubit_operator.compress()
413
+
414
+ qilisdk_ham = openfermion_to_qilisdk(position_qubit_operator)
415
+ openfermion_ham = qilisdk_to_openfermion(qilisdk_ham)
416
+
417
+ ```
418
+
419
+
420
+
421
+
376
422
  ---
377
423
 
378
424
  ## Development
@@ -1,14 +1,14 @@
1
1
  [project]
2
2
  name = "qilisdk"
3
- version = "0.1.6"
3
+ version = "0.1.7"
4
4
  description = "QiliSDK is a Python framework for writing digital and analog quantum algorithms and executing them across multiple quantum backends. Its modular design streamlines the development process and enables easy integration with a variety of quantum platforms."
5
5
  readme = "README.md"
6
6
  authors = [{name = "Qilimanjaro Quantum Tech", email = "info@qilimanjaro.tech"}]
7
- requires-python = ">=3.10"
7
+ requires-python = ">=3.11"
8
8
  keywords = ["qilimanjaro", "quantum computing", "digital quantum computing", "analog quantum computing"]
9
9
  urls = { "Homepage" = "https://github.com/qilimanjaro-tech/qilisdk", "Documentation" = "https://qilimanjaro-tech.github.io/qilisdk/", "Source" = "https://github.com/qilimanjaro-tech/qilisdk", "Issues" = "https://github.com/qilimanjaro-tech/qilisdk/issues", "Changelog" = "https://github.com/qilimanjaro-tech/qilisdk/blob/main/CHANGELOG.md" }
10
10
  classifiers = [
11
- "Development Status :: 3 - Alpha",
11
+ "Development Status :: 4 - Beta",
12
12
  "Environment :: Console",
13
13
  "Operating System :: POSIX :: Linux",
14
14
  "License :: OSI Approved :: Apache Software License",
@@ -18,49 +18,55 @@ classifiers = [
18
18
  "Intended Audience :: Developers",
19
19
  "Intended Audience :: Science/Research",
20
20
  "Programming Language :: Python :: 3",
21
- "Programming Language :: Python :: 3.10",
22
21
  "Programming Language :: Python :: 3.11",
23
22
  "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
24
  ]
25
25
  dependencies = [
26
26
  "dill>=0.3.9",
27
- "numpy>=1.26.4",
27
+ "numpy>=2.2.0",
28
28
  "ruamel-yaml>=0.18.16",
29
- "scipy>=1.15.3",
29
+ "scipy>=1.16.3; sys_platform == 'darwin'",
30
+ "scipy>=1.15,<1.16.3; sys_platform != 'darwin'",
30
31
  "pydantic>=2.12.3",
31
32
  "pydantic-settings>=2.11.0",
32
33
  "loguru>=0.7.3",
33
34
  "matplotlib>=3.10.7",
35
+ "mkl-service>=2.4.2; sys_platform != 'darwin'",
34
36
  ]
35
37
 
36
38
  [project.optional-dependencies]
37
39
  cuda = [
38
- "cuda-quantum-cu12==0.12.0.post1",
40
+ "cuda-quantum-cu12==0.13.0",
39
41
  ]
40
42
  speqtrum = [
41
- "httpx>=0.28.1",
43
+ "httpx==0.28.1",
42
44
  "keyring>=25.6.0",
43
45
  "keyrings-alt>=5.0.2",
44
46
  ]
45
47
  qutip = [
46
- "qutip>=5.2.1",
48
+ "qutip>=5.2.2",
47
49
  "qutip-qip>=0.4.1",
48
50
  ]
51
+ openfermion = [
52
+ "openfermion>=1.7.1",
53
+ ]
49
54
 
50
55
  [dependency-groups]
51
56
  dev = [
52
- "hypothesis>=6.142.3",
53
- "ipykernel>=7.0.1",
57
+ "hypothesis>=6.147.0",
58
+ "ipykernel>=7.1.0",
54
59
  "mypy>=1.18.2",
55
60
  "pre-commit>=4.3.0",
56
61
  "pytest>=8.4.2",
57
62
  "pytest-sugar>=1.1.1",
58
- "ruff>=0.14.2",
63
+ "ruff>=0.14.6",
59
64
  "towncrier>=25.8.0",
60
65
  "loguru-caplog>=0.2.0",
61
66
  "pytest-cov>=7.0.0",
62
67
  ]
63
68
  docs = [
69
+ "astroid<3.2",
64
70
  "nbsphinx>=0.9.7",
65
71
  "pypandoc>=1.15",
66
72
  "sphinx>=8.1.3",
@@ -72,6 +78,17 @@ docs = [
72
78
  "sphinxawesome-theme>=5.3.2",
73
79
  ]
74
80
 
81
+ [tool.uv.sources]
82
+ sphinx-multiversion = { git = "https://github.com/sphinx-contrib/multiversion", branch = "main"}
83
+ numpy = [{ index = "numpy-mkl", marker = "sys_platform != 'darwin'" }]
84
+ scipy = [{ index = "numpy-mkl", marker = "sys_platform != 'darwin'" }]
85
+ mkl-service = [{ index = "numpy-mkl", marker = "sys_platform != 'darwin'" }]
86
+
87
+ [[tool.uv.index]]
88
+ name = "numpy-mkl"
89
+ url = "https://urob.github.io/numpy-mkl"
90
+ explicit = true
91
+
75
92
  [build-system]
76
93
  requires = ["hatchling"]
77
94
  build-backend = "hatchling.build"
@@ -94,10 +111,6 @@ exclude = [
94
111
  [tool.hatch.build.targets.wheel]
95
112
  packages = ["src/qilisdk"]
96
113
 
97
- [tool.uv.sources]
98
- cudaq = { git = "https://github.com/NVIDIA/cuda-quantum", tag = "0.11.0"}
99
- sphinx-multiversion = { git = "https://github.com/sphinx-contrib/multiversion", branch = "main"}
100
-
101
114
  [tool.ruff]
102
115
  line-length = 120
103
116
  output-format = "concise"
@@ -193,7 +206,7 @@ docstring-code-format = true
193
206
  docstring-code-line-length = "dynamic"
194
207
 
195
208
  [tool.mypy]
196
- python_version = "3.10"
209
+ python_version = "3.13"
197
210
  ignore_missing_imports = true
198
211
  exclude = ["\\.ipynb$"]
199
212
 
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from .hamiltonian import Hamiltonian, I, PauliI, PauliX, PauliY, PauliZ, X, Y, Z
16
- from .linear_schedule import LinearSchedule
17
16
  from .schedule import Schedule
18
17
 
19
- __all__ = ["Hamiltonian", "I", "LinearSchedule", "PauliI", "PauliX", "PauliY", "PauliZ", "Schedule", "X", "Y", "Z"]
18
+ __all__ = ["Hamiltonian", "I", "PauliI", "PauliX", "PauliY", "PauliZ", "Schedule", "X", "Y", "Z"]
@@ -256,6 +256,7 @@ class Hamiltonian(Parameterizable):
256
256
  Raises:
257
257
  ValueError: If the provided coefficients include generic variables instead of parameters.
258
258
  """
259
+ super(Hamiltonian, self).__init__()
259
260
  self._elements: dict[tuple[PauliOperator, ...], complex | Term | Parameter] = defaultdict(complex)
260
261
  self._parameters: dict[str, Parameter] = {}
261
262
  if elements:
@@ -294,79 +295,11 @@ class Hamiltonian(Parameterizable):
294
295
  for k, v in self._elements.items()
295
296
  }
296
297
 
297
- @property
298
- def nparameters(self) -> int:
299
- """Return the number of unique symbolic parameters contained in the Hamiltonian."""
300
- return len(self._parameters)
301
-
302
298
  @property
303
299
  def parameters(self) -> dict[str, Parameter]:
304
300
  """Return a mapping from parameter labels to their corresponding parameter objects."""
305
301
  return self._parameters
306
302
 
307
- def get_parameter_values(self) -> list[float]:
308
- """Return the current numeric values of the Hamiltonian parameters."""
309
- return [param.value for param in self._parameters.values()]
310
-
311
- def get_parameter_names(self) -> list[str]:
312
- """Return the ordered list of parameter labels defined in the Hamiltonian."""
313
- return list(self._parameters.keys())
314
-
315
- def get_parameters(self) -> dict[str, float]:
316
- """Return a mapping from parameter labels to their current numerical values."""
317
- return {label: param.value for label, param in self._parameters.items()}
318
-
319
- def set_parameter_values(self, values: list[float]) -> None:
320
- """
321
- Update the numerical values of the Hamiltonian parameters.
322
-
323
- Args:
324
- values (list[float]): New values ordered according to ``get_parameter_names()``.
325
-
326
- Raises:
327
- ValueError: If the number of provided values does not match ``nparameters``.
328
- """
329
- if len(values) != self.nparameters:
330
- raise ValueError(f"Provided {len(values)} but Hamiltonian has {self.nparameters} parameters.")
331
- for i, parameter in enumerate(self._parameters.values()):
332
- parameter.set_value(values[i])
333
-
334
- def set_parameters(self, parameter_dict: dict[str, float]) -> None:
335
- """
336
- Update a subset of parameters by label.
337
-
338
- Args:
339
- parameter_dict (dict[str, float]): Mapping from parameter labels to new numerical values.
340
-
341
- Raises:
342
- ValueError: If an unknown parameter label is provided.
343
- """
344
- for label, param in parameter_dict.items():
345
- if label not in self._parameters:
346
- raise ValueError(f"Parameter {label} is not defined in this hamiltonian.")
347
- self._parameters[label].set_value(param)
348
-
349
- def get_parameter_bounds(self) -> dict[str, tuple[float, float]]:
350
- """Return the lower and upper bounds currently associated with each parameter."""
351
- return {k: v.bounds for k, v in self._parameters.items()}
352
-
353
- def set_parameter_bounds(self, ranges: dict[str, tuple[float, float]]) -> None:
354
- """
355
- Update parameter bounds.
356
-
357
- Args:
358
- ranges (dict[str, tuple[float, float]]): Mapping from parameter labels to ``(lower, upper)`` bounds.
359
-
360
- Raises:
361
- ValueError: If an unknown parameter label is provided.
362
- """
363
- for label, bound in ranges.items():
364
- if label not in self._parameters:
365
- raise ValueError(
366
- f"The provided parameter label {label} is not defined in the list of parameters in this object."
367
- )
368
- self._parameters[label].set_bounds(bound[0], bound[1])
369
-
370
303
  def simplify(self) -> Hamiltonian:
371
304
  """Simplify the Hamiltonian expression by removing near-zero terms and accumulating constant terms.
372
305