ommx-openjij-adapter 1.8.3__tar.gz → 1.8.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ommx_openjij_adapter
3
- Version: 1.8.3
3
+ Version: 1.8.5
4
4
  Summary: OMMX Adapter for OpenJij.
5
5
  Author-email: "Jij Inc." <info@j-ij.com>
6
6
  Project-URL: Repository, https://github.com/Jij-Inc/ommx
@@ -14,9 +14,8 @@ Classifier: License :: OSI Approved :: Apache Software License
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Requires-Python: <3.13,>=3.9
16
16
  Description-Content-Type: text/markdown
17
- Requires-Dist: ommx<2.0.0,>=1.8.3
17
+ Requires-Dist: ommx<2.0.0,>=1.8.5
18
18
  Requires-Dist: openjij>=0.9.2
19
- Provides-Extra: dev
20
19
 
21
20
  OMMX Adapter for OpenJij
22
21
  =========================
@@ -0,0 +1,207 @@
1
+ from __future__ import annotations
2
+
3
+ from ommx.v1 import Instance, State, Samples, SampleSet
4
+ from ommx.adapter import SamplerAdapter
5
+ import openjij as oj
6
+ from typing_extensions import deprecated
7
+
8
+
9
+ class OMMXOpenJijSAAdapter(SamplerAdapter):
10
+ """
11
+ Sampling QUBO with Simulated Annealing (SA) by `openjij.SASampler <https://openjij.github.io/OpenJij/reference/openjij/index.html#openjij.SASampler>`_
12
+ """
13
+
14
+ ommx_instance: Instance
15
+ """
16
+ ommx.v1.Instance representing a QUBO problem
17
+
18
+ The input `instance` must be a QUBO (Quadratic Unconstrained Binary Optimization) problem, i.e.
19
+
20
+ - Every decision variables are binary
21
+ - No constraint
22
+ - Objective function is quadratic
23
+ - Minimization problem
24
+
25
+ You can convert an instance to QUBO via :meth:`ommx.v1.Instance.penalty_method` or other corresponding method.
26
+ """
27
+
28
+ beta_min: float | None = None
29
+ """ minimal value of inverse temperature """
30
+ beta_max: float | None = None
31
+ """ maximum value of inverse temperature """
32
+ num_sweeps: int | None = None
33
+ """ number of sweeps """
34
+ num_reads: int | None = None
35
+ """ number of reads """
36
+ schedule: list | None = None
37
+ """ list of inverse temperature """
38
+ initial_state: list | dict | None = None
39
+ """ initial state """
40
+ updater: str | None = None
41
+ """ updater algorithm """
42
+ sparse: bool | None = None
43
+ """ use sparse matrix or not """
44
+ reinitialize_state: bool | None = None
45
+ """ if true reinitialize state for each run """
46
+ seed: int | None = None
47
+ """ seed for Monte Carlo algorithm """
48
+
49
+ @classmethod
50
+ def sample(
51
+ cls,
52
+ ommx_instance: Instance,
53
+ *,
54
+ beta_min: float | None = None,
55
+ beta_max: float | None = None,
56
+ num_sweeps: int | None = None,
57
+ num_reads: int | None = None,
58
+ schedule: list | None = None,
59
+ initial_state: list | dict | None = None,
60
+ updater: str | None = None,
61
+ sparse: bool | None = None,
62
+ reinitialize_state: bool | None = None,
63
+ seed: int | None = None,
64
+ ) -> SampleSet:
65
+ sampler = cls(
66
+ ommx_instance,
67
+ beta_min=beta_min,
68
+ beta_max=beta_max,
69
+ num_sweeps=num_sweeps,
70
+ num_reads=num_reads,
71
+ schedule=schedule,
72
+ initial_state=initial_state,
73
+ updater=updater,
74
+ sparse=sparse,
75
+ reinitialize_state=reinitialize_state,
76
+ seed=seed,
77
+ )
78
+ response = sampler._sample()
79
+ return sampler.decode_to_sampleset(response)
80
+
81
+ def __init__(
82
+ self,
83
+ ommx_instance: Instance,
84
+ *,
85
+ beta_min: float | None = None,
86
+ beta_max: float | None = None,
87
+ num_sweeps: int | None = None,
88
+ num_reads: int | None = None,
89
+ schedule: list | None = None,
90
+ initial_state: list | dict | None = None,
91
+ updater: str | None = None,
92
+ sparse: bool | None = None,
93
+ reinitialize_state: bool | None = None,
94
+ seed: int | None = None,
95
+ ):
96
+ self.ommx_instance = ommx_instance
97
+ self.beta_min = beta_min
98
+ self.beta_max = beta_max
99
+ self.num_sweeps = num_sweeps
100
+ self.num_reads = num_reads
101
+ self.schedule = schedule
102
+ self.initial_state = initial_state
103
+ self.updater = updater
104
+ self.sparse = sparse
105
+ self.reinitialize_state = reinitialize_state
106
+ self.seed = seed
107
+
108
+ def decode_to_sampleset(self, data: oj.Response) -> SampleSet:
109
+ samples = decode_to_samples(data)
110
+ return self.ommx_instance.evaluate_samples(samples)
111
+
112
+ def decode_to_samples(self, data: oj.Response) -> Samples:
113
+ """
114
+ Convert `openjij.Response <https://openjij.github.io/OpenJij/reference/openjij/index.html#openjij.Response>`_ to :class:`Samples`
115
+
116
+ There is a static method :meth:`decode_to_samples` that does the same thing.
117
+ """
118
+ return decode_to_samples(data)
119
+
120
+ @property
121
+ def sampler_input(self) -> dict[tuple[int, int], float]:
122
+ qubo, _offset = self.ommx_instance.as_qubo_format()
123
+ return qubo
124
+
125
+ def _sample(self) -> oj.Response:
126
+ sampler = oj.SASampler()
127
+ qubo, _offset = self.ommx_instance.as_qubo_format()
128
+ return sampler.sample_qubo(
129
+ qubo, # type: ignore
130
+ beta_min=self.beta_min,
131
+ beta_max=self.beta_max,
132
+ num_sweeps=self.num_sweeps,
133
+ num_reads=self.num_reads,
134
+ schedule=self.schedule,
135
+ initial_state=self.initial_state,
136
+ updater=self.updater,
137
+ sparse=self.sparse,
138
+ reinitialize_state=self.reinitialize_state,
139
+ seed=self.seed,
140
+ )
141
+
142
+
143
+ @deprecated("Renamed to `decode_to_samples`")
144
+ def response_to_samples(response: oj.Response) -> Samples:
145
+ """
146
+ Deprecated: renamed to :meth:`decode_to_samples`
147
+ """
148
+ return decode_to_samples(response)
149
+
150
+
151
+ def decode_to_samples(response: oj.Response) -> Samples:
152
+ """
153
+ Convert `openjij.Response <https://openjij.github.io/OpenJij/reference/openjij/index.html#openjij.Response>`_ to :class:`Samples`
154
+ """
155
+ # Filling into ommx.v1.Samples
156
+ # Since OpenJij does not issue the sample ID, we need to generate it in the responsibility of this OMMX Adapter
157
+ sample_id = 0
158
+ entries = []
159
+
160
+ num_reads = len(response.record.num_occurrences)
161
+ for i in range(num_reads):
162
+ sample = response.record.sample[i]
163
+ state = State(entries=zip(response.variables, sample)) # type: ignore
164
+ # `num_occurrences` is encoded into sample ID list.
165
+ # For example, if `num_occurrences` is 2, there are two samples with the same state, thus two sample IDs are generated.
166
+ ids = []
167
+ for _ in range(response.record.num_occurrences[i]):
168
+ ids.append(sample_id)
169
+ sample_id += 1
170
+ entries.append(Samples.SamplesEntry(state=state, ids=ids))
171
+ return Samples(entries=entries)
172
+
173
+
174
+ @deprecated("Use `OMMXOpenJijSAAdapter.sample` instead")
175
+ def sample_qubo_sa(
176
+ instance: Instance,
177
+ *,
178
+ beta_min: float | None = None,
179
+ beta_max: float | None = None,
180
+ num_sweeps: int | None = None,
181
+ num_reads: int | None = None,
182
+ schedule: list | None = None,
183
+ initial_state: list | dict | None = None,
184
+ updater: str | None = None,
185
+ sparse: bool | None = None,
186
+ reinitialize_state: bool | None = None,
187
+ seed: int | None = None,
188
+ ) -> Samples:
189
+ """
190
+ Deprecated: Use :meth:`OMMXOpenJijSAAdapter.sample` instead
191
+ """
192
+ q, _offset = instance.as_qubo_format()
193
+ sampler = oj.SASampler()
194
+ response = sampler.sample_qubo(
195
+ q, # type: ignore
196
+ beta_min=beta_min,
197
+ beta_max=beta_max,
198
+ num_sweeps=num_sweeps,
199
+ num_reads=num_reads,
200
+ schedule=schedule,
201
+ initial_state=initial_state,
202
+ updater=updater,
203
+ sparse=sparse,
204
+ reinitialize_state=reinitialize_state,
205
+ seed=seed,
206
+ )
207
+ return decode_to_samples(response)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ommx_openjij_adapter
3
- Version: 1.8.3
3
+ Version: 1.8.5
4
4
  Summary: OMMX Adapter for OpenJij.
5
5
  Author-email: "Jij Inc." <info@j-ij.com>
6
6
  Project-URL: Repository, https://github.com/Jij-Inc/ommx
@@ -14,9 +14,8 @@ Classifier: License :: OSI Approved :: Apache Software License
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Requires-Python: <3.13,>=3.9
16
16
  Description-Content-Type: text/markdown
17
- Requires-Dist: ommx<2.0.0,>=1.8.3
17
+ Requires-Dist: ommx<2.0.0,>=1.8.5
18
18
  Requires-Dist: openjij>=0.9.2
19
- Provides-Extra: dev
20
19
 
21
20
  OMMX Adapter for OpenJij
22
21
  =========================
@@ -0,0 +1,2 @@
1
+ ommx<2.0.0,>=1.8.5
2
+ openjij>=0.9.2
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ommx_openjij_adapter"
7
- version = "1.8.3"
7
+ version = "1.8.5"
8
8
 
9
9
  description = "OMMX Adapter for OpenJij."
10
10
  authors = [{ name = "Jij Inc.", email = "info@j-ij.com" }]
@@ -20,11 +20,8 @@ classifiers = [
20
20
  "License :: OSI Approved :: Apache Software License",
21
21
  "License :: OSI Approved :: MIT License",
22
22
  ]
23
- dependencies = ["ommx>=1.8.3,<2.0.0","openjij>=0.9.2"]
23
+ dependencies = ["ommx>=1.8.5,<2.0.0","openjij>=0.9.2"]
24
24
 
25
25
  [project.urls]
26
26
  Repository = "https://github.com/Jij-Inc/ommx"
27
27
  Issues = "https://github.com/Jij-Inc/ommx/issues"
28
-
29
- [project.optional-dependencies]
30
- dev = []
@@ -1,5 +1,5 @@
1
1
  from ommx.v1 import Instance, DecisionVariable
2
- import ommx_openjij_adapter as adapter
2
+ from ommx_openjij_adapter import OMMXOpenJijSAAdapter
3
3
 
4
4
 
5
5
  def test_minimize():
@@ -12,8 +12,7 @@ def test_minimize():
12
12
  constraints=[],
13
13
  sense=Instance.MINIMIZE,
14
14
  )
15
- samples = adapter.sample_qubo_sa(instance, num_reads=1)
16
- sample_set = instance.evaluate_samples(samples)
15
+ sample_set = OMMXOpenJijSAAdapter.sample(instance, num_reads=1)
17
16
 
18
17
  # x0 = x1 = 0 is minimum
19
18
  assert sample_set.extract_decision_variables("x", 0) == {(0,): 0.0, (1,): 0.0}
@@ -30,8 +29,7 @@ def test_maximize():
30
29
  sense=Instance.MAXIMIZE,
31
30
  )
32
31
  instance.as_minimization_problem()
33
- samples = adapter.sample_qubo_sa(instance, num_reads=1)
34
- sample_set = instance.evaluate_samples(samples)
32
+ sample_set = OMMXOpenJijSAAdapter.sample(instance, num_reads=1)
35
33
 
