alphaville / optimization-engine

Nonconvex embedded optimization: code generation for fast real-time optimization + ROS support
https://alphaville.github.io/optimization-engine/
Other
512 stars 53 forks source link

Use CasADi MX for shorter generated code #94

Closed alphaville closed 5 years ago

alphaville commented 5 years ago

I observed that CasADi generates shorter C code for functions that use the symbolic type MX instead of SX. Here's an example:

Using MX

x = cs.MX.sym('x', 3, 1)
r = cs.MX.sym('x', 1, 1)

# Some function (distance from SOC)
normx = cs.norm_2(x)
condition2 = r <= -cs.norm_2(x)
fun2 = normx**2 + r**2
condition3 = (-cs.norm_2(x) < r) * (cs.norm_2(x) > r)
fun3 = (1 - (1*normx + r)/2 * (1/normx))**2 * normx**2
y = condition2*fun2 + condition3*fun3

JF = cs.jacobian(y, x)
JFF = cs.Function('JF', [x, r], [JF])
JFF.generate('jf_mx.c')
print(JF)

Function JF is:

@1=||x||_F, @2=(((@1+x)/2)/@1), @3=(1-@2), @4=(((-||x||_F)<x)*(x<||x||_F)),
    @5=((2.*@3)*(sq(@1)*@4)), 
    @6=(((((((2.*@1)*(sq(@3)*@4))+((@2/@1)*@5))-(0.5*(@5/@1)))
        +((2.*@1)*(x<=(-||x||_F))))/@1)*x), 
    (((zeros(3x1)[0] = @6[0])[1] = @6[1])[2] = @6[2])'

Using SX

The generated function with SX is

@1=((sq(x_0)+sq(x_1))+sq(x_2)), @2=sqrt(@1), 
    @3=(((@2+x)/2)/@2), @4=(1-@3), 
    @5=(((-sqrt(((sq(x_0)+sq(x_1))+sq(x_2))))<x)*(x<sqrt(((sq(x_0)+sq(x_1))+sq(x_2))))), 
    @6=((@4+@4)*(@1*@5)), 
    @7=(((sq(@4)*@5)+((((@3/@2)*@6)-(0.5*(@6/@2)))/(@2+@2)))
        +(x<=(-sqrt(((sq(x_0)+sq(x_1))+sq(x_2)))))), 
    [[((x_0+x_0)*@7), ((x_1+x_1)*@7), ((x_2+x_2)*@7)]]

Generated code

If x has length 1000, then the generated code with MX is 4227 lines, whereas the code with SX is 12144 lines (the difference is even larger because the MX-based code contains comments every other line)

alphaville commented 5 years ago

Related issue: #98

alphaville commented 5 years ago

Both SX and MX symbols are now supported in #86.