Wikunia / ConstraintSolver.jl

ConstraintSolver in Julia: Blog posts ->
https://opensourc.es/blog/constraint-solver-1
MIT License
136 stars 13 forks source link

Restricting the number of solutions? #223

Open hakank opened 3 years ago

hakank commented 3 years ago

For checking the unicity of a model (e.g. Sudoku) - or in general testing a model - it would be great if it it was possible to restrict the number of solutions to a certain number, here 2. Perhaps using the all_solution option for option_with_attributes or maybe better: a new option n_solutions.

E.,g. something like:

model = Model(optimizer_with_attributes(CS.Optimizer,   
                                         # "all_solutions"=> 2,
                                         "n_solutions"=> 2,
                                         "logging"=>[],
                                         # ...
                                        ))
Wikunia commented 3 years ago

How about max_solutions ? n_solutions sounds like if n_solutions = 2 and there is only one then the problem is infeasible or is that actually what you want?

hakank commented 3 years ago

"max_solutions"=>2 works great if it means that the solver tries to find "all solutions" but it stops after the second solution.

For my particular use case (Sudoku): I want the solver to yield at most 2 solutions. If I get only 1 solution then I'm happy, but if I actually get 2 solutions then my model is wrong, and I can then increment the number of solutions to debug the model. (The model can - of course - be wrong even if I get only one solution, but that's another thing. :-) ).

But you have a point: Perhaps there is another use case (exactly_n_solutions=2) were the solver should yield INFEASIBLE if there is only 1 solution or 3 (or more solutions). One use case for this might be automatic testing?

Wikunia commented 3 years ago

I have some problems and maybe you ( @hakank ) can help me out :wink:

If the uses the default it will compute one solution only, right? So max_solutions is by default 1 ? And when I set all_solutions = true it's basically infinite? What happens if we have a problem with objective? max_solutions is always referring to optimal solutions, correct?

I'm wondering what should happen for max_solutions => 2, all_solutions => true. Should this throw an error?

hakank commented 3 years ago

Here's my thoughts about this.

On the first question, the main rule is that max_solutions should be 1 as default. And that would give that all_solutions=true(without max_solutions flag) should then give just one optimal solution, because the default for max_solutions is 1. The other way to think is that for optimality problems then max_solutions is Infinity. I'm not sure if this mixed default is desirable.

My intuition for the specific case you state is that max_solution => 2, all_solutions => true would give (max) 2 optimal solutions.

I should also note that most FlatZinc (and other CP) solvers interprets the -a ("alll solutions") flag for optimality problems as printing all intermediate solutions (i.e. not printing all optimal solutions) which is very useful for harder problems since one then see the progress. This a great feature that would be great too also be supported.

Wikunia commented 3 years ago

Currently I have all_solutions and all_optimal_solutions. In general the -a flag is probably most helpful when using with a callback such that one can actually get the solutions during the solve call.

One could also just drop all_solutions to and be able to set max_solutions => Inf or max_solutions => :all ? Otherwise there is this weird overlap.

hakank commented 3 years ago

You have a good point: Using only one flag (max_solutions) might be better and solve the weird overlap problem. I suggest that the default value should be 1.

This would mean that the all_solutions and all_optimal_solutions flags in old models would yield syntax error, right?