RobotLocomotion / drake

Model-based design and verification for robotics.
https://drake.mit.edu
Other
3.19k stars 1.25k forks source link

clean up / sugar needed for mathematical program's use of symbolic::Polynomial #10839

Open RussTedrake opened 5 years ago

RussTedrake commented 5 years ago

See, for example: https://github.com/RussTedrake/underactuated/blob/pend_global_sos/src/pendulum/global_sums_of_squares.ipynb

Our prog.New__Polynomial methods return Polynomial objects. But these objects don't play well with other symbolic variables, etc. So I end up calling .ToExpression() on them almost immediately almost always. I've found this confusing to students/collaborators as well.

I see a few possible remedies:

Thoughts?

hongkai-dai commented 5 years ago

I think there is a tradeoff between ease of use and speed. I guess you don't like to use the returned polynomial directly, because this polynomial will be used later in other symbolic operations, and it is easier to apply these operations to symbolic Expression, rather than on symbolic Polynomial. For example, in your code

V = prog.NewFreePolynomial(Variables(x), deg_V).ToExpression()
constraint1 = prog.AddSosConstraint(V - eps*(x-x0).dot(x-x0))  # V is strictly positive away from x0
Vdot = V.Jacobian(x).dot(f)

On the other hand, after you apply these symbolic operations, eventually you need to convert the symbolic expression back to symbolic polynomial, so as to impose the sum-of-squares constraint (MathematicalProgram decomposes the symbolic Expression to symbolic Polynomial when calling AddSosConstraint); for example here

constraint2 = prog.AddSosConstraint( -Vdot - L*(s**2+c**2-1) - eps*(x-x0).dot(x-x0)*s**2 )

Converting the symbolic expression to symbolic polynomial is computationally expensive. I think for this simple example you probably don't see the slowdown coming from the conversion. But when I worked on SOS problem with complicated polynomials (> 1,000 terms in one polynomial, which could happen for a 4th-order polynomial with 7 indeterimates), this conversion could eat a big chunk of time.

As a result, when I worked on SOS, I use exclusively symbolic::Polynomial, but not symbolic::Expression. For example, I will create eps * (x - x0).dot(x- x0) as a symbolic::Polynomial, and then use the operation "+, - " between the symbolic polynomial V and `eps (x-x0).dot(x - x0)`.

I think there are two possible solutions

  1. Make it really easy to create the symbolic polynomial like (x - x0).dot(x - x0)
  2. Improve the speed to convert a symbolic Expression to symbolic Polynomial.