openjij
Framework for the Ising model and QUBO.
Loading...
Searching...
No Matches
integer_quadratic_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
17namespace openjij {
18namespace graph {
19
21
22public:
24 std::vector<std::vector<std::int64_t>> &key_list,
25 std::vector<double> &value_list,
26 std::vector<std::pair<std::int64_t, std::int64_t>> &bounds) {
27 if (key_list.size() != value_list.size()) {
28 throw std::runtime_error("Key and value lists must have the same size.");
29 }
30
31 std::unordered_set<std::int64_t> index_set;
32 for (const auto &key : key_list) {
33 if (key.size() > 2) {
34 throw std::runtime_error("Key size must be less than or equal to 2.");
35 }
36 index_set.insert(key.begin(), key.end());
37 }
38
39 this->bounds_ = bounds;
40
41 this->index_list_ =
42 std::vector<std::int64_t>(index_set.begin(), index_set.end());
43 std::sort(this->index_list_.begin(), this->index_list_.end());
44
45 this->num_variables_ = this->index_list_.size();
46
47 this->quadratic_.resize(this->num_variables_);
48 this->linear_.resize(this->num_variables_, 0.0);
49 this->squared_.resize(this->num_variables_, 0.0);
50 this->constant_ = 0.0;
51
52 for (std::size_t i = 0; i < key_list.size(); ++i) {
53 const auto &key = key_list[i];
54 if (key.size() == 0) {
55 this->constant_ += value_list[i];
56 } else if (key.size() == 1) {
57 if (key[0] < 0 || key[0] >= num_variables_) {
58 throw std::runtime_error("Index out of bounds.");
59 }
60 this->linear_[key[0]] += value_list[i];
61 } else if (key.size() == 2) {
62 if (key[0] < 0 || key[0] >= this->num_variables_ || key[1] < 0 ||
63 key[1] >= this->num_variables_) {
64 throw std::runtime_error("Index out of bounds.");
65 }
66 if (key[0] == key[1]) {
67 this->squared_[key[0]] += value_list[i];
68 } else {
69 this->quadratic_[key[0]].emplace_back(key[1], value_list[i]);
70 this->quadratic_[key[1]].emplace_back(key[0], value_list[i]);
71 }
72 }
73 }
74
75 for (std::int64_t i = 0; i < this->num_variables_; ++i) {
76 if (std::abs(this->squared_[i]) < 1e-10) {
77 this->only_bilinear_index_set_.insert(i);
78 }
79 }
80 }
81
82 std::pair<double, double> GetMaxMinTerms() const {
83 const double MIN_THRESHOLD = 1e-10;
84
85 auto nonzero_abs_min = [&](double current_min, double value) -> double {
86 if (std::abs(value) > MIN_THRESHOLD) {
87 return std::min(std::abs(current_min), std::abs(value));
88 }
89 return current_min;
90 };
91
92 auto nonzero_abs_max = [&](double current_max, double value) -> double {
93 if (std::abs(value) > MIN_THRESHOLD) {
94 return std::max(std::abs(current_max), std::abs(value));
95 }
96 return current_max;
97 };
98
99 double abs_min_dE = std::numeric_limits<double>::infinity();
100 double abs_max_dE = 0.0;
101
102 for (std::int64_t i = 0; i < this->num_variables_; ++i) {
103 const auto &bound_i = this->bounds_[i];
104 const double max_abs_i = static_cast<double>(std::max(std::abs(bound_i.first), std::abs(bound_i.second)));
105
106 double min_nonzero_abs_i;
107 if (bound_i.first > 0) {
108 min_nonzero_abs_i = static_cast<double>(bound_i.first);
109 } else if (bound_i.second < 0) {
110 min_nonzero_abs_i = static_cast<double>(std::abs(bound_i.second));
111 } else {
112 min_nonzero_abs_i = 1.0;
113 }
114
115 for (const auto &[j, q] : this->quadratic_[i]) {
116 const auto &bound_j = this->bounds_[j];
117 const double max_abs_j = static_cast<double>(std::max(std::abs(bound_j.first), std::abs(bound_j.second)));
118
119 double min_nonzero_abs_j;
120 if (bound_j.first > 0) {
121 min_nonzero_abs_j = static_cast<double>(bound_j.first);
122 } else if (bound_j.second < 0) {
123 min_nonzero_abs_j = static_cast<double>(std::abs(bound_j.second));
124 } else {
125 min_nonzero_abs_j = 1.0;
126 }
127
130 }
131
133 abs_max_dE = nonzero_abs_max(abs_max_dE, std::abs(this->linear_[i]) * max_abs_i);
134
135 abs_min_dE = nonzero_abs_min(abs_min_dE, std::abs(this->squared_[i]) * std::pow(min_nonzero_abs_i, 2));
136 abs_max_dE = nonzero_abs_max(abs_max_dE, std::abs(this->squared_[i]) * std::pow(max_abs_i, 2));
137 }
138
139 if (std::isinf(abs_min_dE) || abs_max_dE == 0.0) {
140 throw std::runtime_error("No valid energy difference found.");
141 }
142
143 return std::make_pair(abs_max_dE, abs_min_dE);
144 }
145
146 const std::vector<std::int64_t> &GetIndexList() const { return index_list_; }
147 std::int64_t GetNumVariables() const { return num_variables_; }
148 const std::vector<std::vector<std::pair<std::int64_t, double>>> &
149 GetQuadratic() const {
150 return quadratic_;
151 }
152 const std::vector<double> &GetLinear() const { return linear_; }
153 const std::vector<double> &GetSquared() const { return squared_; }
154 double GetConstant() const { return constant_; }
155 const std::vector<std::pair<std::int64_t, std::int64_t>> &GetBounds() const {
156 return bounds_;
157 }
158 const std::unordered_set<std::int64_t> &GetOnlyBilinearIndexSet() const {
160 }
161
162private:
163 std::vector<std::int64_t> index_list_;
164 std::int64_t num_variables_;
165 std::vector<std::vector<std::pair<std::int64_t, double>>> quadratic_;
166 std::vector<double> linear_;
167 std::vector<double> squared_;
168 double constant_;
169 std::vector<std::pair<std::int64_t, std::int64_t>> bounds_;
170 std::unordered_set<std::int64_t> only_bilinear_index_set_;
171};
172
173} // namespace graph
174} // namespace openjij
Definition integer_quadratic_model.hpp:20
const std::vector< double > & GetLinear() const
Definition integer_quadratic_model.hpp:152
const std::unordered_set< std::int64_t > & GetOnlyBilinearIndexSet() const
Definition integer_quadratic_model.hpp:158
std::int64_t GetNumVariables() const
Definition integer_quadratic_model.hpp:147
double GetConstant() const
Definition integer_quadratic_model.hpp:154
std::vector< std::vector< std::pair< std::int64_t, double > > > quadratic_
Definition integer_quadratic_model.hpp:165
std::vector< double > squared_
Definition integer_quadratic_model.hpp:167
std::int64_t num_variables_
Definition integer_quadratic_model.hpp:164
const std::vector< double > & GetSquared() const
Definition integer_quadratic_model.hpp:153
std::vector< double > linear_
Definition integer_quadratic_model.hpp:166
const std::vector< std::vector< std::pair< std::int64_t, double > > > & GetQuadratic() const
Definition integer_quadratic_model.hpp:149
std::vector< std::int64_t > index_list_
Definition integer_quadratic_model.hpp:163
double constant_
Definition integer_quadratic_model.hpp:168
const std::vector< std::pair< std::int64_t, std::int64_t > > & GetBounds() const
Definition integer_quadratic_model.hpp:155
std::pair< double, double > GetMaxMinTerms() const
Definition integer_quadratic_model.hpp:82
std::unordered_set< std::int64_t > only_bilinear_index_set_
Definition integer_quadratic_model.hpp:170
IntegerQuadraticModel(std::vector< std::vector< std::int64_t > > &key_list, std::vector< double > &value_list, std::vector< std::pair< std::int64_t, std::int64_t > > &bounds)
Definition integer_quadratic_model.hpp:23
const std::vector< std::int64_t > & GetIndexList() const
Definition integer_quadratic_model.hpp:146
std::vector< std::pair< std::int64_t, std::int64_t > > bounds_
Definition integer_quadratic_model.hpp:169
auto json_parse(const json &obj, bool relabel=true)
parse json object from bqm.to_serializable
Definition parse.hpp:50
Definition algorithm.hpp:24