Skip to content

Conversation

@masinag
Copy link

@masinag masinag commented Jun 5, 2025

Fix #810.

Hi, we released a new version of OptiMathSAT. The broken tests are now fixed.

I tested it on Linux and MacOS (I compiled it for arm64 only, I hope this is not a problem).
Bindings generation on Windows is still broken, but it was also broken with the previous version:

warning: I don't know what to do with 'runtime_library_dirs': ['$ORIGIN']
error: don't know how to set runtime library search path for MSVC
Traceback (most recent call last):
  File "C:\Users\sebad\Desktop\test\toRemove\Scripts\pysmt-install-script.py", line 33, in <module>
    sys.exit(load_entry_point('PySMT==0.9.7.dev334', 'console_scripts', 'pysmt-install')())
  File "c:\users\sebad\desktop\test\toremove\lib\site-packages\pysmt\cmd\install.py", line 261, in main
    installer.install(force_redo=options.force_redo)
  File "c:\users\sebad\desktop\test\toremove\lib\site-packages\pysmt\cmd\installers\base.py", line 147, in install
    self.compile()
  File "c:\users\sebad\desktop\test\toremove\lib\site-packages\pysmt\cmd\installers\optimsat.py", line 67, in compile
    SolverInstaller.run_python("./setup.py build_ext -R $ORIGIN", self.python_bindings_dir)
  File "c:\users\sebad\desktop\test\toremove\lib\site-packages\pysmt\cmd\installers\base.py", line 201, in run_python
    return SolverInstaller.run(cmd, directory=directory,
  File "c:\users\sebad\desktop\test\toremove\lib\site-packages\pysmt\cmd\installers\base.py", line 228, in run
    subprocess.check_call(program, env=environment,
  File "C:\Users\sebad\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line 373, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['c:\\users\\sebad\\desktop\\test\\toremove\\scripts\\python.exe', './setup.py', 'build_ext', '-R', '$ORIGIN']' returned non-zero exit status 1.

@mikand
Copy link
Contributor

mikand commented Jun 5, 2025

@masinag Wow! Fantastic! Thanks a lot!

Please, add yourself to the CONTRIBUTORS file as detailed here: https://pysmt.readthedocs.io/en/latest/development.html#licensing

@masinag
Copy link
Author

masinag commented Jun 5, 2025

I see that two tests are failing

FAILED pysmt/test/test_optimizing.py::test_fast_examples[optimization_example0-optimsat] - AssertionError: test_id: test: QF_LIA 2 variables multiple objective; solver: optimsat; optimization: PARETO, goal: Maximize{x}, oracle value: 1, cost returned: 0, extra: {}
FAILED pysmt/test/test_optimizing.py::test_fast_examples[optimization_example1-optimsat] - AssertionError: test_id: test: QF_LIA 2 int 2 bools multiple objective; solver: optimsat; optimization: PARETO, goal: Maximize{x}, oracle value: 1, cost returned: 0, extra: {}

but if I run the single file they pass:

pytest pysmt/test/test_optimizing.py
platform linux -- Python 3.12.3, pytest-8.4.0, pluggy-1.6.0
rootdir: /home/gabriele/Documents/pysmt
configfile: pytest.ini
collected 5 items                                                                                                                                                                                                 

pysmt/test/test_optimizing.py .....                                                                                                                                                                         [100%]

================================================================================================ 5 passed in 0.23s ================================================================================================

I am trying to figure out what is happening, do you have any ideas?

@masinag
Copy link
Author

masinag commented Jun 16, 2025

Hey @mikand, after some digging, I found out the following issue.

Sometimes, the outputs of

self._msat_lib.msat_get_model_value(self.msat_env(), msat_obj_term)

and

self._msat_lib.msat_objective_value_term(self.msat_env(), msat_obj, self._msat_lib.MSAT_OPTIMUM, None, None)

don't match. That is, the value of the objective in the optimum model and the optimum objective value are different (the latter seems to contain the correct value).
This would be expected for infinitesimal and unbounded values ---since the model only contains finite values--- but in the failing examples the value is finite, and I don't think this is expected.

Reproducibility

from pysmt.optimization.goal import MaximizationGoal
from pysmt.shortcuts import Implies, Optimizer, Symbol, Iff
from pysmt.typing import INT, BOOL
import optimathsat


x = Symbol("x", INT)
y = Symbol("y", INT)
a = Symbol("a", BOOL)
b = Symbol("b", BOOL)
c = Symbol("c", BOOL)
d = Symbol("d", BOOL)
e = Symbol("e", BOOL)
assertions = [
    Iff((0 < (x + y)), a),
    Iff((((2 * x) + (3 * y)) < -10), c),
    ((a | b) & (c | d)),
    Implies(e, (10 < x)),
    Implies((10 < x), e),
    (x <= 100),
    (y <= 100),
    a,
    b,
    e,
]

goals = [MaximizationGoal(x), MaximizationGoal(y)]

goals = [MaximizationGoal(x), MaximizationGoal(y)]

with Optimizer("optimsat") as s:
    env = s.msat_env()
    s.add_assertions(assertions)
    for _, obj_values in s.pareto_optimize(goals):
        print("Value:", end=" ")
        obj_iter = optimathsat.msat_create_objective_iterator(env)
        while optimathsat.msat_objective_iterator_has_next(obj_iter):
            _, obj = optimathsat.msat_objective_iterator_next(obj_iter)
            msat_obj_term = optimathsat.msat_objective_get_term(env, obj)
            cost_fn = s.converter.back(msat_obj_term)
            msat_model_value = s.converter.back(optimathsat.msat_get_model_value(env, msat_obj_term))
            print("(model-val {}: {})".format(cost_fn, msat_model_value), end=" ")
            msat_value = optimathsat.msat_objective_value_term(env, obj, optimathsat.MSAT_OPTIMUM, None, None)
            value = s.converter.back(msat_value)
            print("(obj-val {}: {})".format(cost_fn, value), end=" ")
        optimathsat.msat_destroy_objective_iterator(obj_iter)
        print()

with output

Value: (model-val x: 11) (obj-val x: 100) (model-val y: 100) (obj-val y: 100) 

I think this might be a bug in OptiMathSAT, but I need to investigate further, since it's very hard to reproduce.

I'll let you know if I make any progress 😄

@masinag
Copy link
Author

masinag commented Jun 16, 2025

Also, with the above example, if I dump the smt-lib file with "debug.api_call_trace=3" and feed it to the command-line executable*, it gives the correct answer 😅

*I also have to manually modify "opt.priority=par" as it is set after initialization. Maybe PySMT sets some other options?

@mikand
Copy link
Contributor

mikand commented Jun 16, 2025

Thanks for the investigation, @masinag !!

I am not aware of special options passed by PySMT, but you can have a look at the MSatOptions class in msat.py and maybe print there wahtever is used to create the config!

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

Successfully merging this pull request may close these issues.

Optimsat issues

2 participants