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_t
is 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 anndarray
object 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_t
for 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
T
and 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_t
is 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 inx2
must 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.