Forum Discussion

FICO's avatar
FICO
Community Manager
6 years ago

Forum Post

Is it reasonable to declare constraints in a procedure? The behaviour illustrated by the following Mosel suggests that it is not

model ModelName

uses "mmxprs"

declarations

x: array(1..2) of mpvar

end-declarations

objective:= x(1)

forward procedure defineConstraint(RHS: real)

forward procedure report

defineConstraint(2)

maximize(objective)

report

defineConstraint(1)

maximize(objective)

report

defineConstraint(2)

maximize(objective)

report

procedure defineConstraint(RHS: real)

Constraint := x(1) + x(2) <= RHS

end-procedure

procedure report

writeln("Objective = ", getobjval, ": x = [", getsol(x(1)), ", ", getsol(x(2)),"]")

end-procedure

end-model

1 Reply

  • FICO's avatar
    FICO
    Community Manager

    The form of the procedure 'defineConstraint' your model (local definition of a constraint name) is the same as writing out this full form:

    procedure defineConstraint(RHS: real)

     declarations

       Constraint: linctr

     end-declarations

     Constraint := x(1) + x(2) <= RHS

    end-procedure

    That is, the model entity named ‘Constraint’ only exists locally in your procedure and the next time you enter the procedure again a new one is created and hence a new constraint is added to the underlying optimization problem: you can observe this cumulative effect of constraint definition by adding this line into your ‘report’ routine:

      exportprob("", objective)

    This means that you obtain by-and-large the same behaviour as with this anonymous constraint version:

    procedure defineConstraint(RHS: real)

      x(1) + x(2) <= RHS

    end-procedure

    In Mosel, the underlying optimization problem collects all constraints that are defined, including in subroutines, independent on whether they are named or not (this is in order to make it possible to employ subroutines for the definition of algorithms and any more complicated forms of model definition that may occur in larger projects).

    There are 2 ways how to address the problem:

    1. Define your constraints globally (by adding them into a ‘declarations’ block outside of any subroutine), so that every call to ‘defineConstraints’ redefines the same model entity (and hence overwrites the constraint definition in the underlying optimization problem):

    declarations

     x: array(1..2) of mpvar

     Constraint:linctr

    end-declarations

    2. Create individual problems for every constraint definition/solver call (note that the full set of constraints needs to be stated within every ‘mpproblem’, including unary constraints on variables such as ‘is_binary’):

    with mpproblem do

     defineConstraint(1)

     maximize(objective)

     report

    end-do