qamomile 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.
- qamomile-0.1.0/PKG-INFO +101 -0
- qamomile-0.1.0/README.md +83 -0
- qamomile-0.1.0/pyproject.toml +48 -0
- qamomile-0.1.0/qamomile/core/__init__.py +12 -0
- qamomile-0.1.0/qamomile/core/ising_qubo/__init__.py +8 -0
- qamomile-0.1.0/qamomile/core/ising_qubo/ising_qubo.py +76 -0
- qamomile-0.1.0/qamomile/core/qrac/__init__.py +8 -0
- qamomile-0.1.0/qamomile/core/qrac/graph_coloring.py +111 -0
- qamomile-0.1.0/qamomile/qiskit/__init__.py +19 -0
- qamomile-0.1.0/qamomile/qiskit/minimal_encoding/__init__.py +9 -0
- qamomile-0.1.0/qamomile/qiskit/minimal_encoding/cost_function.py +98 -0
- qamomile-0.1.0/qamomile/qiskit/minimal_encoding/to_minimal_encoding.py +217 -0
- qamomile-0.1.0/qamomile/qiskit/qaoa/__init__.py +4 -0
- qamomile-0.1.0/qamomile/qiskit/qaoa/ising_hamiltonian.py +58 -0
- qamomile-0.1.0/qamomile/qiskit/qaoa/to_qaoa.py +166 -0
- qamomile-0.1.0/qamomile/qiskit/qrao/__init__.py +18 -0
- qamomile-0.1.0/qamomile/qiskit/qrao/qrao21.py +57 -0
- qamomile-0.1.0/qamomile/qiskit/qrao/qrao31.py +102 -0
- qamomile-0.1.0/qamomile/qiskit/qrao/qrao32.py +148 -0
- qamomile-0.1.0/qamomile/qiskit/qrao/qrao_space_efficient.py +77 -0
- qamomile-0.1.0/qamomile/qiskit/qrao/to_qrac.py +294 -0
- qamomile-0.1.0/qamomile/quri_parts/__init__.py +14 -0
- qamomile-0.1.0/qamomile/quri_parts/qaoa/__init__.py +3 -0
- qamomile-0.1.0/qamomile/quri_parts/qaoa/to_qaoa.py +209 -0
- qamomile-0.1.0/qamomile/quri_parts/qrao/__init__.py +17 -0
- qamomile-0.1.0/qamomile/quri_parts/qrao/qrao21.py +69 -0
- qamomile-0.1.0/qamomile/quri_parts/qrao/qrao31.py +122 -0
- qamomile-0.1.0/qamomile/quri_parts/qrao/qrao32.py +185 -0
- qamomile-0.1.0/qamomile/quri_parts/qrao/to_qrac.py +237 -0
qamomile-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: qamomile
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary:
|
|
5
|
+
Author: Jij Inc.
|
|
6
|
+
Author-email: info@j-ij.com
|
|
7
|
+
Requires-Python: >=3.9.8,<3.11
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Provides-Extra: qiskit
|
|
11
|
+
Provides-Extra: quri-parts
|
|
12
|
+
Requires-Dist: black (>=23.11.0,<24.0.0)
|
|
13
|
+
Requires-Dist: jijmodeling-transpiler (>=0.6.0rc3)
|
|
14
|
+
Requires-Dist: qiskit[qiskit] (>=0.44.0) ; extra == "qiskit"
|
|
15
|
+
Requires-Dist: quri-parts-qulacs[quri-parts] ; extra == "quri-parts"
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# Qamomile
|
|
19
|
+
|
|
20
|
+
`Qamomile` is a transpiler from model written in [JijModeling]() to quantum optimization algorithms on variaous quantum platform.
|
|
21
|
+
|
|
22
|
+
- [Qiskit](#qiskit)
|
|
23
|
+
- [QURI-Parts](#quri-parts)
|
|
24
|
+
|
|
25
|
+
Documentation: [https://jij-inc.github.io/Qamomile/](https://jij-inc.github.io/Qamomile/)
|
|
26
|
+
|
|
27
|
+
## Qiskit
|
|
28
|
+
|
|
29
|
+
[Qiskit](https://qiskit.org/) is an open-source SDK for working with quantum computers at the level of circuits, algorithms, and application modules.
|
|
30
|
+
|
|
31
|
+
### Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install "qamomile[qiskit]"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Quantum Approximate Optimization Algorithm (QAOA)
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import jijmodeling as jm
|
|
41
|
+
import jijmodeling_transpiler as jmt
|
|
42
|
+
import qamomile as jtq
|
|
43
|
+
|
|
44
|
+
# Create model
|
|
45
|
+
problem = jm.Problem("model")
|
|
46
|
+
... # Modeling ...
|
|
47
|
+
|
|
48
|
+
# Compile
|
|
49
|
+
compiled_instance = jmt.compile_model(problem, instance_data, fixed_vars)
|
|
50
|
+
|
|
51
|
+
# Transpile to QAOA of qikit
|
|
52
|
+
qaoa_builder = jtq.qiskit.transpile_to_qaoa(compiled_instance)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## QURI-Parts
|
|
57
|
+
|
|
58
|
+
[QURI Parts](https://quri-parts.qunasys.com/) is an open source library suite for creating and executing quantum algorithms on various quantum computers and simulators.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install "qamomile[quri-parts]"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Quantum Approximate Optimization Algorithm (QAOA)
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import jijmodeling as jm
|
|
68
|
+
import jijmodeling_transpiler as jmt
|
|
69
|
+
import qamomile as jtq
|
|
70
|
+
|
|
71
|
+
# Create model
|
|
72
|
+
problem = jm.Problem("model")
|
|
73
|
+
... # Modeling ...
|
|
74
|
+
|
|
75
|
+
# Compile
|
|
76
|
+
compiled_instance = jmt.compile_model(problem, instance_data, fixed_vars)
|
|
77
|
+
|
|
78
|
+
# Transpile to QAOA of qikit
|
|
79
|
+
qaoa_builder = jtq.quri.transpile_to_qaoa(compiled_instance)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
## Contributing
|
|
84
|
+
|
|
85
|
+
### Setup
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install poetry
|
|
89
|
+
poetry install --all-extras
|
|
90
|
+
poetry shell
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Test
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pytest tests
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
qamomile-0.1.0/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Qamomile
|
|
2
|
+
|
|
3
|
+
`Qamomile` is a transpiler from model written in [JijModeling]() to quantum optimization algorithms on variaous quantum platform.
|
|
4
|
+
|
|
5
|
+
- [Qiskit](#qiskit)
|
|
6
|
+
- [QURI-Parts](#quri-parts)
|
|
7
|
+
|
|
8
|
+
Documentation: [https://jij-inc.github.io/Qamomile/](https://jij-inc.github.io/Qamomile/)
|
|
9
|
+
|
|
10
|
+
## Qiskit
|
|
11
|
+
|
|
12
|
+
[Qiskit](https://qiskit.org/) is an open-source SDK for working with quantum computers at the level of circuits, algorithms, and application modules.
|
|
13
|
+
|
|
14
|
+
### Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install "qamomile[qiskit]"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Quantum Approximate Optimization Algorithm (QAOA)
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
import jijmodeling as jm
|
|
24
|
+
import jijmodeling_transpiler as jmt
|
|
25
|
+
import qamomile as jtq
|
|
26
|
+
|
|
27
|
+
# Create model
|
|
28
|
+
problem = jm.Problem("model")
|
|
29
|
+
... # Modeling ...
|
|
30
|
+
|
|
31
|
+
# Compile
|
|
32
|
+
compiled_instance = jmt.compile_model(problem, instance_data, fixed_vars)
|
|
33
|
+
|
|
34
|
+
# Transpile to QAOA of qikit
|
|
35
|
+
qaoa_builder = jtq.qiskit.transpile_to_qaoa(compiled_instance)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## QURI-Parts
|
|
40
|
+
|
|
41
|
+
[QURI Parts](https://quri-parts.qunasys.com/) is an open source library suite for creating and executing quantum algorithms on various quantum computers and simulators.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install "qamomile[quri-parts]"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Quantum Approximate Optimization Algorithm (QAOA)
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import jijmodeling as jm
|
|
51
|
+
import jijmodeling_transpiler as jmt
|
|
52
|
+
import qamomile as jtq
|
|
53
|
+
|
|
54
|
+
# Create model
|
|
55
|
+
problem = jm.Problem("model")
|
|
56
|
+
... # Modeling ...
|
|
57
|
+
|
|
58
|
+
# Compile
|
|
59
|
+
compiled_instance = jmt.compile_model(problem, instance_data, fixed_vars)
|
|
60
|
+
|
|
61
|
+
# Transpile to QAOA of qikit
|
|
62
|
+
qaoa_builder = jtq.quri.transpile_to_qaoa(compiled_instance)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Contributing
|
|
67
|
+
|
|
68
|
+
### Setup
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install poetry
|
|
72
|
+
poetry install --all-extras
|
|
73
|
+
poetry shell
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Test
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pytest tests
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["poetry-core>=1.5.2", "poetry-dynamic-versioning>=0.21.4"]
|
|
3
|
+
build-backend = "poetry_dynamic_versioning.backend"
|
|
4
|
+
|
|
5
|
+
[tool.poetry-dynamic-versioning]
|
|
6
|
+
enable = false
|
|
7
|
+
style = "pep440"
|
|
8
|
+
|
|
9
|
+
[tool.poetry]
|
|
10
|
+
name = "qamomile"
|
|
11
|
+
version = "0.1.0" # using poetry-dynamic-versioning
|
|
12
|
+
description = ""
|
|
13
|
+
authors = ["Jij Inc. <info@j-ij.com>"]
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
packages = [
|
|
16
|
+
{include = "qamomile"},
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[tool.poetry.dependencies]
|
|
20
|
+
python = ">=3.9.8,<3.11"
|
|
21
|
+
jijmodeling-transpiler = ">=0.6.0rc3"
|
|
22
|
+
qiskit = {version = ">=0.44.0", extras = ["qiskit"]}
|
|
23
|
+
quri-parts-qulacs = {version = "*", extras = ["quri-parts"]}
|
|
24
|
+
black = "^23.11.0"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
[tool.poetry.group.dev.dependencies]
|
|
28
|
+
jupyter = "^1.0.0"
|
|
29
|
+
matplotlib = "^3.7.1"
|
|
30
|
+
pylatexenc = "^2.10"
|
|
31
|
+
pytest = "^7.3.2"
|
|
32
|
+
|
|
33
|
+
[tool.poetry.extras]
|
|
34
|
+
qiskit = ["qiskit"]
|
|
35
|
+
quri-parts = ["quri-parts-qulacs"]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
addopts = "--doctest-modules"
|
|
40
|
+
|
|
41
|
+
[tool.poetry.group.docs.dependencies]
|
|
42
|
+
mkdocs = "^1.4.2"
|
|
43
|
+
mkdocs-material = "^9.1.5"
|
|
44
|
+
mkdocs-gen-files = ">=0.4,<0.6"
|
|
45
|
+
mkdocs-section-index = "^0.3.5"
|
|
46
|
+
mkdocs-literate-nav = "^0.6.0"
|
|
47
|
+
mkdocs-jupyter = "^0.24.0"
|
|
48
|
+
mkdocstrings = {version = ">=0.19", extras = ["python"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from qamomile.core import ising_qubo as ising_qubo
|
|
2
|
+
from qamomile.core import qrac as qrac
|
|
3
|
+
from .ising_qubo import qubo_to_ising, IsingModel
|
|
4
|
+
from .qrac import greedy_graph_coloring
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"ising_qubo",
|
|
8
|
+
"qrac",
|
|
9
|
+
"qubo_to_ising",
|
|
10
|
+
"IsingModel",
|
|
11
|
+
"greedy_graph_coloring",
|
|
12
|
+
]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclasses.dataclass
|
|
5
|
+
class IsingModel:
|
|
6
|
+
quad: dict[tuple[int, int], float]
|
|
7
|
+
linear: dict[int, float]
|
|
8
|
+
constant: float
|
|
9
|
+
|
|
10
|
+
def calc_energy(self, state: list[int]) -> float:
|
|
11
|
+
"""Calculates the energy of the state.
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
>>> ising = IsingModel({(0, 1): 2.0}, {0: 4.0, 1: 5.0}, 6.0)
|
|
15
|
+
>>> ising.calc_energy([1, -1])
|
|
16
|
+
3.0
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
energy = self.constant
|
|
20
|
+
for (i, j), value in self.quad.items():
|
|
21
|
+
energy += value * state[i] * state[j]
|
|
22
|
+
for i, value in self.linear.items():
|
|
23
|
+
energy += value * state[i]
|
|
24
|
+
return energy
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def calc_qubo_energy(qubo: dict[tuple[int, int], float], state: list[int]) -> float:
|
|
28
|
+
"""Calculates the energy of the state.
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
>>> calc_qubo_energy({(0, 0): 1.0, (0, 1): 2.0, (1, 1): 3.0}, [1, 1])
|
|
32
|
+
6.0
|
|
33
|
+
"""
|
|
34
|
+
energy = 0.0
|
|
35
|
+
for (i, j), value in qubo.items():
|
|
36
|
+
energy += value * state[i] * state[j]
|
|
37
|
+
return energy
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def qubo_to_ising(qubo: dict[tuple[int, int], float], simplify=True) -> IsingModel:
|
|
41
|
+
"""Converts a QUBO to an Ising model.
|
|
42
|
+
|
|
43
|
+
QUBO: sum_{ij} Q_{ij} x_i x_j -> Ising: sum_{ij} J_{ij} z_i z_j + sum_i h_i z_i
|
|
44
|
+
Correspondence - x_i = (1 - z_i) / 2, where x_i in {0, 1} and z_i in {-1, 1}
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
>>> qubo = {(0, 0): 1.0, (0, 1): 2.0, (1, 1): 3.0}
|
|
48
|
+
>>> ising = qubo_to_ising(qubo)
|
|
49
|
+
>>> binary = [1, 0]
|
|
50
|
+
>>> spin = [-1, 1]
|
|
51
|
+
>>> qubo_energy = calc_qubo_energy(qubo, binary)
|
|
52
|
+
>>> assert qubo_energy == ising.calc_energy(spin)
|
|
53
|
+
|
|
54
|
+
>>> qubo = {(0, 1): 2, (0, 0): -1, (1, 1): -1}
|
|
55
|
+
>>> ising = qubo_to_ising(qubo)
|
|
56
|
+
>>> assert ising.constant == -0.5
|
|
57
|
+
>>> assert ising.linear == {}
|
|
58
|
+
>>> assert ising.quad == {(0, 1): 0.5}
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
ising_J: dict[tuple[int, int], float] = {}
|
|
62
|
+
ising_h: dict[int, float] = {}
|
|
63
|
+
constant = 0.0
|
|
64
|
+
for (i, j), value in qubo.items():
|
|
65
|
+
if i != j:
|
|
66
|
+
ising_J[(i, j)] = value / 4.0 + ising_J.get((i, j), 0.0)
|
|
67
|
+
constant += value / 4.0
|
|
68
|
+
else:
|
|
69
|
+
constant += value / 2.0
|
|
70
|
+
ising_h[i] = -value / 4.0 + ising_h.get(i, 0.0)
|
|
71
|
+
ising_h[j] = -value / 4.0 + ising_h.get(j, 0.0)
|
|
72
|
+
|
|
73
|
+
if simplify:
|
|
74
|
+
ising_J = {ij: value for ij, value in ising_J.items() if value != 0.0}
|
|
75
|
+
ising_h = {i: value for i, value in ising_h.items() if value != 0.0}
|
|
76
|
+
return IsingModel(ising_J, ising_h, constant)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides utilities for the Quantum Random Access Coding (QRAC).
|
|
3
|
+
Ex: QRAC utilizes are used Quantum Random Access Optimization (QRAO).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .graph_coloring import greedy_graph_coloring, check_linear_term
|
|
7
|
+
|
|
8
|
+
__all__ = ["greedy_graph_coloring", "check_linear_term"]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import typing as typ
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def greedy_graph_coloring(
|
|
6
|
+
graph: typ.Iterable[tuple[int, int]],
|
|
7
|
+
max_color_group_size: int,
|
|
8
|
+
init_coloring: typ.Optional[dict[int, int]] = None,
|
|
9
|
+
) -> tuple[dict[int, int], dict[int, list[int]]]:
|
|
10
|
+
"""graph coloring for QRAC
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
graph (typ.Iterable[tuple[int, int]]): _description_
|
|
14
|
+
max_color_group_size (int): if you want to use for the qrac31, set 3.
|
|
15
|
+
init_coloring (typ.Optional[dict[int, int]], optional): initial coloring. Defaults to None.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
tuple[dict[int, int], dict[int, list[int]]]: coloring, color_group
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
>>> graph = [(0, 1), (1, 2), (2, 0), (0, 4)]
|
|
23
|
+
>>> greedy_graph_coloring(graph, 2)
|
|
24
|
+
({0: 0, 1: 1, 2: 2, 4: 1}, {0: [0], 1: [1, 4], 2: [2]})
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
coloring = {}
|
|
28
|
+
if init_coloring:
|
|
29
|
+
coloring.update(init_coloring)
|
|
30
|
+
|
|
31
|
+
max_color = max(coloring.values()) if coloring else -1
|
|
32
|
+
|
|
33
|
+
adj_matrix: dict[int, list[int]] = {}
|
|
34
|
+
for i, j in graph:
|
|
35
|
+
if i == j:
|
|
36
|
+
continue
|
|
37
|
+
if i not in adj_matrix:
|
|
38
|
+
adj_matrix[i] = []
|
|
39
|
+
if j not in adj_matrix:
|
|
40
|
+
adj_matrix[j] = []
|
|
41
|
+
adj_matrix[i].append(j)
|
|
42
|
+
adj_matrix[j].append(i)
|
|
43
|
+
|
|
44
|
+
color_group: dict[int, list[int]] = {}
|
|
45
|
+
for index, color in coloring.items():
|
|
46
|
+
if color not in coloring:
|
|
47
|
+
color_group[color] = []
|
|
48
|
+
color_group[color].append(index)
|
|
49
|
+
|
|
50
|
+
for i, neigborhoors in adj_matrix.items():
|
|
51
|
+
if i in coloring:
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
neighbor_colors = [coloring[k] for k in neigborhoors if k in coloring]
|
|
55
|
+
|
|
56
|
+
done_coloring = False
|
|
57
|
+
for color in range(max_color + 1):
|
|
58
|
+
if color not in color_group or color not in neighbor_colors:
|
|
59
|
+
if color not in color_group or max_color_group_size > len(
|
|
60
|
+
color_group[color]
|
|
61
|
+
):
|
|
62
|
+
coloring[i] = color
|
|
63
|
+
done_coloring = True
|
|
64
|
+
if color not in color_group:
|
|
65
|
+
color_group[color] = []
|
|
66
|
+
color_group[color].append(i)
|
|
67
|
+
break
|
|
68
|
+
if not done_coloring:
|
|
69
|
+
coloring[i] = max_color + 1
|
|
70
|
+
color_group[max_color + 1] = [i]
|
|
71
|
+
max_color += 1
|
|
72
|
+
|
|
73
|
+
return coloring, color_group
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def check_linear_term(
|
|
77
|
+
color_group: dict[int, list[int]],
|
|
78
|
+
linear_term_index: list[int],
|
|
79
|
+
max_color_group_size: int,
|
|
80
|
+
) -> dict[int, list[int]]:
|
|
81
|
+
"""Search for items within the index of linear term that have not been assigned to the color_group, and add them.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
color_group (dict[int, list[int]]): color_group
|
|
85
|
+
linear_term_index (list[int]): list of index of linear term
|
|
86
|
+
max_color_group_size (int): the maximum number of encoding qubits. if you want to use for the qrac31, set 3.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
dict[int, list[int]]: color_group which added items within the index of linear term that have not been assigned to the color_group.
|
|
90
|
+
"""
|
|
91
|
+
idx_in_color_group = []
|
|
92
|
+
for v in color_group.values():
|
|
93
|
+
idx_in_color_group.extend(v)
|
|
94
|
+
|
|
95
|
+
# We're adding a bit to the next index of the 'quad' qubit, affecting only the linear term.
|
|
96
|
+
# If the Ising Hamiltonian has only linear terms, making 'quad' empty and causing a 'max' error, we return index 0 to avoid this.
|
|
97
|
+
qubit_index_for_linear = max(color_group.keys()) + 1 if color_group else 0
|
|
98
|
+
bits_in_qubits_counter = 1
|
|
99
|
+
for idx in linear_term_index:
|
|
100
|
+
if idx not in idx_in_color_group:
|
|
101
|
+
if bits_in_qubits_counter == 1:
|
|
102
|
+
color_group[qubit_index_for_linear] = []
|
|
103
|
+
|
|
104
|
+
color_group[qubit_index_for_linear].append(idx)
|
|
105
|
+
bits_in_qubits_counter += 1
|
|
106
|
+
|
|
107
|
+
if bits_in_qubits_counter > max_color_group_size:
|
|
108
|
+
qubit_index_for_linear += 1
|
|
109
|
+
bits_in_qubits_counter = 1
|
|
110
|
+
|
|
111
|
+
return color_group
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from qamomile.qiskit import qaoa as qaoa
|
|
2
|
+
from qamomile.qiskit import qrao as qrao
|
|
3
|
+
from .qaoa.to_qaoa import transpile_to_qaoa_ansatz
|
|
4
|
+
from .qrao.to_qrac import (
|
|
5
|
+
transpile_to_qrac31_hamiltonian,
|
|
6
|
+
transpile_to_qrac21_hamiltonian,
|
|
7
|
+
transpile_to_qrac32_hamiltonian,
|
|
8
|
+
transpile_to_qrac_space_efficient_hamiltonian,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"qaoa",
|
|
13
|
+
"qrao",
|
|
14
|
+
"transpile_to_qaoa_ansatz",
|
|
15
|
+
"transpile_to_qrac31_hamiltonian",
|
|
16
|
+
"transpile_to_qrac21_hamiltonian",
|
|
17
|
+
"transpile_to_qrac32_hamiltonian",
|
|
18
|
+
"transpile_to_qrac_space_efficient_hamiltonian",
|
|
19
|
+
]
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import itertools
|
|
4
|
+
import typing as typ
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import qiskit as qk
|
|
9
|
+
import qiskit.quantum_info as qk_info
|
|
10
|
+
from qiskit.primitives import Estimator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def define_pauli_op(
|
|
14
|
+
num_register_bits: int, ancilla: bool = False
|
|
15
|
+
) -> list[qk_info.SparsePauliOp]:
|
|
16
|
+
"""Function to define pauli operators
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
num_register_bits (int): number of register bits
|
|
20
|
+
ancilla (bool, optional): whether to add ancilla qubit |1> or not. Defaults to False.
|
|
21
|
+
|
|
22
|
+
Raises:
|
|
23
|
+
ValueError: if num_register_bits < 1
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
list[qk_info.SparsePauliOp]: list of pauli operators
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
if num_register_bits < 1:
|
|
30
|
+
raise ValueError("num_register_bits must be greater than 0")
|
|
31
|
+
|
|
32
|
+
z = [[False], [True]]
|
|
33
|
+
x = [[False], [False]]
|
|
34
|
+
zero_op = qk_info.SparsePauliOp(
|
|
35
|
+
qk_info.PauliList.from_symplectic(z, x), coeffs=[1 / 2, 1 / 2]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
one_op = qk_info.SparsePauliOp(
|
|
39
|
+
qk_info.PauliList.from_symplectic(z, x), coeffs=[1 / 2, -1 / 2]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
identity_op = qk_info.SparsePauliOp(qk_info.Pauli(([0], [0])))
|
|
43
|
+
|
|
44
|
+
ancilla_operator = one_op if ancilla else identity_op
|
|
45
|
+
|
|
46
|
+
pauli_ops = []
|
|
47
|
+
|
|
48
|
+
if num_register_bits == 1:
|
|
49
|
+
for _op in [one_op, zero_op]:
|
|
50
|
+
pauli_ops.append(_op.tensor(ancilla_operator))
|
|
51
|
+
else:
|
|
52
|
+
for val in itertools.product(
|
|
53
|
+
[one_op, zero_op], repeat=num_register_bits
|
|
54
|
+
):
|
|
55
|
+
pauli_op = val[0]
|
|
56
|
+
for _op in val[1:]:
|
|
57
|
+
pauli_op = pauli_op.tensor(_op)
|
|
58
|
+
|
|
59
|
+
pauli_ops.append(pauli_op.tensor(ancilla_operator))
|
|
60
|
+
|
|
61
|
+
return pauli_ops
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def initialize_cost_function(
|
|
65
|
+
qubo: dict[tuple[int, int], float], num_cbits: int
|
|
66
|
+
) -> Callable[[np.array], float]:
|
|
67
|
+
"""Function to initialize cost function for minimal encoding
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
qubo (dict[tuple[int, int], float]): QUBO Matrix
|
|
71
|
+
num_cbit (int): number of classical bits
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Callable[[np.array], float]: cost function for minimal encoding
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# define cost function
|
|
78
|
+
def cost_function(one_coeffs: np.array) -> float:
|
|
79
|
+
"""Function to compute value of cost function for minimal encoding
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
one_coeffs (np.array): the ratio of the expectation value of each pauli operator for when ancilla qubit is |1> and the expectation value of each pauli operator ignoring ancilla qubit
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
float: value of cost function
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
cost = 0
|
|
89
|
+
for i in range(num_cbits):
|
|
90
|
+
for j in range(i, num_cbits):
|
|
91
|
+
if i != j:
|
|
92
|
+
cost += 2 * qubo[(i, j)] * one_coeffs[i] * one_coeffs[j]
|
|
93
|
+
else:
|
|
94
|
+
cost += qubo[(i, j)] * one_coeffs[i]
|
|
95
|
+
|
|
96
|
+
return cost
|
|
97
|
+
|
|
98
|
+
return cost_function
|