Search code examples
c++optimizationconvex-optimizationmosek

How to fix DimensionError?


I am having a strange error still could not figure it out.

#include <iostream>
#include "fusion.h"

using namespace mosek::fusion;
using namespace monty;

int main(int argc, char ** argv)
{

  int number_of_steps = 7;
  int lambda1 = 1000;
  int lambda2 = 1000;
  int dim_space = 3;
  auto A = new_array_ptr<double, 2>({ {-0.1504 ,   0.5675 ,  -0.7252},
                                      {-0.4518,    0.0456  ,  0.0530},
                                      {0.2635 ,  -0.1113 ,  -0.2546},
                                      {-0.0495 ,  -0.2224  ,  0.1030},
                                      { 0.1216,   -0.2716 ,   0.0503},
                                      { 0.2000  , -0.2788 ,   0.1627},
                                      {0.3534 ,  -0.2255  ,  0.1733},
                                      { 0.2737 ,  -0.2614 ,   0.1941},
                                      {0.3001,    0.1014 ,   0.3227},
                                      { 0.2473 ,   0.0765  ,  0.3377}});
  
  auto b = new_array_ptr<double, 2>({{0.3597},
                                    {0.8894}, 
                                    {0.9238}, 
                                    {0.9682}, 
                                    {0.9534}, 
                                    {0.9251},
                                    {0.8912},
                                    {0.9050},
                                    {0.8919},
                                    {0.9050}});

  auto b_rep = new_array_ptr<double, 2>({{0.3597, 0.3597, 0.3597, 0.3597, 0.3597, 0.3597, 0.3597},
                                    {0.8894, 0.8894, 0.8894, 0.8894, 0.8894, 0.8894, 0.8894}, 
                                    {0.9238,0.9238, 0.9238,0.9238, 0.9238,0.9238, 0.9238}, 
                                    {0.9682, 0.9682, 0.9682, 0.9682, 0.9682, 0.9682, 0.9682}, 
                                    {0.9534, 0.9534, 0.9534, 0.9534, 0.9534, 0.9534, 0.9534}, 
                                    {0.9251, 0.9251, 0.9251, 0.9251, 0.9251, 0.9251, 0.9251},
                                    {0.8912, 0.8912, 0.8912, 0.8912, 0.8912, 0.8912, 0.8912},
                                    {0.9050, 0.9050, 0.9050, 0.9050, 0.9050, 0.9050, 0.9050},
                                    {0.8919, 0.8919, 0.8919, 0.8919, 0.8919, 0.8919, 0.8919},
                                    {0.9050, 0.9050, 0.9050, 0.9050, 0.9050, 0.9050, 0.9050}});

  Model::t M = new Model();
  auto x = M->variable(new_array_ptr<int,1>({dim_space, number_of_steps}), Domain::unbounded()) ;
  Matrix::t recipe = Matrix::dense(A);

  // This way does not work,
  // for (int i = 0; i < number_of_steps; i++)
  // {
  //   auto x_i = Var::vstack(x->index(0,i), x->index(1, i), x->index(2, i));
  //   M->constraint(Expr::mul(recipe, x_i), Domain::lessThan(b));
  // }
  
  // This is working fine
  M->constraint(Expr::mul(A, x), Domain::lessThan(b_rep));
}

Here when I use M->constraint(Expr::mul(A, x), Domain::lessThan(b_rep)); expression it working fine. But the same thing can be done in the following way which does not work,

for (int i = 0; i < number_of_steps; i++)
{
     auto x_i = Var::vstack(x->index(0,i), x->index(1, i), x->index(2, i));
     M->constraint(Expr::mul(recipe, x_i), Domain::lessThan(b));
}

I am getting the following error

terminate called after throwing an instance of 'mosek::fusion::DimensionError'
  what():  Mismatching expression and domain
Aborted (core dumped)

Solution

  • The shape of b is (1,10) and the shape of the expression is (10). It will work if you do

      auto b = new_array_ptr<double, 1>({0.3597,
                                        0.8894, 
                                        0.9238, 
                                        0.9682, 
                                        0.9534, 
                                        0.9251,
                                        0.8912,
                                        0.9050,
                                        0.8919,
                                        0.9050});
    

    Alternatively you can also use the same b as before, but as domain use

    Domain::lessThan(b)->withShape(new_array_ptr<int,1>({10}))
    

    The vectorized variant that works fine is, however, most recommended.