19 #include <pybind11/pybind11.h>
20 #include <pybind11/stl.h>
21 #include <pybind11/functional.h>
22 #include <pybind11/eigen.h>
24 #include <pybind11_json/pybind11_json.hpp>
26 #include <nlohmann/json.hpp>
35 namespace py = pybind11;
37 using namespace py::literals;
38 using namespace cimod;
40 template<
typename IndexType,
typename FloatType,
typename DataType>
41 inline void declare_BQM( py::module& m,
const std::string& name ) {
45 using DenseMatrix = Eigen::Matrix<FloatType, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
46 using SparseMatrix = Eigen::SparseMatrix<FloatType, Eigen::RowMajor>;
48 auto pyclass_BQM = py::class_<BQM>( m, name.c_str() );
63 py::init<Eigen::Ref<const DenseMatrix>, std::vector<IndexType>, FloatType,
Vartype,
bool>(),
68 "fix_format"_a =
true )
70 py::init<Eigen::Ref<const DenseMatrix>, std::vector<IndexType>,
Vartype,
bool>(),
74 "fix_format"_a =
true )
76 py::init<
const SparseMatrix&, std::vector<IndexType>, FloatType,
Vartype>(),
82 py::init<
const SparseMatrix&, std::vector<IndexType>,
Vartype>(),
86 .def( py::init<const BQM&>(),
"bqm"_a )
87 .def(
"length", &BQM::length )
88 .def(
"get_num_variables", &BQM::get_num_variables )
89 .def(
"get_linear", py::overload_cast<IndexType>( &BQM::get_linear, py::const_ ) )
90 .def(
"get_linear", py::overload_cast<>( &BQM::get_linear, py::const_ ) )
91 .def(
"get_quadratic", py::overload_cast<IndexType, IndexType>( &BQM::get_quadratic, py::const_ ) )
92 .def(
"get_quadratic", py::overload_cast<>( &BQM::get_quadratic, py::const_ ) )
93 .def(
"get_offset", &BQM::get_offset )
94 .def(
"get_vartype", &BQM::get_vartype )
95 .def(
"get_variables", &BQM::get_variables )
97 .def(
"empty", &BQM::empty,
"vartype"_a )
98 .def(
"add_variable", &BQM::add_variable,
"v"_a,
"bias"_a )
99 .def(
"add_variables_from", &BQM::add_variables_from,
"linear"_a )
100 .def(
"add_interaction", &BQM::add_interaction,
"u"_a,
"v"_a,
"bias"_a )
101 .def(
"add_interactions_from", &BQM::add_interactions_from,
"quadratic"_a )
102 .def(
"remove_variable", &BQM::remove_variable,
"v"_a )
103 .def(
"remove_variables_from", &BQM::remove_variables_from,
"variables"_a )
104 .def(
"remove_interaction", &BQM::remove_interaction,
"u"_a,
"v"_a )
105 .def(
"remove_interactions_from", &BQM::remove_interactions_from,
"interactions"_a )
106 .def(
"add_offset", &BQM::add_offset,
"offset"_a )
107 .def(
"remove_offset", &BQM::remove_offset )
112 "ignored_variables"_a = std::vector<IndexType>(),
113 "ignored_interactions"_a = std::vector<std::pair<IndexType, IndexType>>(),
114 "ignored_offset"_a =
false )
118 "bias_range"_a = std::pair<FloatType, FloatType>( 1.0, 1.0 ),
119 "use_quadratic_range"_a =
false,
120 "quadratic_range"_a = std::pair<FloatType, FloatType>( 1.0, 1.0 ),
121 "ignored_variables"_a = std::vector<IndexType>(),
122 "ignored_interactions"_a = std::vector<std::pair<IndexType, IndexType>>(),
123 "ignored_offset"_a =
false )
124 .def(
"fix_variable", &BQM::fix_variable,
"v"_a,
"value"_a )
125 .def(
"fix_variables", &BQM::fix_variables,
"fixed"_a )
126 .def(
"flip_variable", &BQM::flip_variable,
"v"_a )
128 .def(
"change_vartype", py::overload_cast<const Vartype&>( &BQM::change_vartype ),
"vartype"_a )
129 .def(
"change_vartype", py::overload_cast<const Vartype&, bool>( &BQM::change_vartype ),
"vartype"_a,
"inplace"_a )
130 .def(
"energy", &BQM::energy,
"sample"_a )
131 .def(
"energies", &BQM::energies,
"samples_like"_a )
132 .def(
"to_qubo", &BQM::to_qubo )
133 .def(
"to_ising", &BQM::to_ising )
134 .def_static(
"from_qubo", &BQM::from_qubo,
"Q"_a,
"offset"_a = 0.0 )
135 .def_static(
"from_ising", &BQM::from_ising,
"h"_a,
"J"_a,
"offset"_a = 0.0 )
136 .def(
"interaction_matrix", py::overload_cast<>( &BQM::interaction_matrix, py::const_ ) )
139 .def(
"to_serializable", [](
const BQM&
self ) {
return static_cast<py::object
>(
self.to_serializable() ); } )
142 [](
const py::object& input ) {
return BQM::from_serializable(
static_cast<nlohmann::json
>( input ) ); },
146 if constexpr ( std::is_same_v<DataType, cimod::Dict> )
147 pyclass_BQM.def(
"_generate_indices", &BQM::_generate_indices )
149 "interaction_matrix", py::overload_cast<
const std::vector<IndexType>&>( &BQM::interaction_matrix, py::const_ ) );
152 template<
typename IndexType,
typename FloatType>
153 inline void declare_BPM( py::module& m,
const std::string& name ) {
157 py::class_<BPM>( m, name.c_str() )
166 const std::vector<IndexType>&,
176 [](
const BPM&
self ) {
177 py::dict py_polynomial;
178 const auto& poly_key_list =
self.GetKeyList();
179 const auto& poly_value_list =
self.GetValueList();
180 for ( std::size_t i = 0; i < poly_key_list.size(); ++i ) {
182 for (
const auto& index : poly_key_list[ i ] ) {
183 tuple = tuple + py::make_tuple( index );
185 py_polynomial[ tuple ] = poly_value_list[ i ];
187 return py_polynomial;
189 .def(
"get_polynomial", py::overload_cast<std::vector<IndexType>&>( &BPM::GetPolynomial, py::const_ ),
"key"_a )
190 .def(
"get_variables_to_integers", py::overload_cast<>( &BPM::GetVariablesToIntegers ) )
191 .def(
"get_variables_to_integers", py::overload_cast<const IndexType&>( &BPM::GetVariablesToIntegers ),
"v"_a )
192 .def(
"get_key_list", &BPM::GetKeyList )
193 .def(
"get_value_list", &BPM::GetValueList )
194 .def(
"get_variables", py::overload_cast<>( &BPM::GetSortedVariables ) )
195 .def(
"indices", py::overload_cast<>( &BPM::GetSortedVariables ) )
196 .def(
"get_degree", &BPM::GetDegree )
197 .def(
"get_offset", &BPM::GetOffset )
198 .def(
"get_vartype", &BPM::GetVartype )
199 .def(
"get_num_interactions", &BPM::GetNumInteractions )
200 .def(
"get_num_variables", &BPM::GetNumVariables )
201 .def(
"empty", &BPM::Empty,
"vartype"_a )
202 .def(
"clear", &BPM::Clear )
203 .def(
"remove_interaction", py::overload_cast<std::vector<IndexType>&>( &BPM::RemoveInteraction ),
"key"_a )
205 "remove_interactions_from",
208 .def(
"remove_offset", &BPM::RemoveOffset )
209 .def(
"remove_variable", &BPM::RemoveVariable,
"v"_a )
210 .def(
"remove_variables_from", &BPM::RemoveVariablesFrom,
"variables"_a )
213 py::overload_cast<std::vector<IndexType>&,
const FloatType&,
const Vartype>( &BPM::AddInteraction ),
216 "vartype"_a = Vartype::NONE )
218 "add_interactions_from",
220 &BPM::AddInteractionsFrom ),
223 "vartype"_a = Vartype::NONE )
225 "add_interactions_from",
228 "vartype"_a = Vartype::NONE )
229 .def(
"add_offset", &BPM::AddOffset,
"offset"_a )
234 "omp_flag"_a = true )
235 .def(
"energy", py::overload_cast<
const std::vector<int32_t>&,
bool>( &BPM::Energy ),
"sample"_a,
"omp_flag"_a = true )
236 .def(
"energies", py::overload_cast<
const std::vector<
Sample<IndexType>>&>( &BPM::Energies, py::const_ ),
"samples"_a )
237 .def(
"energies", py::overload_cast<
const std::vector<std::vector<int32_t>>&>( &BPM::Energies ),
"samples"_a )
243 "ignored_offset"_a = false )
247 "range"_a = std::pair<FloatType, FloatType>{ 1.0, 1.0 },
249 "ignored_offset"_a = false )
250 .def(
"change_vartype", py::overload_cast<const Vartype, const bool>( &BPM::ChangeVartype ),
"vartype"_a,
"inplace"_a )
251 .def(
"change_vartype", py::overload_cast<const Vartype>( &BPM::ChangeVartype ),
"vartype"_a )
252 .def(
"has_variable", &BPM::HasVariable,
"v"_a )
255 [](
const BPM&
self ) {
256 py::dict py_polynomial;
257 for (
const auto& it :
self.ToHubo() ) {
259 for (
const auto& index : it.first ) {
260 tuple = tuple + py::make_tuple( index );
262 py_polynomial[ tuple ] = it.second;
264 return py_polynomial;
268 [](
const BPM&
self ) {
269 py::dict py_polynomial;
270 for (
const auto& it :
self.ToHising() ) {
272 for (
const auto& index : it.first ) {
273 tuple = tuple + py::make_tuple( index );
275 py_polynomial[ tuple ] = it.second;
277 return py_polynomial;
279 .def(
"to_serializable", [](
const BPM&
self ) {
return static_cast<py::object
>(
self.ToSerializable() ); } )
282 [](
const py::object& input ) {
return BPM::FromSerializable(
static_cast<nlohmann::json
>( input ) ); },
298 .def(
"__repr__", [](
const BPM&
self ) {
299 const auto& poly_key_list =
self.GetKeyList();
300 const auto& poly_value_list =
self.GetValueList();
301 std::ostringstream out;
302 out <<
"cxxcimod.BinaryPolynomialModel({";
303 for ( std::size_t i = 0; i < poly_key_list.size(); ++i ) {
305 for (
const auto& it : poly_key_list[ i ] ) {
306 tuple = tuple + py::make_tuple( it );
308 out << tuple.attr(
"__repr__" )();
309 if ( i == poly_key_list.size() - 1 ) {
310 out <<
": " << poly_value_list[ i ];
312 out <<
": " << poly_value_list[ i ] <<
", ";
317 out <<
"Vartype.SPIN"
320 out <<
"Vartype.BINARY"
323 out <<
"Vartype.NONE"
Class for BinaryPolynomialModel.
Definition: binary_polynomial_model.hpp:168
Class for dense binary quadratic model.
Definition: binary_quadratic_model.hpp:148
void declare_BQM(py::module &m, const std::string &name)
Definition: main.hpp:41
void declare_BPM(py::module &m, const std::string &name)
Definition: main.hpp:153
BINARY
Definition: vartype.py:22
SPIN
Definition: vartype.py:21
Definition: binary_polynomial_model.hpp:139
std::vector< std::vector< IndexType > > PolynomialKeyList
Type alias for the indices of the polynomial interactions (namely, the list of keys of the polynomial...
Definition: binary_polynomial_model.hpp:151
std::unordered_map< IndexType, int32_t > Sample
Type alias for sample, which represents the spin or binary configurations.
Definition: binary_polynomial_model.hpp:162
std::vector< FloatType > PolynomialValueList
Type alias for the values of the polynomial interactions (namely, the list of values of the polynomia...
Definition: binary_polynomial_model.hpp:157
std::unordered_map< IndexType, FloatType > Linear
Type alias for linear bias.
Definition: binary_quadratic_model.hpp:111
std::unordered_map< std::pair< IndexType, IndexType >, FloatType, pair_hash > Quadratic
Type alias for quadratic bias.
Definition: binary_quadratic_model.hpp:119
std::unordered_map< std::vector< IndexType >, FloatType, vector_hash > Polynomial
Type alias for the polynomial interactions as std::unordered_map.
Definition: binary_polynomial_model.hpp:145
Vartype
Enum class for representing problem type.
Definition: vartypes.hpp:24