Reputation: 67
I'm trying to solve an optimization problem that uses the PerspectiveQuadraticCost
function defined in Drake. According to a 2022 paper "Motion Planning Around Obstacles with Convex Optimization", a perspective quadratic cost term can capture the cost
\frac{||\dot{r}_i||_2^2}{\dot{h}_i}
which is convex, if \dot{h}_i > 0
. I see in the code GCS code base;
https://github.com/mpetersen94/gcs
that this is implemented using the PerspectiveQuadraticConstraint and solved with the MOSEK solver. I am assuming it is therefore that MOSEK is one of the solvers which considers this as a convex constraint (the PerspectiveQuadraticCost
documentation mentions that 'most' solvers consider it as non-convex).
My problem arises when I wish to do something similar, but not on the GCS class structure (consisting of edges etc.). It seems MathematicalProgram
does not have any member functions associated of the form AddPerspectiveQuadraticCost
and prog.AddCost(PerspectiveQuadraticCost,vars)
gives a non-supported GenericCost
error.
The code in GCS assigns a cost to an edge according to
H = np.vstack(((self.order) * b_ctrl, np.matmul(np.sqrt(weight_matrix), A_ctrl)))
energy_cost = PerspectiveQuadraticCost(H, np.zeros(H.shape[0]))
self.edge_costs.append(energy_cost)
for edge in self.gcs.Edges():
if edge.u() == self.source:
continue
edge.AddCost(Binding[Cost](energy_cost, edge.xu()))
which seems to be allowed (I run the code successfully). My example is as
H = np.stack(((self.order)*b_ctrl[0], weight*A_ctrl[0]))
energy_cost = PerspectiveQuadraticCost(H, np.zeros(H.shape)
self.prog.AddCost(energy_cost,self.rh_var_flat)
My question: How can I add a PerspectiveQuadraticCost
to my problem without using any of the GCS base-code (edges, convex sets)? Is this currently supported? If not, is there a specific workaround?
An additional peculiarity, which might be connected in some way, is that the L2NormCost
seems to not have been implemented for MOSEK (it throws the error ValueError: MosekSolver is unable to solve because a L2NormCost was declared but is not supported.
) after invoking self.prog.AddL2NormCost()
. However, also in the GCS code, this cost term is assigned to the edges of the graph via the Binding mentioned above.
update: it seems to be working with the SnoptSolver(), yet I need to introduce some binary variables, which is why I want to use MosekSolveR()
Thank you in advance for any help you could provide!
Upvotes: 0
Views: 132
Reputation: 5543
In both cases, Mosek (and other convex solvers) do not know how to consume these directly. You have to rewrite them using slack variables. I have a method in the GCS implementation which does exactly this, with a TODO to move it to the public API. I agree it would be useful.
In the short term, you would need to implement the objectives using slack variables and constraints yourself.
Upvotes: 1