Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support reduced-space formulation #70

Closed
Robbybp opened this issue Aug 12, 2024 · 7 comments
Closed

Support reduced-space formulation #70

Robbybp opened this issue Aug 12, 2024 · 7 comments

Comments

@Robbybp
Copy link
Collaborator

Robbybp commented Aug 12, 2024

The documentation says:

MathOptAI.jl implements the full-space formulation. It cannot model a reduced-space formulation. We choose the full-space formulation for simplicity, and because, in our experience, "simpler" models with more variables and constraints are faster to formulate, compute derivatives of, and solve.

I believe this is actually an open research question for nonlinear problems. I've seen full and reduced space formulations each perform better for certain applications. I propose that we have an option to implement reduced-space formulations.

Longer term, it might even be nice to have a fully "black-box" formulation, where we just return to the user an external function for evaluating the predictor (along with its derivatives, if requested). This way we could potentially evaluate the predictor using something like PyTorch or Jax, which could take advantage of existing infrastructure for AD or GPU acceleration.

@odow
Copy link
Collaborator

odow commented Aug 12, 2024

I'm open to this, and at various times I had a prototype. I ended up going with simplicity in this initial version.

The reduced-space is actually quite easy to implement, since we just return expressions:

function add_predictor(model::JuMP.Model, predictor::Affine, x::Vector)
m = size(predictor.A, 1)
y = JuMP.@variable(model, [1:m], base_name = "moai_Affine")
bounds = _get_variable_bounds.(x)
for i in 1:size(predictor.A, 1)
y_lb, y_ub = predictor.b[i], predictor.b[i]
for j in 1:size(predictor.A, 2)
a_ij = predictor.A[i, j]
lb, ub = bounds[j]
y_ub += a_ij * ifelse(a_ij >= 0, ub, lb)
y_lb += a_ij * ifelse(a_ij >= 0, lb, ub)
end
_set_bounds_if_finite(y[i], y_lb, y_ub)
end
JuMP.@constraint(model, predictor.A * x .+ predictor.b .== y)

I wasn't sure whether the syntax should be:

add_predictor(model, predictor, x; reduced_space::Bool)

or

add_predictor(model, predictor, x)
add_reduced_space_predictor(model, predictor, x)

Probably the kwarg option that propagates the kwarg to nested predictors, and there is a fallback to the full-space implementation if not supported (e.g., ReLU big M?).

@odow
Copy link
Collaborator

odow commented Aug 13, 2024

See #71. I'd appreciate your thoughts.

@Robbybp
Copy link
Collaborator Author

Robbybp commented Aug 13, 2024

At first thought, I'd probably go with

add_predictor(model, predictor, x; formulation::FormulationEnum=FULL_SPACE)

Thanks for opening #71. I'll try to give it a review tomorrow.

@odow
Copy link
Collaborator

odow commented Aug 13, 2024

I've also opened #72. I think I might like that better.

@odow
Copy link
Collaborator

odow commented Aug 13, 2024

it might even be nice to have a fully "black-box" formulation, where we just return to the user an external function for evaluating the predictor (along with its derivatives, if requested)

I think this is just a user-defined operator built-in to JuMP? Or are you thinking that we would automate the derivative info, etc.

@odow
Copy link
Collaborator

odow commented Aug 14, 2024

Closed by #72

Feel free to open a new issue for the black-box thing if you wanted something other than a user-defined operator.

@odow odow closed this as completed Aug 14, 2024
@Robbybp
Copy link
Collaborator Author

Robbybp commented Aug 14, 2024

Yes, I was thinking we could automate derivative info. I don't have a concrete use case for now though, but will re-open if it comes up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants