3
$\begingroup$

I have a question regarding pyomo. I have seen quite often, that for the definition of parameters, objectives and constraints, explicit functions are defined. These functions expect some arguments and in Pyomo most often they are not passed when calling. I do not understand how this is possible. Here is an example (taken from https://pyomo.readthedocs.io/en/doc-testbuild/pyomo_modeling_components/Parameters.html)

def s_init(model, i, j):
    if i == j:
        return i*i
    else:
        return 0.0
model.S2 = pyo.Param(model.A, model.A, initialize=s_init)

The function s_init requires 3 parameters: model, i, j. However when calling the function no parameter is being passed initialize=s_init. So I am wondering how this is possible? While the parameter model has been defined (maybe it can be regarded as a static variable like in Java), I have no clue where the function takes the parameters i and j from.

Can anybody tell me more about this? I'd appreciate every comment and will be quite thankful for your help.

$\endgroup$
5
  • $\begingroup$ Pyomo takes model.A to define i and j. If model.A = [1,2,3], Pyomo will iterate over this set to define i and j. $\endgroup$ Feb 11, 2021 at 10:31
  • $\begingroup$ Thanks for your answer Steven. But why can I call a function without any arguments altough the function s_init requires 3 arguments? $\endgroup$
    – PeterBe
    Feb 11, 2021 at 11:33
  • 2
    $\begingroup$ You are passing the function instead of calling it (note the absence of parenthesis) and then pyomo internally calls it. github.com/Pyomo/pyomo/blob/… $\endgroup$
    – Stradivari
    Feb 11, 2021 at 12:24
  • $\begingroup$ But where do the values i an j come from that I never specified? $\endgroup$
    – PeterBe
    Feb 12, 2021 at 13:49
  • $\begingroup$ Thanks for your answer Stradivari. But still I do not get where i and j come from. They are not defined at all in the model. $\endgroup$
    – PeterBe
    Feb 15, 2021 at 13:04

1 Answer 1

4
$\begingroup$

From the syntax used in your specific example, s_init is most likely used as a callback.

Here's a simple Python example of how this works:

>>> def get_square(val):
...     """The callback."""
...     return val ** 2
...
>>> def caller(func, val):
...     return func(val)
...
>>> caller(get_square, 5)
25

More broadly speaking, many languages, including Python and C++, also provide syntax for optional arguments to methods. Depending on the language/syntax used, they don't even need to be in a specific order. If you don't provide everything, default values will be used instead for that method, assuming the developer has coded that logic into that specific method. Param() has optional arguments, so you need to tell Python that the third argument (s_init) should be used to populate a variable called initialize with data.

In this particular case, this data is a reference to the function (s_init). You can tell by the lack of parentheses. s_init() would call the function, while s_init is a reference to the function. What happens next really depends on how that information is used by Param, but syntactically this is simply passing a reference as an optional argument.

$\endgroup$
12
  • $\begingroup$ Thanks Nikos for your answer. So what is basically done in the line "model.S2 = pyo.Param(model.A, model.A, initialize=s_init)". Is pyo.Param() a function that expects 3 arguments? One of these arguments is "initialize". When calling the pyo.Param() function we assign the function s-init to it. But why and how is the s_init function now executed? Someone has to execute it and I do not see it in the code. Is this done within the pyo.Param() function? $\endgroup$
    – PeterBe
    Feb 11, 2021 at 16:54
  • $\begingroup$ Further, I do not understand what you are talking about in the first paragraph of your answer about the functions with optional arguments. But I guess this is not so important. $\endgroup$
    – PeterBe
    Feb 11, 2021 at 16:55
  • $\begingroup$ initialize is the name of the input argument that the Pyomo devs defined for this, e.g., def Param(nikos=x,initialize=some_function). When you invoke Param you can specify which input argument s_init corresponds to by using its name: initialize=s_init. This syntax is used because Param() has numerous optional arguments, so you need to specify that the third argument you are passing is used to populate the initialize variable with data (in this case a reference to s_init) $\endgroup$ Feb 11, 2021 at 19:34
  • $\begingroup$ @PeterBe I also updated the answer, hopefully it makes more sense now. $\endgroup$ Feb 11, 2021 at 19:37
  • 1
    $\begingroup$ @PeterBe This is quite a lengthy topic that unfortunately goes beyond the scope of comments. Since this is really a programming question (rather than an OR one) I encourage you to post a question on StackOverflow about the Python-specific details of the syntax used here. $\endgroup$ Feb 15, 2021 at 15:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.