36
34
  # x0 = x1 = 1 is maximum
37
35
  assert sample_set.extract_decision_variables("x", 0) == {(0,): 1.0, (1,): 1.0}
@@ -1,87 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from ommx.v1 import Instance, State, Samples
4
- import openjij as oj
5
-
6
-
7
- def response_to_samples(response: oj.Response) -> Samples:
8
- """
9
- Convert OpenJij's `Response` to `ommx.v1.Samples`
10
- """
11
- # Filling into ommx.v1.Samples
12
- # Since OpenJij does not issue the sample ID, we need to generate it in the responsibility of this OMMX Adapter
13
- sample_id = 0
14
- entries = []
15
-
16
- num_reads = len(response.record.num_occurrences)
17
- for i in range(num_reads):
18
- sample = response.record.sample[i]
19
- state = State(entries=zip(response.variables, sample)) # type: ignore
20
- # `num_occurrences` is encoded into sample ID list.
21
- # For example, if `num_occurrences` is 2, there are two samples with the same state, thus two sample IDs are generated.
22
- ids = []
23
- for _ in range(response.record.num_occurrences[i]):
24
- ids.append(sample_id)
25
- sample_id += 1
26
- entries.append(Samples.SamplesEntry(state=state, ids=ids))
27
- return Samples(entries=entries)
28
-
29
-
30
- def sample_qubo_sa(
31
- instance: Instance,
32
- *,
33
- beta_min: float | None = None,
34
- beta_max: float | None = None,
35
- num_sweeps: int | None = None,
36
- num_reads: int | None = None,
37
- schedule: list | None = None,
38
- initial_state: list | dict | None = None,
39
- updater: str | None = None,
40
- sparse: bool | None = None,
41
- reinitialize_state: bool | None = None,
42
- seed: int | None = None,
43
- ) -> Samples:
44
- """
45
- Sampling QUBO with Simulated Annealing (SA) by [`openjij.SASampler`](https://openjij.github.io/OpenJij/reference/openjij/index.html#openjij.SASampler)
46
-
47
- The input `instance` must be a QUBO (Quadratic Unconstrained Binary Optimization) problem, i.e.
48
-
49
- - Every decision variables are binary
50
- - No constraint
51
- - Objective function is quadratic
52
- - Minimization problem
53
-
54
- You can convert a problem to QUBO via [`ommx.v1.Instance.penalty_method`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.penalty_method) or other corresponding method.
55
-
56
- :param instance: ommx.v1.Instance representing a QUBO problem
57
- :param beta_min: minimal value of inverse temperature
58
- :param beta_max: maximum value of inverse temperature
59
- :param num_sweeps: number of sweeps
60
- :param num_reads: number of reads
61
- :param schedule: list of inverse temperature
62
- :param initial_state: initial state
63
- :param updater: updater algorithm
64
- :param sparse: use sparse matrix or not.
65
- :param reinitialize_state: if true reinitialize state for each run
66
- :param seed: seed for Monte Carlo algorithm
67
-
68
- Note that this is a simple wrapper function for `openjij.SASampler.sample_qubo` method.
69
- For more advanced usage, you can use `ommx.v1.Instance.as_qubo_format` to get QUBO matrix,
70
- and use OpenJij manually, and convert the `openjij.Response` via `response_to_samples` function.
71
- """
72
- q, _offset = instance.as_qubo_format()
73
- sampler = oj.SASampler()
74
- response = sampler.sample_qubo(
75
- q, # type: ignore
76
- beta_min=beta_min,
77
- beta_max=beta_max,
78
- num_sweeps=num_sweeps,
79
- num_reads=num_reads,
80
- schedule=schedule,
81
- initial_state=initial_state,
82
- updater=updater,
83
- sparse=sparse,
84
- reinitialize_state=reinitialize_state,
85
- seed=seed,
86
- )
87
- return response_to_samples(response)
@@ -1,4 +0,0 @@
1
- ommx<2.0.0,>=1.8.3
2
- openjij>=0.9.2
3
-
4
- [dev]