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

Accessing information of constraints #713

Closed
MoRic3 opened this issue Aug 1, 2023 · 9 comments · Fixed by #760
Closed

Accessing information of constraints #713

MoRic3 opened this issue Aug 1, 2023 · 9 comments · Fixed by #760
Labels

Comments

@MoRic3
Copy link

MoRic3 commented Aug 1, 2023

I am using PySCIPopt version 4.3.0 which corresponds to SCIP version 8.0.3.

I am wondering if PySCIPopt/SCIP allows to do something like the following:

Given a model object, I want to access information of a constraint. In fact, I want to know which variables appear in the specific constraint. And I want to get the constraint rule/expression, so I can use it further, e.g., for embedding it into a new constraint.

I attached code showing what I want to do using the Pyomo environment (see https://anaconda.org/conda-forge/pyomo).

Do you see any possibility of doing something similar in PySCIPopt?
Thanks a lot.

from pyomo.environ import *
from pyomo.core.expr.current import identify_variables

# define the model
def build_model():
    model = ConcreteModel()

    # define variables
    model.x1 = Var(within=Reals, bounds=(0,1))
    model.x2 = Var(within=Reals, bounds=(0,1))
    model.x3 = Var(within=Integers, bounds=(-4,1))

    # define constraint
    model.cons_nonlin0 = Constraint(expr = (1 - model.x1**2 - model.x2**2) <= 0)

    # define objective
    model.objective0_nonlin = Objective(expr = model.x2 - exp(model.x3))

    return model

model = build_model()

for c in model.component_objects(Constraint):
    var_list = list(identify_variables(c.body))
    print('appearing variables (pyomo objects):', var_list)
    
    print('constraint expression:', c.body)
    
    # add modified constraint
    model.add_component('modified_'+c.name,
                        Constraint(expr = c.body + 5 <= 0))
    
    # deactivate old one
    c.deactivate()
@Joao-Dionisio
Copy link
Collaborator

Joao-Dionisio commented Aug 1, 2023

Good morning, @MoRic3! This will not help you, but there is the printCons() method, but that just outputs the constraint to the terminal, in quite a gimmicky way:

image

But to do that, it has to access the constraint somehow. I'm gonna look at the source code and I'll let you know if I find anything.

@Joao-Dionisio
Copy link
Collaborator

I did not manage to find anything, sorry... @mattmilten @fserra, do any of you know how one would do this? Ambros asked something about it a few days ago as well and I didn't know how to answer.

@ambros-gleixner
Copy link
Member

I guess for this we would just need to interface SCIPconsGetVars(), see https://scipopt.org/doc/html/cons_8c.php#aeacdfba7623596329c1cfb1500cfdb36, right? That should not be too hard to do.

@Joao-Dionisio
Copy link
Collaborator

I think I've already done everything, Ambros, I'm only having some issues with the compilation (it's my first modification to the source code). I'm waiting for some help with it, but with the weekend and people on vacation, it may take a bit.

@ambros-gleixner
Copy link
Member

Great, thanks!

@MoRic3
Copy link
Author

MoRic3 commented Aug 7, 2023

Wow, you are awesome! I am looking forward. Thanks a lot!! Let me know if there is anything I can help with (but be aware that I have no experience with the SCIP source code yet).

@Joao-Dionisio
Copy link
Collaborator

Joao-Dionisio commented Oct 24, 2023

Hello, @MoRic3! Sorry for the extremely large delay. I think that with the new PR #732 you can now access the variables of a constraint. It doesn't yet allow you to do the modification of the constraint like you wanted, but we're getting there.

I'm getting more comfortable with this kind of stuff, so hopefully next time it won't take so long :)

EDIT: It's not exactly what you wanted, as it is for linear constraints only, but there is the addConsCoeff(), which allows you to add other variables to an already existing constraint. It's not as nice as what your code shows, but I think it might achieve what you want.

In the meantime, I am going to be working on interfacing scipAddExprNonlinear, which should helpfully do everything.

@MoRic3
Copy link
Author

MoRic3 commented Oct 26, 2023

Hello, @Joao-Dionisio ! Thanks a lot for your effort, it sounds very nice. I'll try it out and follow the updates closely.

@Joao-Dionisio
Copy link
Collaborator

Hello, @MoRic3! This ended up taking longer than expected, sorry about that. I just added PR #760 with the possibility of adding a nonlinear expression to a nonlinear constraint. If you need to use it on a linear constraint, just add a dummy variable and square it

x = m.addVar(lb=0,ub=0), m.addCons(your_linear_cons + x**2 <= right_hand_side)

The function will probably be changed in the future since it's a bit hacky, but I think it does what you want. Please let me know if it works in your own work! I ran some tests, but it seems bugs always manage to slip through :)

@Joao-Dionisio Joao-Dionisio linked a pull request Feb 2, 2024 that will close this issue
@github-project-automation github-project-automation bot moved this from Seems Harder to Done in PySCIPOpt Feb 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants