mesmo-dev / mesmo

MESMO - Multi-Energy System Modeling and Optimization
https://mesmo-dev.github.io/mesmo
MIT License
48 stars 11 forks source link

Optimization solver interfaces #11

Closed stroitzsch closed 3 years ago

stroitzsch commented 3 years ago

Optimization problem setup through cvxpy is slow for large test cases in FLEDGE (which seems to be a known issue: https://github.com/cvxpy/cvxpy/issues/708, https://github.com/cvxpy/cvxpy/issues/1159, https://github.com/cvxpy/cvxpy/issues/706). I'd like to try adding direct optimization solver interfaces to see if we can get better performance. To keep things clean & make switching interfaces easier in future, we will need some internal abstractions to define optimization variables / constraints / objective.

stroitzsch commented 3 years ago

This is being implemented on branch feature/solver_interfaces and in pull request #12.

tomschelo commented 3 years ago

@stroitzsch I just pushed my first attempt, however, I cannot get it to work properly. When trying to solve, it returns "unfeasible or unbounded". However, Gurobi's "Coefficient statistics" are equal to the ones produced by the equivalent problem solved with cvxpy.

One key difference I encountered is that gurobipy forces your to define "x_vector" as a 1-D array --> shape=(len(variables), ) instead of shape=(len(variables), 1). Otherwise you cannot formulate a matrix-based constraint. Maybe I did something wrong in reshaping x and b?

stroitzsch commented 3 years ago

@tomschelo I think the issue was in the variable definition.

Looks like Gurobi defaults the lower bound to zero: image

So we've got to explicitly set it to negative infinity:

x_vector = (
    gurobipy_problem.addMVar(
        shape=(len(self.variables), ),
        lb=-np.inf,
        ub=np.inf,
        vtype=GRB.CONTINUOUS,
        name='x_vector'
    )
)

I'll fix and push this.

stroitzsch commented 3 years ago

Retrieving duals & broadcasting done!

kaiATtum commented 3 years ago

whats broadcasting?

stroitzsch commented 3 years ago

@kaiATtum Check standard_form_example: Basically repeated matrix operation along an index dimension. E.g. state equation repeated for all timesteps. Broadcasting implementation avoids for-loops like for timestep in timesteps.

stroitzsch commented 3 years ago

@tomschelo I've fixed the grid constraint equations: Basically there was as in error in the way that constants were repeated for all timesteps with np.repeat(). To avoid this in future, I've enabled broadcasting for constants. Looks a bit hacky, because you have to set an index key set for the constants, but works fine.

I've also slightly rewritten the equations. The new formulation uses diagonal matrix multiplications to replace some of of the numpy broadcasting operations. This way we retain the sparse matrices, which may be useful for performance with bigger problems.

stroitzsch commented 3 years ago

I've also added "parameters" in the latest commits: Parameter values can be set with define_parameter(name, value), then the name string can be used in place of numerical values in define_constraint()

stroitzsch commented 3 years ago

Redefine model class methods also done. - Some testing / bugfixing / cleanup remains to be done.