1#
2#     This file is part of CasADi.
3#
4#     CasADi -- A symbolic framework for dynamic optimization.
5#     Copyright (C) 2010-2014 Joel Andersson, Joris Gillis, Moritz Diehl,
6#                             K.U. Leuven. All rights reserved.
7#     Copyright (C) 2011-2014 Greg Horn
8#
9#     CasADi is free software; you can redistribute it and/or
10#     modify it under the terms of the GNU Lesser General Public
11#     License as published by the Free Software Foundation; either
12#     version 3 of the License, or (at your option) any later version.
13#
14#     CasADi is distributed in the hope that it will be useful,
15#     but WITHOUT ANY WARRANTY; without even the implied warranty of
16#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17#     Lesser General Public License for more details.
18#
19#     You should have received a copy of the GNU Lesser General Public
20#     License along with CasADi; if not, write to the Free Software
21#     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22#
23#
24# -*- coding: utf-8 -*-
25"""
26Demonstration on how the algorithm of an MX function can be accessed and its operations can be transversed.
27"""
28
29from casadi import *
30import numpy
31
32# Create a function
33a = MX.sym('a')
34b = MX.sym('b',2)
35c = MX.sym('c',2,2)
36f = Function("f", [a,b,c], [3*mtimes(c,b)*a + b], ['a', 'b', 'c'], ['r'])
37
38# Input values of the same dimensions as the above
39input_val = [numpy.array([2.0]),\
40             numpy.array([3.0,4.0]),\
41             numpy.array([[5.0,1.0],[8.0,4.0]])]
42
43# Output values to be calculated of the same dimensions as the above
44output_val = [numpy.zeros(2)]
45
46# Work vector
47work = [ None for i in range(f.sz_w())]
48
49# Loop over the algorithm
50for k in range(f.n_instructions()):
51
52  # Get the atomic operation
53  op = f.instruction_id(k)
54
55  o = f.instruction_output(k)
56  i = f.instruction_input(k)
57
58  if(op==OP_CONST):
59    v = f.instruction_MX(k).to_DM()
60    assert v.is_dense()
61    work[o[0]] = np.array(v)
62    print('work[{o[0]}] = {v}'.format(o=o,v=v))
63  else:
64    if op==OP_INPUT:
65      work[o[0]] = input_val[i[0]]
66      print('work[{o[0]}] = input[{i[0]}]            ---> {v}'.format(o=o,i=i,v=work[o[0]]))
67    elif op==OP_OUTPUT:
68      output_val[o[0]] = work[i[0]]
69      print('output[{o[0]}] = work[{i[0]}]             ---> {v}'.format(o=o,i=i,v=output_val[o[0]]))
70    elif op==OP_ADD:
71      work[o[0]] = work[i[0]] + work[i[1]]
72      print('work[{o[0]}] = work[{i[0]}] + work[{i[1]}]      ---> {v}'.format(o=o,i=i,v=work[o[0]]))
73    elif op==OP_MUL:
74      work[o[0]] = work[i[0]] * work[i[1]]
75      print('work[{o[0]}] = work[{i[0]}] * work[{i[1]}]        ---> {v}'.format(o=o,i=i,v=work[o[0]]))
76    elif op==OP_MTIMES:
77      work[o[0]] = np.dot(work[i[1]], work[i[2]])+work[i[0]]
78      print('work[{o[0]}] = work[{i[1]}] @ work[{i[2]}] + work[{i[0]}]        ---> {v}'.format(o=o,i=i,v=work[o[0]]))
79    else:
80      disp_in = ["work[" + str(a) + "]" for a in i]
81      debug_str = print_operator(f.instruction_MX(k),disp_in)
82      raise Exception('Unknown operation: ' + str(op) + ' -- ' + debug_str)
83
84print('------')
85print('Evaluated ' + str(f))
86print('Expected: ', f.call(input_val))
87print('Got:      ', output_val)
88