bbopt / nomad

NOMAD - A blackbox optimization software
https://nomad-4-user-guide.readthedocs.io/
GNU Lesser General Public License v3.0
116 stars 24 forks source link

Failure in solving recurrent problems using PyNOMAD #53

Closed juantorres91 closed 2 years ago

juantorres91 commented 2 years ago

Hi, I'm devising an application for which I'm using Nomad in python as an MIP solver. I want to use PyNomad recurrently to solve several subproblems but I get the following message from the second execution of Nomad (it works well in the first one) : image

How can I avoid such problem?

Best regards, Juan José

wlav commented 2 years ago

How are you invoking optimize and which version is this? (I'm asking the latter b/c there is no encode call in PyNomad.pyx, line 46 in the latest release.)

Anyway, what's going on is the following: NOMAD is given its parameters by the Python interface by turning them into strings for the NOMAD options parser to digest. In Python3, strings (str objects) are unicode, but NOMAD wants ASCII. The encode() call turns unicode into ASCII (assuming no code points fall outside of that set, of course).

There is also the bytes object in Python3, which is a char-based string. This, of course, would not need encoding.

Since you say it fails the second execution, is param changed in between in your code? If yes, check the types of invidual parameters. If the type is bytes and you can't control its creation, convert it to str before calling optimize. For example, like so (assuming param is a list):

     for idx, p in enumerate(param[:]):
         if type(p) is bytes:
            param[idx] = p.decode('utf-8')

(I note that the code in PyNomad.pyx is a bit inconsistent: in some places it does and in some places it does not check whether the parameter type is str before encoding.)

ctribes commented 2 years ago

I agree with the suggestion proposed by wlav. I will work on a more robust and consistent management of input/ouput parameters.

juantorres91 commented 2 years ago

Hi, as you said I was able to solve the issue by imputing a copy of the parameter list every time I invoked PyNomad.optimize().

jan-provaznik commented 2 years ago

The problem lies within impurity of the optimize function. The list of parameters is passed by reference and subsequently changed in place. The caller is then left with undocumented and unexpected side-effect: a modified list of parameters.

A simple fix would be to store the encoded parameters into different list. I can turn this into a patch and a pull request, if desired.

ctribes commented 2 years ago

Yes. Please. Thanks for contributing.