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

Allow finding intermediate solutions with Minizinc #251

Closed
timvandam opened this issue Mar 11, 2023 · 5 comments
Closed

Allow finding intermediate solutions with Minizinc #251

timvandam opened this issue Mar 11, 2023 · 5 comments

Comments

@timvandam
Copy link

I am trying to find all intermediate solutions for an optimization problem. CPM_minizinc does not allow this, as solve() will only return the last solution, and solveAll() does not work for optimization problems. I did not encounter this problem for the CPM_ortools model, where I can provide a callback to solve() to store all intermediate solutions myself

@timvandam
Copy link
Author

For some additional context, I pass intermediate_solutions=True to the solve() function to get multiple solutions. I am then met with the Warning: multiple solutions found, only returning last one log

@timvandam
Copy link
Author

timvandam commented Mar 11, 2023

The easiest solution would be to simply have an argument change this behavior of solve(). Or otherwise, a callback function argument that is called for each solution that was found (I suppose this is the best option). I am willing to make a PR for this if this sounds good. Let me know

@timvandam
Copy link
Author

timvandam commented Mar 11, 2023

For those looking for a workaround, I extended the CPM_minizinc class to store objective values the following way:

class MinizincSolver(CPM_minizinc):
    """
    Wrapper around CPM_minizinc that allows capturing all (intermediate) solutions,
    because CPM_minizinc abandons all but the last solution
    """

    objective_values: List[int]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.objective_values = []

    def _post_solve(self, mzn_result):
        solutions = mzn_result.solution if is_any_list(mzn_result.solution) else [mzn_result.solution]
        for sol in solutions:
            self.objective_values.append(sol.objective)
        return super()._post_solve(mzn_result)

I then call solver.solve(intermediate_solutions=True), and use solver.objective_values to access the information I need

@tias
Copy link
Collaborator

tias commented Mar 13, 2023

Hi Tim,

I think that is a very elegant solution.

To have something to main CPMpy would indeed be best with a callback, but if the above solution suits you well then I think we can leave it at that?

@timvandam
Copy link
Author

Hi Tim,

I think that is a very elegant solution.

To have something to main CPMpy would indeed be best with a callback, but if the above solution suits you well then I think we can leave it at that?

Yes, this works for me. We can leave it at that, but it may be nice for future users. However, I am not sure how common this requirement is

@tias tias closed this as completed Apr 12, 2023
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

No branches or pull requests

2 participants