14.1 Fusion API conventions¶
14.1.1 General conventions¶
All the classes of the Fusion interface are contained in the namespace mosek::fusion. The user should not directly instantiate objects of any class other than creating a Model.
Model::t M = new Model(); auto _M = finally([&]() { M->dispose(); });
The model is the main access point to an optimization problem and its solution. All other objects should be created through the model (Model.variable, Model.constraint, etc.) or using static factory methods (Matrix.sparse etc.).
The C++ Fusion implements its own reference counting and array types to improve garbage collection. The user will require the type definitions from two namespaces:
#include "fusion.h"
using namespace mosek::fusion;
using namespace monty;
The following subsections document the API extensions specific for C++.
14.1.2 C++ Arrays and Pointers¶
Arrays
All arrays in Fusion are passed as objects of type monty::ndarray wrapped in a shared pointer:
std::shared_ptr<monty::ndarray<T,N>>
where T is the type of the elements and N is an integer denoting the number of dimensions. See monty::ndarray for ways to create, manipulate and iterate over arrays and monty::new_array_ptr for array factory methods.
Shapes and indexes
The shape of arrays is defined by a type monty::shape_t, which is also used to define an \(N\)-dimensional index.
Objects and reference counting
Objects of all classes defined in the mosek::fusion namespace are wrapped in a reference counting pointer of type monty::rc_ptr. Every Fusion class C contains a definition of a type
typedef monty::rc_ptr<C> t;
for example Model::t, Variable::t etc. These pointer types should be used instead of standard pointers to ensure proper garbage collection. It is also recommended to use
a finalizer if possible, as below. For example
Model::t M = new Model("MyModel");
auto _M = finally([&]() { M->dispose(); });
Variable::t v = M->variable(5);
An object will be destroyed the moment nobody refers to it any more.
14.1.3 Using vectors¶
Standard C++ vectors can be converted into a Fusion array using monty::new_array_ptr.
std::vector<double> x(5);
// ....
auto a = monty::new_array_ptr<double>(x);
// Now we can use a in Fusion calls, eg:
auto product = Expr::dot(a, v);
Similar version of monty::new_array_ptr is available for 2D vectors:
std::vector<std::vector<double>> x({{1,1,1,1,1}, {1,2,3,4,5}});
// ....
auto product = Expr::mul(monty::new_array_ptr<double>(x), v);
For more details see monty::new_array_ptr, and monty::new_vector_from_array_ptr.
14.1.4 C++ extension reference¶
14.1.4.1 Multidimensional arrays¶
- monty::ndarray<T,N>¶
A template class for all arrays in Fusion.
- Template parameters:
T – The type of objects stored in the array.
N – The number of dimensions.
- ndarray<T,N>.ndarray<T,N>¶
ndarray(shape_t<N> shape) ndarray(shape_t<N> shape, T value) ndarray(const shape_t<N> & shape, const std::function<T(ptrdiff_t)> & fLin); ndarray(const shape_t<N> & shape, const std::function<T(const shape_t<N> &)> & fInd) ndarray(const T* vals, shape_t<N> shape) ndarray(init_t & init) template<typename Iterator> ndarray(const shape_t<N> & shape, Iterator begin, Iterator end) template<typename Iterable> ndarray(const shape_t<N> & shape, const typename const_iterable_t<Iterable>::t & that) template<typename Iterable> ndarray(const shape_t<N> & shape, const const_iterable_t<Iterable> & that) ndarray(const ndarray<T,N> & that) ndarray(ndarray<T,N> && that)
Constructor of a multidimensional array object. The initializing data can have several forms:
Default value, e.g. 0 for numerical types.
Create a new array initialized with values generated by a generator function.
auto a1 = std::make_shared<ndarray<int,1>>(shape(5), [](ptrdiff_t i) { return 5-i; }); auto a2 = std::make_shared<ndarray<int,2>>(shape(5,5), std::function<int(const shape_t<2> &)>([](const shape_t<2> & p) { return p[0]+p[1]; }));
Initialized with values from another array.
Initialized with an initializer list.
Arrays can also be constructed with the factory method
monty::new_array_ptr.- Parameters:
shape(shape_t) – The shape of the array.value(T) – The default value for all elements.fLin– An array-filling function taking the linear index as an argument.fInd– An array-filling function taking the multidimensional index as an argument.vals(T*) – An array with element values.init(init_t) – An initializer list. The typeinit_tis an \(N\)-fold nested initializer list of typestd::initializer_list. For example, for 2-dimensional arrays this is an initializer list of initializer lists, and so forth.begin, end– The pointers to an iterator.that– Another iterable object (seemonty_base.h) or anndarrayobject used as initializer.
- ndarray<T,N>.operator()¶
T& operator()(int i1, ..., int iN)
\(N\)-dimensional access operator. Returns the element at position \((i_1,...,i_N)\).
Example:
auto a = std::make_shared<ndarray<int,2>>(shape(5,5)); (*a)(3,4) = 15;
- Parameters:
i1,... iN(int) – The multi-dimensional index of the element.
- ndarray<T,N>.operator[]¶
T& operator[](int i) T& operator[](const shape_t<N> & idx)
Access operator. Returns a specific element in the array.
- Parameters:
i(int) – The linear index of the element, referring to its position in the one-dimensional row-wise flattening of the array.idx(shape_t) – The multi-dimensional index of the element.
- ndarray<T,N>.begin¶
T* begin()
An iterator pointing to the beginning of the array. Note that the iterator sees the array as a one dimensional array obtained traversing the \(N\)-dimensional array row-wise.
Example:
auto a = new_array_ptr<double,2>({ { 1.1, 2.2 }, { 3.3, 4.4 } } ); for(auto x : *a) std::cout << x << " ";
- ndarray<T,N>.end¶
T* end()
An iterator pointing to the end of the array.
- ndarray<T,N>.raw¶
T* raw()
Returns a pointer to the raw data array.
- ndarray<T,N>.size¶
size_t size()
Returns the number of elements in the array.
14.1.4.2 Shapes and indices¶
- monty::shape_t<N>¶
Represents the shape of an \(N\)-dimensional array. It is in fact an \(N\)-tuple of integers. It is also used to specify an index in an \(N\)-dimensional array.
- Template parameters:
N – The number of dimensions.
- shape_t<N>.shape_t<N>¶
shape_t(int i1, ..., int iN) shape_t(int i0, shape_t<N-1> is) shape_t(const shape_t<N> & that)
Constructor of a new shape. Shapes can also be constructed with the factory method
monty::shape.
- shape_t<N>.operator[]¶
int operator[](int i)
Return the size in a specific dimension.
- Parameters:
i(int) – The dimension.
- shape_t<N>.tolinear¶
int tolinear(const shape_t<N> & point) int tolinear(int i1, ..., int iN)
Compute the linear index of an element within this shape. The linear index is the position of the element in the one-dimensional row-wise flattening of the shape.
Example:
std::cout << shape(2,3).tolinear(1,1); // 4
- Parameters:
point(shape_t) – The coordinates of an index within the current shape.i1,...,iN(int) – The coordinates of an index within the current shape.
- shape_t<N>.begin¶
shape_iterator<N> begin()
An iterator to the shape. This iterator will traverse all indices belonging to the shape in increasing linear order, i.e. in the row-wise order in the multidimensional shape, and return a object of type
shape_tfor each index.Example:
for(auto p : shape(2,3)) std::cout << p; // (0,0)(0,1)(0,2)(1,0)(1,1)(1,2)
- shape_t<N>.end¶
shape_iterator<N> end()
An iterator pointing to the end of shape.
14.1.4.3 Reference counting pointers¶
- monty::rc_ptr<T>¶
A reference counting pointer wrapped around an object of type
T. Implements standard pointer type operators such as*and->in the expected way. For Fusion classes, the reference counting pointer typemonty::rc_ptr<C>is defined asC::t.
14.1.4.4 Exceptions¶
- monty::ArrayInitializerException¶
An exception thrown when the array initializer is incorrect, for instance a 2-dimensional array is initialized with row lists of non-equal lengths.
14.1.4.5 Auxiliary functions in the monty namespace¶
- monty::new_array_ptr¶
std::shared_ptr<ndarray<T,N>> new_array_ptr(init_t init) std::shared_ptr<ndarray<T,1>> new_array_ptr(const std::vector<T> & x) std::shared_ptr<ndarray<T,2>> new_array_ptr(const std::vector<std::vector<T>> & x2)
Create a new \(N\)-dimensional array of type
Tand wrap it in a shared pointer.Examples:
auto a1 = new_array_ptr<double,1>({ 1.1, 2.2 , 3.3, 4.4 } ); auto a2 = new_array_ptr<double,2>({ { 1.1, 2.2 }, { 3.3, 4.4 } } );
std::vector<double> x(5); // .... auto a = monty::new_array_ptr<double>(x); // Now we can use a in Fusion calls, eg: auto product = Expr::dot(a, v);
std::vector<std::vector<double>> x({{1,1,1,1,1}, {1,2,3,4,5}}); // .... auto product = Expr::mul(monty::new_array_ptr<double>(x), v);
- Parameters:
init(init_t) – An initializer list. The typeinit_tis an \(N\)-fold nested initializer list of typestd::initializer_list. For example, for 2-dimensional arrays this is an initializer list of initializer lists, and so forth.x(std::vector<T>) – A vector of typeT. The new array will have lengthx.size().x2(std::vector<std::vector<T>>) – A vector of typeT. All rows inx2must be vectors of the same length, otherwise an exception will be thrown.
- monty::new_vector_from_array_ptr¶
std::vector<T> new_vector_from_array_ptr(const std::shared_ptr<ndarray<T,1>> & a) {Convert a Fusion array into a C++ vector.
Examples:
auto a = std::make_shared<ndarray<double,1>>(shape(5)); // .... std::vector<double> v = monty::new_vector_from_array_ptr(a);
- Parameters:
a(std::shared_ptr<ndarray<T,1>>) – A one-dimensional array.
- monty::shape¶
shape_t<N> shape(int i1, ..., int iN)
Create a new shape with the given dimensions.
Example:
auto s = shape(2,3,4);
- Parameters:
i1, ..., iN(int) – The dimensions.