intelloptim 0.1.0__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 (148) hide show
  1. intelloptim-0.1.0/.github/CODEOWNERS +1 -0
  2. intelloptim-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +29 -0
  3. intelloptim-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. intelloptim-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +14 -0
  5. intelloptim-0.1.0/.github/dependabot.yml +21 -0
  6. intelloptim-0.1.0/.github/pull_request_template.md +11 -0
  7. intelloptim-0.1.0/.github/workflows/ci.yml +126 -0
  8. intelloptim-0.1.0/.github/workflows/release.yml +114 -0
  9. intelloptim-0.1.0/.github/workflows/scheduled.yml +45 -0
  10. intelloptim-0.1.0/.gitignore +59 -0
  11. intelloptim-0.1.0/.pre-commit-config.yaml +34 -0
  12. intelloptim-0.1.0/CHANGELOG.md +36 -0
  13. intelloptim-0.1.0/CLAUDE.md +178 -0
  14. intelloptim-0.1.0/CODE_OF_CONDUCT.md +9 -0
  15. intelloptim-0.1.0/CONTRIBUTING.md +76 -0
  16. intelloptim-0.1.0/LICENSE +201 -0
  17. intelloptim-0.1.0/MANIFEST.in +4 -0
  18. intelloptim-0.1.0/NOTICE +8 -0
  19. intelloptim-0.1.0/PKG-INFO +188 -0
  20. intelloptim-0.1.0/README.md +124 -0
  21. intelloptim-0.1.0/SECURITY.md +21 -0
  22. intelloptim-0.1.0/noxfile.py +79 -0
  23. intelloptim-0.1.0/pyproject.toml +190 -0
  24. intelloptim-0.1.0/scripts/release.sh +44 -0
  25. intelloptim-0.1.0/scripts/release_tools.py +171 -0
  26. intelloptim-0.1.0/setup.cfg +4 -0
  27. intelloptim-0.1.0/src/intelloptim/__init__.py +51 -0
  28. intelloptim-0.1.0/src/intelloptim/_internal/__init__.py +19 -0
  29. intelloptim-0.1.0/src/intelloptim/_internal/audit.py +349 -0
  30. intelloptim-0.1.0/src/intelloptim/_internal/hashing.py +255 -0
  31. intelloptim-0.1.0/src/intelloptim/_internal/logging.py +352 -0
  32. intelloptim-0.1.0/src/intelloptim/_internal/schemas.py +300 -0
  33. intelloptim-0.1.0/src/intelloptim/algorithms/__init__.py +22 -0
  34. intelloptim-0.1.0/src/intelloptim/algorithms/backend/__init__.py +19 -0
  35. intelloptim-0.1.0/src/intelloptim/algorithms/backend/builtin/__init__.py +25 -0
  36. intelloptim-0.1.0/src/intelloptim/algorithms/backend/builtin/_common.py +41 -0
  37. intelloptim-0.1.0/src/intelloptim/algorithms/backend/builtin/owg.py +454 -0
  38. intelloptim-0.1.0/src/intelloptim/algorithms/backend/builtin/sa.py +317 -0
  39. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/__init__.py +31 -0
  40. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/__init__.py +0 -0
  41. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/base.py +348 -0
  42. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/config.py +115 -0
  43. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/distributions.py +319 -0
  44. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/executor.py +149 -0
  45. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/learner.py +225 -0
  46. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/measurement.py +86 -0
  47. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/policy.py +248 -0
  48. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/ppo.py +135 -0
  49. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/resources.py +60 -0
  50. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/serialization.py +25 -0
  51. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/snapshot.py +104 -0
  52. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/commons/space.py +230 -0
  53. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/gaus.py +47 -0
  54. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/mixture.py +49 -0
  55. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/qiskit/__init__.py +15 -0
  56. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/qiskit/circuit.py +33 -0
  57. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/qiskit/ibm_runtime.py +88 -0
  58. intelloptim-0.1.0/src/intelloptim/algorithms/backend/quantum/qiskit/simulator.py +62 -0
  59. intelloptim-0.1.0/src/intelloptim/algorithms/errors.py +33 -0
  60. intelloptim-0.1.0/src/intelloptim/algorithms/protocols.py +71 -0
  61. intelloptim-0.1.0/src/intelloptim/algorithms/pruners.py +88 -0
  62. intelloptim-0.1.0/src/intelloptim/algorithms/samplers.py +235 -0
  63. intelloptim-0.1.0/src/intelloptim/algorithms/space.py +53 -0
  64. intelloptim-0.1.0/src/intelloptim/client/__init__.py +30 -0
  65. intelloptim-0.1.0/src/intelloptim/client/api.py +364 -0
  66. intelloptim-0.1.0/src/intelloptim/client/auth.py +88 -0
  67. intelloptim-0.1.0/src/intelloptim/client/errors.py +170 -0
  68. intelloptim-0.1.0/src/intelloptim/client/study.py +388 -0
  69. intelloptim-0.1.0/src/intelloptim/client/trial.py +250 -0
  70. intelloptim-0.1.0/src/intelloptim/core/__init__.py +27 -0
  71. intelloptim-0.1.0/src/intelloptim/core/objective.py +146 -0
  72. intelloptim-0.1.0/src/intelloptim/core/parameters.py +301 -0
  73. intelloptim-0.1.0/src/intelloptim/core/pruners/__init__.py +63 -0
  74. intelloptim-0.1.0/src/intelloptim/core/pruners/base.py +56 -0
  75. intelloptim-0.1.0/src/intelloptim/core/pruners/optuna.py +176 -0
  76. intelloptim-0.1.0/src/intelloptim/core/samplers/__init__.py +97 -0
  77. intelloptim-0.1.0/src/intelloptim/core/samplers/base.py +141 -0
  78. intelloptim-0.1.0/src/intelloptim/core/samplers/builtin.py +138 -0
  79. intelloptim-0.1.0/src/intelloptim/core/samplers/optuna.py +215 -0
  80. intelloptim-0.1.0/src/intelloptim/core/samplers/quantum.py +332 -0
  81. intelloptim-0.1.0/src/intelloptim/params.py +24 -0
  82. intelloptim-0.1.0/src/intelloptim/py.typed +0 -0
  83. intelloptim-0.1.0/src/intelloptim/version.py +10 -0
  84. intelloptim-0.1.0/src/intelloptim/worker/__init__.py +14 -0
  85. intelloptim-0.1.0/src/intelloptim/worker/cli.py +134 -0
  86. intelloptim-0.1.0/src/intelloptim/worker/evaluator_cli.py +223 -0
  87. intelloptim-0.1.0/src/intelloptim/worker/registry.py +130 -0
  88. intelloptim-0.1.0/src/intelloptim/worker/slurm.py +72 -0
  89. intelloptim-0.1.0/src/intelloptim.egg-info/PKG-INFO +188 -0
  90. intelloptim-0.1.0/src/intelloptim.egg-info/SOURCES.txt +146 -0
  91. intelloptim-0.1.0/src/intelloptim.egg-info/dependency_links.txt +1 -0
  92. intelloptim-0.1.0/src/intelloptim.egg-info/entry_points.txt +2 -0
  93. intelloptim-0.1.0/src/intelloptim.egg-info/requires.txt +35 -0
  94. intelloptim-0.1.0/src/intelloptim.egg-info/scm_file_list.json +147 -0
  95. intelloptim-0.1.0/src/intelloptim.egg-info/scm_version.json +8 -0
  96. intelloptim-0.1.0/src/intelloptim.egg-info/top_level.txt +1 -0
  97. intelloptim-0.1.0/tests/__init__.py +0 -0
  98. intelloptim-0.1.0/tests/integration/__init__.py +0 -0
  99. intelloptim-0.1.0/tests/integration/quantum/__init__.py +0 -0
  100. intelloptim-0.1.0/tests/integration/quantum/test_hardware_smoke.py +41 -0
  101. intelloptim-0.1.0/tests/integration/quantum/test_ibm_runtime.py +141 -0
  102. intelloptim-0.1.0/tests/integration/quantum/test_qiskit_simulator.py +95 -0
  103. intelloptim-0.1.0/tests/integration/quantum/test_sim_samplers.py +200 -0
  104. intelloptim-0.1.0/tests/support/__init__.py +0 -0
  105. intelloptim-0.1.0/tests/support/numpy_executor.py +76 -0
  106. intelloptim-0.1.0/tests/unit/__init__.py +0 -0
  107. intelloptim-0.1.0/tests/unit/algorithms/__init__.py +0 -0
  108. intelloptim-0.1.0/tests/unit/algorithms/quantum/__init__.py +0 -0
  109. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_distributions.py +307 -0
  110. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_learner.py +205 -0
  111. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_measurement_and_executor.py +145 -0
  112. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_policy.py +210 -0
  113. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_ppo.py +127 -0
  114. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_samplers.py +443 -0
  115. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_snapshot.py +81 -0
  116. intelloptim-0.1.0/tests/unit/algorithms/quantum/test_space.py +176 -0
  117. intelloptim-0.1.0/tests/unit/algorithms/test_owg_sampler.py +627 -0
  118. intelloptim-0.1.0/tests/unit/algorithms/test_plugin_loading.py +125 -0
  119. intelloptim-0.1.0/tests/unit/algorithms/test_sa_sampler.py +358 -0
  120. intelloptim-0.1.0/tests/unit/algorithms/test_sampler_dependencies.py +155 -0
  121. intelloptim-0.1.0/tests/unit/client/__init__.py +0 -0
  122. intelloptim-0.1.0/tests/unit/client/conftest.py +58 -0
  123. intelloptim-0.1.0/tests/unit/client/test_auth.py +139 -0
  124. intelloptim-0.1.0/tests/unit/client/test_client.py +226 -0
  125. intelloptim-0.1.0/tests/unit/client/test_enqueue.py +40 -0
  126. intelloptim-0.1.0/tests/unit/client/test_error_mapping.py +123 -0
  127. intelloptim-0.1.0/tests/unit/client/test_optimize_worker_id.py +47 -0
  128. intelloptim-0.1.0/tests/unit/client/test_pruning.py +297 -0
  129. intelloptim-0.1.0/tests/unit/client/test_public_surface.py +21 -0
  130. intelloptim-0.1.0/tests/unit/client/test_trial.py +105 -0
  131. intelloptim-0.1.0/tests/unit/core/__init__.py +0 -0
  132. intelloptim-0.1.0/tests/unit/core/test_hashing.py +254 -0
  133. intelloptim-0.1.0/tests/unit/core/test_objective.py +137 -0
  134. intelloptim-0.1.0/tests/unit/core/test_parameters.py +161 -0
  135. intelloptim-0.1.0/tests/unit/core/test_pruners.py +107 -0
  136. intelloptim-0.1.0/tests/unit/core/test_quantum_specs.py +226 -0
  137. intelloptim-0.1.0/tests/unit/core/test_samplers.py +61 -0
  138. intelloptim-0.1.0/tests/unit/core/test_schemas.py +212 -0
  139. intelloptim-0.1.0/tests/unit/core/test_top_level_imports.py +137 -0
  140. intelloptim-0.1.0/tests/unit/internal/__init__.py +0 -0
  141. intelloptim-0.1.0/tests/unit/internal/test_audit.py +162 -0
  142. intelloptim-0.1.0/tests/unit/internal/test_logging.py +210 -0
  143. intelloptim-0.1.0/tests/unit/test_release_tools.py +193 -0
  144. intelloptim-0.1.0/tests/unit/worker/__init__.py +0 -0
  145. intelloptim-0.1.0/tests/unit/worker/test_cli.py +109 -0
  146. intelloptim-0.1.0/tests/unit/worker/test_evaluator_cli.py +261 -0
  147. intelloptim-0.1.0/tests/unit/worker/test_registry.py +94 -0
  148. intelloptim-0.1.0/tests/unit/worker/test_slurm_identity.py +58 -0
