openjij
Framework for the Ising model and QUBO.
Loading...
Searching...
No Matches
binary_polynomial_model.hpp
Go to the documentation of this file.
1// Copyright 2023 Jij Inc.
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7// http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <unordered_map>
18
21
22
23namespace openjij {
24namespace graph {
25
26template<typename FloatType>
28 static_assert(std::is_floating_point<FloatType>::value,
29 "Template parameter FloatType must be floating point type");
30
31
32public:
35
38
41
43 using VariableType = std::int8_t;
44
45 BinaryPolynomialModel(const std::vector<std::vector<IndexType>> &key_list,
46 const std::vector<ValueType> &value_list) {
47
48 if (key_list.size() != value_list.size()) {
49 throw std::runtime_error("The size of keys and values does not match each other.");
50 }
51
52 ValueType abs_max_interaction = -1;
53
54 // Generate index list and store max interactions
55 std::unordered_set<IndexType, IndexHash> index_set;
56
57 for (std::size_t i = 0; i < key_list.size(); ++i) {
58 if (std::abs(value_list[i]) > std::numeric_limits<ValueType>::epsilon()) {
59 index_set.insert(key_list[i].begin(), key_list[i].end());
60 if (std::abs(value_list[i]) > abs_max_interaction) {
61 abs_max_interaction = std::abs(value_list[i]);
62 }
63 }
64 }
65
66 index_list_ = std::vector<IndexType>(index_set.begin(), index_set.end());
67 std::sort(index_list_.begin(), index_list_.end());
68
69 system_size_ = static_cast<std::int32_t>(index_list_.size());
70
71 // Generate index map (from index to integer)
72 index_map_.reserve(system_size_);
73 for (std::int32_t i = 0; i < system_size_; ++i) {
74 index_map_[index_list_[i]] = i;
75 }
76
77 // Generate interactions with integer index
78 std::unordered_map<std::vector<std::int32_t>, ValueType, utility::VectorHash> poly;
79 poly.reserve(key_list.size());
80 for (std::size_t i = 0; i < key_list.size(); ++i) {
81 if (std::abs(value_list[i]) > std::numeric_limits<ValueType>::epsilon()) {
82 std::vector<std::int32_t> int_key(key_list[i].size());
83 for (std::size_t j = 0; j < key_list[i].size(); ++j) {
84 int_key[j] = index_map_.at(key_list[i][j]);
85 }
86 std::sort(int_key.begin(), int_key.end());
87 int_key.erase(std::unique(int_key.begin(), int_key.end()), int_key.end());
88 poly[int_key] += value_list[i];
89 if (degree_ < int_key.size()) {
90 degree_ = static_cast<std::int32_t>(int_key.size());
91 }
92 }
93 }
94
95 key_value_list_.reserve(poly.size());
96 for (const auto &it: poly) {
97 key_value_list_.push_back({it.first, it.second});
98 }
99
100 poly.clear();
101
102 //Sort by keys.
103 std::sort(key_value_list_.begin(), key_value_list_.end(), [](const auto &a, const auto &b) {
104 return a.first < b.first;
105 });
106
108 for (std::size_t i = 0; i < key_value_list_.size(); ++i) {
109 for (const auto &index: key_value_list_[i].first) {
110 adjacency_list_[index].push_back(i);
111 }
112 }
113
114 for (std::int32_t i = 0; i < system_size_; ++i) {
115 adjacency_list_[i].shrink_to_fit();
116 std::sort(adjacency_list_[i].begin(), adjacency_list_[i].end());
117 }
118
119 // Set relevant absolute minimum interaction
120 // Apply threshold to avoid extremely minimum interaction derived from numerical errors.
121 ValueType relevant_abs_min_interaction = abs_max_interaction*min_max_energy_difference_ratio_;
122 estimated_min_energy_difference_ = std::numeric_limits<ValueType>::max();
124
125 for (std::int32_t i = 0; i < system_size_; ++i) {
126 ValueType abs_row_sum_interaction = 0;
127 for (const auto &interaction_index: adjacency_list_[i]) {
128 if (std::abs(key_value_list_[interaction_index].second) >= relevant_abs_min_interaction) {
129 abs_row_sum_interaction += std::abs(key_value_list_[interaction_index].second);
130 if (std::abs(key_value_list_[interaction_index].second) < estimated_min_energy_difference_) {
131 estimated_min_energy_difference_ = std::abs(key_value_list_[interaction_index].second);
132 }
133 }
134 }
135 if (abs_row_sum_interaction > estimated_max_energy_difference_) {
136 estimated_max_energy_difference_ = abs_row_sum_interaction;
137 }
138 }
139
140 if (degree_ == 0) {
143 }
144
145 }
146
149 std::int32_t GetDegree() const {
150 return degree_;
151 }
152
155 std::int32_t GetSystemSize() const {
156 return static_cast<std::int32_t>(index_list_.size());
157 }
158
161 const std::vector<IndexType> &GetIndexList() const {
162 return index_list_;
163 }
164
167 const std::unordered_map<IndexType, std::int32_t, IndexHash> &GetIndexMap() const {
168 return index_map_;
169 }
170
173 const std::vector<std::pair<std::vector<std::int32_t>, ValueType>> &GetKeyValueList() const {
174 return key_value_list_;
175 }
176
180 const std::vector<std::vector<std::size_t>> &GetAdjacencyList() const {
181 return adjacency_list_;
182 }
183
189
195
199 ValueType CalculateEnergy(const std::vector<VariableType> &variables) const {
200 if (variables.size() != system_size_) {
201 throw std::runtime_error("The size of variables is not equal to the system size");
202 }
203 ValueType val = 0;
204 for (std::size_t i = 0; i < key_value_list_.size(); ++i) {
205 VariableType hot_count = 0;
206 for (const auto &index: key_value_list_[i].first) {
207 if (variables[index] == 0) {
208 break;
209 }
210 hot_count += variables[index];
211 }
212 if (hot_count == key_value_list_[i].first.size()) {
213 val += key_value_list_[i].second;
214 }
215 }
216 return val;
217 }
218
219
220private:
222 std::int32_t degree_ = 0;
223
225 std::int32_t system_size_ = 0;
226
228 std::vector<IndexType> index_list_;
229
231 std::unordered_map<IndexType, std::int32_t, IndexHash> index_map_;
232
234 std::vector<std::pair<std::vector<std::int32_t>, ValueType>> key_value_list_;
235
238 std::vector<std::vector<std::size_t>> adjacency_list_;
239
242
245
249
250};
251
252
253}
254}
Definition binary_polynomial_model.hpp:27
const std::unordered_map< IndexType, std::int32_t, IndexHash > & GetIndexMap() const
Get the mapping from the index to the integer.
Definition binary_polynomial_model.hpp:167
const std::vector< std::vector< std::size_t > > & GetAdjacencyList() const
Get the adjacency list, which stored the integer index of the polynomial interaction specified by the...
Definition binary_polynomial_model.hpp:180
std::int32_t degree_
The degree of the interactions.
Definition binary_polynomial_model.hpp:222
const std::vector< IndexType > & GetIndexList() const
Get the index list of the polynomial interactions.
Definition binary_polynomial_model.hpp:161
std::int32_t GetSystemSize() const
Get the system size.
Definition binary_polynomial_model.hpp:155
std::vector< IndexType > index_list_
The index list of the interactions.
Definition binary_polynomial_model.hpp:228
const ValueType min_max_energy_difference_ratio_
The ratio of minimum and maximum energy difference set by 1e-08.
Definition binary_polynomial_model.hpp:248
utility::IndexType IndexType
The index type.
Definition binary_polynomial_model.hpp:37
ValueType CalculateEnergy(const std::vector< VariableType > &variables) const
Calculate energy corresponding to the variable configuration.
Definition binary_polynomial_model.hpp:199
ValueType estimated_max_energy_difference_
The estimated maximum energy difference.
Definition binary_polynomial_model.hpp:244
ValueType GetEstimatedMaxEnergyDifference() const
Get estimated maximum energy difference.
Definition binary_polynomial_model.hpp:192
std::vector< std::vector< std::size_t > > adjacency_list_
The adjacency list, which stored the integer index of the polynomial interaction specified by the sit...
Definition binary_polynomial_model.hpp:238
std::int8_t VariableType
The variable type, which here represents binary variables .
Definition binary_polynomial_model.hpp:43
ValueType GetEstimatedMinEnergyDifference() const
Get estimated minimum energy difference.
Definition binary_polynomial_model.hpp:186
std::int32_t system_size_
The system size.
Definition binary_polynomial_model.hpp:225
ValueType estimated_min_energy_difference_
The estimated minimum energy difference.
Definition binary_polynomial_model.hpp:241
std::vector< std::pair< std::vector< std::int32_t >, ValueType > > key_value_list_
The integer key and value list as pair.
Definition binary_polynomial_model.hpp:234
std::unordered_map< IndexType, std::int32_t, IndexHash > index_map_
The mapping from the index to the integer.
Definition binary_polynomial_model.hpp:231
BinaryPolynomialModel(const std::vector< std::vector< IndexType > > &key_list, const std::vector< ValueType > &value_list)
Definition binary_polynomial_model.hpp:45
std::int32_t GetDegree() const
Get the degree of the polynomial interactions.
Definition binary_polynomial_model.hpp:149
const std::vector< std::pair< std::vector< std::int32_t >, ValueType > > & GetKeyValueList() const
Get the integer key and value list as pair.
Definition binary_polynomial_model.hpp:173
FloatType ValueType
The value type.
Definition binary_polynomial_model.hpp:34
std::variant< std::int32_t, std::string, AnyTupleType > IndexType
The index type of binary variables.
Definition index_type.hpp:28
Definition algorithm.hpp:24
double FloatType
Note:
Definition compile_config.hpp:37
Hash struct of IndexType.
Definition pairhash.hpp:49
Hash struct of std::vector<T>.
Definition pairhash.hpp:92