How to create an iteration callback function in CasADi v3.0.0

1,627 views
Skip to first unread message

Silvia Manara

unread,
Jun 28, 2016, 9:31:43 AM6/28/16
to CasADi
Hi everybody,

I am using CasADi v3.0.0 with the Python interface and I would like to create a callback function such that it allows me to see what's going on with the solution at each iteration of IPOPT.
In CasADi v2.4.0 I used to do this by using:

@pycallback
def current_solution(f):
    opt = V(f.getOutput("x"))
    return 0

[...]

nlp = MXFunction( nlpIn( x = V ), nlpOut( f = f, g = g ) )
nlp.init()
solver = NlpSolver( "ipopt", nlp )
solver.setOption("iteration_callback", current_solution)

I tried to do something analogous with the new version of CasADi, but it does not seem to work.. What I get is the following error:

"RuntimeError:  on line 254 of file "/home/travis/build/casadi/binaries/casadi/casadi/interfaces/ipopt/ipopt_interface.cpp"
No such IPOPT option: iteration_callback"

Does anybody know how to tackle the problem?

Best regards,
Silvia

Joris Gillis

unread,
Jun 28, 2016, 10:38:22 AM6/28/16
to CasADi
Dear Silvia,

The way we implement Callbacks internally drastically altered with 3.0.0.
This caused a syntax change.
It's easiest if you pattern-match off the example: http://casadi.sourceforge.net/api/html/d7/df0/solvers_2callback_8py-example.html

Best regards,
  Joris

Mikhail Katliar

unread,
Oct 9, 2016, 3:15:20 PM10/9/16
to CasADi
Hi Joris,

Does the callback mechanism also work in MATLAB?

вторник, 28 июня 2016 г., 16:38:22 UTC+2 пользователь Joris Gillis написал:

Peter Listov

unread,
May 19, 2017, 8:59:23 AM5/19/17
to CasADi
Hello Joris,

Do I understand correctly, that the "iteration_callback" functionality available only for CasADi and IPOPT built from sources? (as 'enableipoptCallback' fix might imply) 

Best regards,
Peter

Joris Gillis

unread,
May 19, 2017, 9:02:35 AM5/19/17
to CasADi
The functionality should work from the binaries, and on Matlab as well.

Best,
  Joris

Peter Listov

unread,
May 19, 2017, 9:28:41 AM5/19/17
to CasADi
I then got a bit confused with assertion I am getting when trying to create an iteration callback in Matlab (v3.0 binaries):

Error using casadiMEX
The assertion "fcallback_.size_in(i)==size_out(i)" on line 245 of file "/Users/travis/build/casadi/binaries/casadi/casadi/core/function/nlpsol.cpp" failed.
Callback function input size mismatch

Here is code for Callback class I use. It generally mimics the aforementioned python tutorial:

classdef IterationCallback < casadi.Callback

  properties

    nx

    ng

    np

  end

  methods

    function self = IterationCallback(name, nx, ng, np)

      

      se...@casadi.Callback();

 

      self.nx = nx;

      self.ng = ng;

      self.np = np;

      

      opts.input_scheme = casadi.nlpsol_out();

      opts.output_scheme = 'ret';

      self.construct(name,opts);

      disp('Callback instance created')

    end

    

    function v=get_n_in(self)

        v=casadi.nlpsol_n_out;

    end

    function v = get_n_out(self)

        v = 1;

    end

    

    function v = get_sparsity_in(self, i)

      n = casadi.nlpsol_out(i);

      if n=='f'

        v =  casadi.Sparsity.scalar();

      elseif strcmp(n,'x') || strcmp(n,'lam_x')

        v = casadi.Sparsity.dense(self.nx);

      elseif strcmp(n,'g') || strcmp(n,'lam_g')

        v = casadi.Sparsity.dense(self.ng);

      elseif strcmp(n,'lam_p')

        v = casadi.Sparsity.dense(self.np);

      else

        v = casadi.Sparsity(0,0);

      end

    end

 

    function v = eval(self, arg)

      disp('Solver iteration')

      v = {0};

    end

  end

end



I see it comes from sanity assertion in nlpsol.cpp but further output is not available in Matlab. Would be very great full for any hint why is it happening.

Best regards,
Peter

Joris Gillis

unread,
May 19, 2017, 9:39:48 AM5/19/17
to CasADi
Let's debug.
In get_sparsity_in, make it print 'i' and 'n'.
Also, give a printout of solver.print_dimensions()/solver.printDimensions() when you disable the callback.

We are fully aware that the Callbacks are not userfriendly yet.

Best,
  Joris

Peter Listov

unread,
May 19, 2017, 10:00:02 AM5/19/17
to CasADi
Thanks a lot for helping out.

solver.printDimensions() output is:

 Number of inputs: 8
  Input 0, a.k.a. "x0", (243, 1)
  Input 1, a.k.a. "p", (0, 0)
  Input 2, a.k.a. "lbx", (243, 1)
  Input 3, a.k.a. "ubx", (243, 1)
  Input 4, a.k.a. "lbg", (180, 1)
  Input 5, a.k.a. "ubg", (180, 1)
  Input 6, a.k.a. "lam_x0", (243, 1)
  Input 7, a.k.a. "lam_g0", (180, 1)
 Number of outputs: 6
  Output 0, a.k.a. "x", (243, 1)
  Output 1, a.k.a. "f", (1, 1)
  Output 2, a.k.a. "g", (180, 1)
  Output 3, a.k.a. "lam_x", (243, 1)
  Output 4, a.k.a. "lam_g", (180, 1)
  Output 5, a.k.a. "lam_p", (0, 0)

Here is output on callback creation:

get_n_in
v = 6
get_n_out
Callback instance created

It does not seem to call 'get_sparsity_in' function.

Best regards,
Peter

Peter Listov

unread,
May 23, 2017, 10:05:47 AM5/23/17
to CasADi
Hello Joris,

I also implemented an example from the tutorial:

x   = SX.sym('x');

y   = SX.sym('y');

f   = (1-x)^2+100*(y-x^2)^2;

nlp = struct('x',vertcat(x,y), 'f', f, 'g', x+y);

fcn = Function('f', {x, y}, {f});


mycallback = IterationCallback('mycallback', 2, 1, 0);

opts = struct;

opts.iteration_callback = mycallback;

opts.ipopt.tol = 1e-8;

opts.ipopt.max_iter = 50;

solver = nlpsol('solver', 'ipopt', nlp, opts);


args = struct;

args.lbx = -10;

args.ubx = 10;

args.lbg = -10;

args.ubg = 10;


sol = solver(args)


Unfortunately it also does not pass "size_in(i) == size_out(i)" assertion.
Reply all
Reply to author
Forward
0 new messages