@@ -0,0 +1 @@
1
+ * @mbarbetti
@@ -0,0 +1,29 @@
1
+ name: Bug report
2
+ description: Something does not work as documented
3
+ labels: [bug]
4
+ body:
5
+ - type: textarea
6
+ id: what
7
+ attributes:
8
+ label: What happened, and what did you expect?
9
+ validations:
10
+ required: true
11
+ - type: textarea
12
+ id: repro
13
+ attributes:
14
+ label: Minimal example
15
+ description: Code that reproduces the problem. Remove tokens and private URLs.
16
+ render: python
17
+ - type: input
18
+ id: version
19
+ attributes:
20
+ label: intelloptim version
21
+ placeholder: "python -c 'import intelloptim; print(intelloptim.__version__)'"
22
+ validations:
23
+ required: true
24
+ - type: input
25
+ id: python
26
+ attributes:
27
+ label: Python version and operating system
28
+ validations:
29
+ required: true
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Report a security vulnerability
4
+ url: https://github.com/mbarbetti/intelloptim/security/advisories/new
5
+ about: Please report security problems privately, not in a public issue.
@@ -0,0 +1,14 @@
1
+ name: Feature request
2
+ description: Suggest an improvement
3
+ labels: [enhancement]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: What problem would this solve?
9
+ validations:
10
+ required: true
11
+ - type: textarea
12
+ id: idea
13
+ attributes:
14
+ label: What would you like to see?
@@ -0,0 +1,21 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ actions:
9
+ patterns: ["*"]
10
+ commit-message:
11
+ prefix: "ci"
12
+
13
+ - package-ecosystem: pip
14
+ directory: /
15
+ schedule:
16
+ interval: weekly
17
+ groups:
18
+ python-dependencies:
19
+ patterns: ["*"]
20
+ commit-message:
21
+ prefix: "build"
@@ -0,0 +1,11 @@
1
+ ## What and why
2
+
3
+ <!-- What changes, and why. Link the issue if there is one. -->
4
+
5
+ ## Checklist
6
+
7
+ - [ ] The PR title follows Conventional Commits (`feat(scope): ...`, `fix: ...`, `docs: ...`)
8
+ - [ ] Tests added or updated, and `nox` passes locally
9
+ - [ ] `CHANGELOG.md` has an entry under `[Unreleased]` (or the PR is labelled `skip-changelog`)
10
+ - [ ] Public API, docstrings and README updated if behaviour changed
11
+ - [ ] No credentials, tokens or private data in code, tests or logs
@@ -0,0 +1,126 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+ workflow_call:
8
+ inputs:
9
+ full:
10
+ description: "Run every supported Python version"
11
+ type: boolean
12
+ default: false
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ concurrency:
18
+ group: ci-${{ github.workflow }}-${{ github.ref }}
19
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
20
+
21
+ jobs:
22
+ plan:
23
+ runs-on: ubuntu-latest
24
+ outputs:
25
+ python: ${{ steps.pick.outputs.python }}
26
+ steps:
27
+ - id: pick
28
+ env:
29
+ FULL: ${{ inputs.full || github.event_name == 'push' }}
30
+ run: |
31
+ if [ "$FULL" = "true" ]; then
32
+ echo 'python=["3.11","3.12","3.13","3.14","3.15"]' >> "$GITHUB_OUTPUT"
33
+ else
34
+ echo 'python=["3.11","3.15"]' >> "$GITHUB_OUTPUT"
35
+ fi
36
+
37
+ lint:
38
+ runs-on: ubuntu-latest
39
+ steps:
40
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
41
+ with:
42
+ fetch-depth: 0
43
+ persist-credentials: false
44
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
45
+ with:
46
+ python-version: "3.12"
47
+ - run: python -m pip install nox
48
+ - run: nox -s lint --default-venv-backend virtualenv
49
+
50
+ typecheck:
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
54
+ with:
55
+ fetch-depth: 0
56
+ persist-credentials: false
57
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
58
+ with:
59
+ python-version: "3.12"
60
+ - run: python -m pip install nox
61
+ - run: nox -s typecheck --default-venv-backend virtualenv
62
+
63
+ test:
64
+ needs: plan
65
+ runs-on: ubuntu-latest
66
+ strategy:
67
+ fail-fast: false
68
+ matrix:
69
+ python: ${{ fromJSON(needs.plan.outputs.python) }}
70
+ steps:
71
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
72
+ with:
73
+ fetch-depth: 0
74
+ persist-credentials: false
75
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
76
+ with:
77
+ python-version: ${{ matrix.python }}
78
+ - run: python -m pip install nox
79
+ - run: nox -s "tests-${{ matrix.python }}" --default-venv-backend virtualenv
80
+
81
+ build:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
85
+ with:
86
+ fetch-depth: 0
87
+ persist-credentials: false
88
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
89
+ with:
90
+ python-version: "3.12"
91
+ - run: python -m pip install nox
92
+ - run: nox -s build --default-venv-backend virtualenv
93
+
94
+ changelog:
95
+ if: github.event_name == 'pull_request'
96
+ runs-on: ubuntu-latest
97
+ steps:
98
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
99
+ with:
100
+ fetch-depth: 0
101
+ persist-credentials: false
102
+ - name: CHANGELOG.md must change unless the PR is labelled skip-changelog
103
+ if: >-
104
+ !contains(github.event.pull_request.labels.*.name, 'skip-changelog')
105
+ && github.actor != 'dependabot[bot]'
106
+ env:
107
+ BASE_REF: ${{ github.base_ref }}
108
+ run: |
109
+ if ! git diff --name-only "origin/${BASE_REF}...HEAD" | grep -qx CHANGELOG.md; then
110
+ echo "::error::Add an entry under [Unreleased] in CHANGELOG.md, or label the PR skip-changelog."
111
+ exit 1
112
+ fi
113
+
114
+ # The only status check that branch protection needs to require.
115
+ ci-ok:
116
+ if: always()
117
+ needs: [plan, lint, typecheck, test, build, changelog]
118
+ runs-on: ubuntu-latest
119
+ steps:
120
+ - env:
121
+ RESULTS: ${{ join(needs.*.result, ' ') }}
122
+ run: |
123
+ echo "job results: $RESULTS"
124
+ case " $RESULTS " in
125
+ *" failure "*|*" cancelled "*) exit 1 ;;
126
+ esac
@@ -0,0 +1,114 @@
1
+ name: Release
2
+
3
+ # Pushing a tag vX.Y.Z (or vX.Y.ZrcN) from main builds the distributions and
4
+ # publishes them: pre-releases to TestPyPI, final releases to PyPI after the
5
+ # `pypi` environment is approved. No token is stored: PyPI trusts this workflow
6
+ # (Trusted Publishing).
7
+ on:
8
+ push:
9
+ tags: ["v*"]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ outputs:
18
+ prerelease: ${{ steps.kind.outputs.prerelease }}
19
+ steps:
20
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
21
+ with:
22
+ fetch-depth: 0
23
+ persist-credentials: false
24
+ - name: The tagged commit must be on main
25
+ run: |
26
+ git fetch --no-tags origin main
27
+ git merge-base --is-ancestor "$GITHUB_SHA" origin/main
28
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
29
+ with:
30
+ python-version: "3.12"
31
+ - run: python -m pip install build twine packaging
32
+ - id: kind
33
+ env:
34
+ TAG: ${{ github.ref_name }}
35
+ run: |
36
+ echo "prerelease=$(python scripts/release_tools.py prerelease "$TAG")" >> "$GITHUB_OUTPUT"
37
+ python scripts/release_tools.py notes "$TAG" > /dev/null
38
+ - run: python -m build --outdir dist
39
+ - run: twine check --strict dist/*
40
+ - env:
41
+ TAG: ${{ github.ref_name }}
42
+ run: |
43
+ python scripts/release_tools.py check-dist dist "$TAG"
44
+ python scripts/release_tools.py check-contents dist
45
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
46
+ with:
47
+ name: dist
48
+ path: dist/
49
+ if-no-files-found: error
50
+
51
+ publish-testpypi:
52
+ needs: build
53
+ if: needs.build.outputs.prerelease == 'true'
54
+ runs-on: ubuntu-latest
55
+ environment:
56
+ name: testpypi
57
+ url: https://test.pypi.org/project/intelloptim/
58
+ permissions:
59
+ id-token: write
60
+ steps:
61
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
62
+ with:
63
+ name: dist
64
+ path: dist/
65
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
66
+ with:
67
+ repository-url: https://test.pypi.org/legacy/
68
+
69
+ publish-pypi:
70
+ needs: build
71
+ if: needs.build.outputs.prerelease == 'false'
72
+ runs-on: ubuntu-latest
73
+ environment:
74
+ name: pypi
75
+ url: https://pypi.org/project/intelloptim/
76
+ permissions:
77
+ id-token: write
78
+ steps:
79
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
80
+ with:
81
+ name: dist
82
+ path: dist/
83
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
84
+
85
+ github-release:
86
+ needs: [build, publish-testpypi, publish-pypi]
87
+ if: >-
88
+ always() && needs.build.result == 'success'
89
+ && (needs.publish-testpypi.result == 'success' || needs.publish-pypi.result == 'success')
90
+ runs-on: ubuntu-latest
91
+ permissions:
92
+ contents: write
93
+ steps:
94
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
95
+ with:
96
+ persist-credentials: false
97
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
98
+ with:
99
+ name: dist
100
+ path: dist/
101
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
102
+ with:
103
+ python-version: "3.12"
104
+ - run: python -m pip install packaging
105
+ - name: Create the GitHub release
106
+ env:
107
+ GH_TOKEN: ${{ github.token }}
108
+ TAG: ${{ github.ref_name }}
109
+ PRERELEASE: ${{ needs.build.outputs.prerelease }}
110
+ run: |
111
+ python scripts/release_tools.py notes "$TAG" > notes.md
112
+ flag=""
113
+ if [ "$PRERELEASE" = "true" ]; then flag="--prerelease"; fi
114
+ gh release create "$TAG" dist/* --title "$TAG" --notes-file notes.md $flag
@@ -0,0 +1,45 @@
1
+ name: Scheduled
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 5 * * 1"
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ ci:
13
+ uses: ./.github/workflows/ci.yml
14
+ with:
15
+ full: true
16
+
17
+ extras-installable:
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ python: ["3.11", "3.12", "3.13", "3.14", "3.15"]
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
25
+ with:
26
+ fetch-depth: 0
27
+ persist-credentials: false
28
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
29
+ with:
30
+ python-version: ${{ matrix.python }}
31
+ - name: Every extra can still be resolved on this Python
32
+ run: python -m pip install --dry-run ".[samplers,quantum-ibm]"
33
+
34
+ audit:
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
38
+ with:
39
+ fetch-depth: 0
40
+ persist-credentials: false
41
+ - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
42
+ with:
43
+ python-version: "3.12"
44
+ - run: python -m pip install ".[samplers,quantum-ibm]" pip-audit
45
+ - run: pip-audit
@@ -0,0 +1,59 @@
1
+ # GenAI tools
2
+ .claude/
3
+ AGENTS.md
4
+
5
+ # Python
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+ *.so
10
+ .Python
11
+ *.egg-info/
12
+ .nox/
13
+ *.egg
14
+ .eggs/
15
+ build/
16
+ dist/
17
+ wheels/
18
+ .pytest_cache/
19
+ .mypy_cache/
20
+ .ruff_cache/
21
+ .tox/
22
+ .coverage
23
+ .coverage.*
24
+ htmlcov/
25
+ coverage.xml
26
+
27
+ # Virtual envs (we use conda envs outside the repo, but keep these out anyway)
28
+ .venv/
29
+ venv/
30
+ env/
31
+
32
+ # Local dev
33
+ *.db
34
+ *.db-journal
35
+ *.sqlite
36
+ *.sqlite3
37
+ dev.db*
38
+
39
+ # OS / editors
40
+ .DS_Store
41
+ .idea/
42
+ .vscode/
43
+ *.swp
44
+ *~
45
+
46
+ # Frontend
47
+ node_modules/
48
+ frontend/dist/
49
+ frontend/.vite/
50
+ frontend/coverage/
51
+
52
+ # Docker / runtime
53
+ .env
54
+ .env.local
55
+ *.pid
56
+
57
+ # Logs
58
+ *.log
59
+ logs/
@@ -0,0 +1,34 @@
1
+ # Hooks for local use: `pre-commit install`. The formatters and the type checker
2
+ # are the ones installed with the `dev` extra (`language: system`), so the
3
+ # versions and the dependencies are the same as in `nox` and in CI.
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: v5.0.0
7
+ hooks:
8
+ - id: trailing-whitespace
9
+ - id: end-of-file-fixer
10
+ - id: check-yaml
11
+ - id: check-toml
12
+ - id: check-added-large-files
13
+ args: ["--maxkb=512"]
14
+ - id: check-merge-conflict
15
+ - id: debug-statements
16
+
17
+ - repo: local
18
+ hooks:
19
+ - id: black
20
+ name: black
21
+ entry: black
22
+ language: system
23
+ types: [python]
24
+ - id: ruff
25
+ name: ruff
26
+ entry: ruff check --fix
27
+ language: system
28
+ types: [python]
29
+ - id: mypy
30
+ name: mypy
31
+ entry: mypy src/intelloptim
32
+ language: system
33
+ pass_filenames: false
34
+ files: ^src/intelloptim/
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file. The format
4
+ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project
5
+ uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html); while the
6
+ version is below 1.0, minor releases may contain breaking changes.
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-10-30
11
+
12
+ First public release.
13
+
14
+ ### Added
15
+
16
+ - Client SDK in `intelloptim.client` (`Client`, `StudyHandle`, `Trial`,
17
+ `TrialState` and the `errors` module) for an intelloptim server: ask/tell,
18
+ enqueue, early stopping with `Trial.report` and `Trial.should_prune`
19
+ (`TrialPruned` ends a pruned trial). `intelloptim.client` and
20
+ `intelloptim.algorithms` are loaded on first access, so `import intelloptim`
21
+ stays light.
22
+ - Declarative search spaces (`intelloptim.params`) with float, int and
23
+ categorical parameters.
24
+ - Sampler and pruner specifications backed by Optuna (Random, TPE, GP, NSGA-II,
25
+ QMC; Median, Percentile, Threshold, Nop) and the built-in samplers SA and OWG.
26
+ - Quantum policy samplers (Gaussian and mixture variants) with a simulated
27
+ version and a hardware version, an executor plugin mechanism
28
+ (`intelloptim.quantum_executors`) and an IBM Runtime executor.
29
+ - `intelloptim-worker evaluator` command, which runs an objective registered with
30
+ `@intopt.objective` against a server, for example as a SLURM array job. Each
31
+ worker sends its worker and site ids (`StudyHandle.optimize(...,
32
+ worker_id=...)`), derived from the SLURM environment.
33
+ - Optional extras: `gp`, `qmc`, `quantum`, `quantum-ibm`, `samplers`.
34
+
35
+ [Unreleased]: https://github.com/mbarbetti/intelloptim/compare/v0.1.0...HEAD
36
+ [0.1.0]: https://github.com/mbarbetti/intelloptim/releases/tag/v0.1.0
@@ -0,0 +1,178 @@
1
+ # intelloptim — project guidance
2
+
3
+ ## What this repo is
4
+
5
+ The client SDK and the algorithm layer of **intelloptim**, a general black-box
6
+ optimization framework built on Optuna's ask/tell API (an evolution of
7
+ **Hopaas**, Barbetti & Anderlini, 2023,
8
+ [arXiv:2301.05522](https://arxiv.org/abs/2301.05522)). It contains the user-facing
9
+ client, the pure domain types, the wire protocol, and the sampler/pruner
10
+ resolution including the in-repo sampler runtimes. Imported as
11
+ `import intelloptim as intopt`.
12
+
13
+ Users install it to talk to a running intelloptim server and to write
14
+ objectives. The server and the dashboard are separate projects that depend on
15
+ this package for its domain types, wire schemas, hashing and algorithms.
16
+
17
+ ## Mental map
18
+
19
+ ```
20
+ src/intelloptim/
21
+ _internal/ wire schemas (incl. TrialState), hashing (study identity),
22
+ logging, audit helpers
23
+ core/ pure domain types — no I/O, only pydantic
24
+ samplers/ base.py (SamplerKind, rebuild policy, base specs),
25
+ optuna.py (Random/TPE/GP/NSGA-II/QMC specs),
26
+ builtin.py (SA/OWG specs), quantum.py (quantum policy
27
+ specs: Gaus/Mixture, simulated "Sim" and hardware)
28
+ pruners/ base.py (PrunerKind), optuna.py (Median/Percentile/
29
+ Threshold/Nop specs)
30
+ parameters.py, objective.py
31
+ algorithms/ spec -> optuna resolvers (samplers.py, pruners.py) and
32
+ load_sampler_plugins() entry-point discovery
33
+ backend/ runtime for non-Optuna samplers (builtin/: sa.py, owg.py;
34
+ quantum/: gaus.py, mixture.py, commons/ for the
35
+ vendor-neutral policy, learner and executors, qiskit/ for
36
+ the only Qiskit code)
37
+ protocols.py, errors.py, space.py
38
+ client/ REST/WS SDK (Client, StudyHandle, Trial, errors) — httpx
39
+ worker/ `intelloptim-worker` CLI (evaluator subcommand, worker and site
40
+ identity from the SLURM environment)
41
+ params.py public facade over core/parameters (`intopt.params.Float`)
42
+ ```
43
+
44
+ ## Hard layering rules
45
+
46
+ 1. **`core/` is pure**: stdlib and pydantic only; no `httpx`, `optuna`, I/O or
47
+ networking.
48
+ 2. **`algorithms/` is the only place Optuna's sampler/pruner classes are
49
+ imported.** `core/` holds specs; `algorithms/` resolves them.
50
+ 3. **`_internal/schemas.py` is the only place wire models are defined.**
51
+ 4. **`_internal/hashing.py` output is byte-stable.** Golden tests pin it;
52
+ changing the hashed payload changes every study id.
53
+ 5. **`client/` is the only module that talks to a server over HTTP.**
54
+ 6. **Quantum samplers** (`SimQuantumGaus`, `QuantumGaus`, `SimQuantumMixture`,
55
+ `QuantumMixture`) live in-repo: specs in `core/samplers/quantum.py`, runtime
56
+ in `algorithms/backend/quantum/`. The `Sim` samplers are ideal; the others
57
+ run on hardware and are separate kinds on purpose. Specs never carry
58
+ credentials, and only `algorithms/backend/quantum/qiskit/` imports Qiskit.
59
+
60
+ ## Wire protocol and stability
61
+
62
+ - The wire models and `API_VERSION` live in `_internal/schemas.py`; the sampler
63
+ and pruner unions are `SamplerSpec` and `PrunerSpec`. Changing any of them is
64
+ a versioned event that the server and the dashboard must follow.
65
+ - Study-scoped requests carry `study_id` in the URL and `config_digest` in the
66
+ body; **409** on mismatch (`ConfigDigestMismatchError`).
67
+ - **503 + `Retry-After`** from `/ask` while a sampler rebuilds
68
+ (`StudyRebuildingError`). **410** from `/ask` and `/enqueue` when the study is
69
+ stopped (`StudyStoppedError`). **429** from `/ask` or `/tell` when the quota is
70
+ exhausted.
71
+ - `POST /studies/{id}/trials/{tid}/should_prune` takes the intermediate values
72
+ not yet sent and returns `{"should_prune": bool}`; it is not quota-counted.
73
+ - Study identity: `study_id = sha256(study_key, study_name, direction,
74
+ canonicalized_params, sampler_spec, pruner_spec)`, always computed with
75
+ `study_identity(study_key, request)`; `study_key` is an opaque per-user or
76
+ per-group key resolved by the server, never the API token.
77
+ - `trial_id` is an opaque handle; `number` is the position in the study.
78
+
79
+ ## Samplers
80
+
81
+ To add a **built-in** sampler: add a spec class in `core/samplers/`, add its
82
+ `kind` to `SamplerKind`, add it to the `SamplerSpec` union, and register a
83
+ resolver in `algorithms/samplers.py:_RESOLVERS`. If it is not a thin wrapper
84
+ over an Optuna sampler, put its runtime in `algorithms/backend/`. Pruners follow
85
+ the same pattern.
86
+
87
+ Built-in samplers must be **stateless**: the server builds a fresh sampler on
88
+ every ask, so anything an in-memory sampler would remember must be rebuilt from
89
+ the study history (with RNGs derived from the seed and trial number) or from a
90
+ model persisted in the study by `rebuild(study)` (see `OWG`, `SA` and the
91
+ quantum samplers).
92
+
93
+ External packages can override the resolver of an existing kind through the
94
+ `intelloptim.samplers` entry-point group, and add a quantum provider through
95
+ `intelloptim.quantum_executors`.
96
+
97
+ Ships in-repo: `Random`, `TPE`, `GP`, `NSGA-II`, `QMC` (Optuna-backed; `GP`
98
+ needs the `gp` extra, `QMC` the `qmc` extra), `SA`, `OWG`, and the quantum
99
+ policy samplers (extras `quantum`, `quantum-ibm`). A missing optional package
100
+ raises `SamplerDependencyError` naming the extra to install.
101
+
102
+ ## SDK contract
103
+
104
+ ```python
105
+ import intelloptim as intopt
106
+ with intopt.client.Client(url="...", token=...) as client:
107
+ study = client.create_study(
108
+ study_name="...", direction="minimize",
109
+ sampler_spec=intopt.samplers.TPESamplerSpec(seed=42),
110
+ parameters=[intopt.params.Float("x", -10, 10)],
111
+ )
112
+ study.optimize(my_objective, n_trials=50, catch=Exception)
113
+ best = study.best_trial
114
+ ```
115
+
116
+ - The search space is declared once, in `create_study(parameters=[...])`.
117
+ Objectives read the sampled values by name: `trial.sampled_float("x")`,
118
+ `sampled_int`, `sampled_categorical`. There is no `suggest_*`.
119
+ - `tell(state=COMPLETE)` requires `value`; `PRUNED`/`FAILED` accept `None`.
120
+ - Early stopping: `trial.report(value, step)` buffers locally,
121
+ `trial.should_prune()` sends the new values, and the objective raises
122
+ `intopt.client.errors.TrialPruned`, which `optimize` records as `PRUNED`.
123
+ - `create_study` is idempotent and parallel-safe; `best_trial` is `None` until
124
+ one trial completes. `optimize(n_trials=N)` raises `InsufficientQuotaError`
125
+ before any call if `N` exceeds the remaining calls.
126
+
127
+ Client errors: `ConfigDigestMismatchError` (409), `StudyRebuildingError` (503),
128
+ `StudyStoppedError` (410), `MissingTokenError`, `InsufficientQuotaError`,
129
+ `StudyLimitExceededError`.
130
+
131
+ ## Testing
132
+
133
+ - `tests/unit/` tests pure logic and never imports third-party quantum SDKs; the
134
+ quantum samplers run against a numpy executor in `tests/support/`.
135
+ `tests/integration/` (marker `qiskit`) uses real Qiskit and a stubbed IBM
136
+ runtime. Tests marked `hardware` hit a real device, are opt-in, and must never
137
+ run in automation.
138
+ - `client/` tests use `httpx.MockTransport`; there is no dependency on a server.
139
+ - Every feature or fix ships with `pytest` tests (happy path and edge cases).
140
+
141
+ ## Style
142
+
143
+ Black (88 columns, double quotes), Ruff, `mypy --strict`. Type hints with
144
+ `typing.List/Dict/Optional/Union`, `os.path` instead of `pathlib`, Google-style
145
+ docstrings with typed `Args:`, `Returns:`, `Raises:`. Comments only for a
146
+ non-obvious *why*. Docstrings describe behaviour for users, not development
147
+ rules.
148
+
149
+ ## Do not modify without explicit instruction
150
+
151
+ - `_internal/hashing.py` and `study_identity` (study ids and digests depend on
152
+ the exact bytes hashed).
153
+ - The wire models in `_internal/schemas.py` (versioned change, bump
154
+ `API_VERSION`).
155
+
156
+ ## Commands
157
+
158
+ ```bash
159
+ pip install -e ".[dev]"
160
+ pytest tests/unit -q
161
+ pytest tests/integration -q # needs the quantum extra
162
+ ruff check src/ tests/
163
+ black --check src/ tests/
164
+ mypy src/intelloptim/
165
+ nox # the same checks, across Python versions
166
+ ```
167
+
168
+ ## Development notes
169
+
170
+ The maintainer keeps additional design notes in `.claude/notes/`. They are not
171
+ part of the repository; ask for them when working in these areas:
172
+
173
+ - samplers and benchmarking (statelessness rules, sampler choice, honest
174
+ benchmarking)
175
+ - quantum samplers (design, cohort/snapshot mechanics, hardware guards, limits)
176
+ - sampler plugins (entry-point contract, adding a built-in sampler kind)
177
+ - documentation conventions (docstring style, checklist after public-surface
178
+ changes)