chocoteam / choco-solver

An open-source Java library for Constraint Programming
http://choco-solver.org/
BSD 4-Clause "Original" or "Old" License
688 stars 138 forks source link

Dealing with nogoods on Solver.reset() #491

Closed cprudhom closed 7 years ago

mwahbi commented 7 years ago

I think that dealing with the nogoodstore externally is a very good option. The best way is to leave the user to decide if the nogoodstore should be kept as it is or erased (set to null maybe) and then initialized again in solve(). Right?

jgFages commented 7 years ago

I believe they should be removed. Whether they come from failures or solutions, they come from SEARCH, hence from the "solver" and not from the "model"... so they should be removed. Nogoodfromsolutions are used to avoid finding the same solutions twice. If you reset the solver, you do want to find again those solutions.

Note that I am talking about the nogoods themselves (which means that the nogoodstores should be cleaned). If the question is "should the solver keep the instruction recordnogoodsfromsolutions" (starting with an empty set) after resetting the solver. In other words, should the nogoodconstraint remain posted but cleared or should it be removed completely (so that the user should recreate it if he wishes to use it again...). Then this is a tough question, because I think it is both a constraint and a monitor. Constraints should stay, monitors should be removed... Anyway, I would vote for removing it because even if it is a Java constraint, its semantic is related to the search process, not a solution set. To me it is not a real CP constraint.

cprudhom commented 7 years ago

I was not thinking of nogoods from solutions/restarts, but the ones from explanations. The former ones should be removed since they related to the search. About the latter, that is not as easy, since those got from failures bring new information about the mode itself. Those about solutions should be erased.

jgFages commented 7 years ago

I would prefer the reset() to have no "exceptions". I have the feeling that we could have said the same for every component (we could have let the user decide if he wants to keep or not the P, the L, the M and each monitor...). And this would be a mess.

@mwahbi do you see any valid reason to keep them?

About managing nogoods externally, I am not saying it is a bad idea, but I would prefer this decision to be based on other reasons than a reset() function.

mwahbi commented 7 years ago

@jgFages imagine you running an LNS activating Nogoodfromsolutions for a neighborhood, to not discover the same solutions as you said. But later on you select another neighborhood that includes the first one here you may want to keep them. But if the new neighborhood includes only a subset you may need to remove them. So, I think it is better to leave it to the user!

jgFages commented 7 years ago

sorry @mwahbi i do not understand your example. I still do not understand the case where you want to reset() the solver and keep the no goods

mwahbi commented 7 years ago

Imagine you are searching on a neighborhood (x1, x2, x3). You can discover some nogoods. Those nogoods are valid and it is better to keep them if you decide to search now on a new neighborhood (x1, x2, x3, x4, x6, x8). However, if you select a neighborhood like (x1, x3, x6) you need to remove the discovered nogoods. Is is clear?

cprudhom commented 7 years ago

I agree with JG. We can consider a way to facilite re-posting learnt nogoods but reset should remain with no exception. That is, clearing nogood store too.

mwahbi commented 7 years ago

@cprudhom if there is a way to re-posting learnt nogoods it is then a good solution!

jgFages commented 7 years ago

@cprudhom the case of explanations seems indeed a bit tricky. I still believe that the default action should be to remove them, because otherwise solver / reset / solve would not give the same performances, which would be strange for most users I believe. However, now you talk about those no goods, would it make sense to have a method like "postLearnedNoGoods" that would post a new constraint (a real one this time) based on the no goods it has found during search?

jgFages commented 7 years ago

ok we agree then

cprudhom commented 7 years ago

NogoodConstraint is a real constraint, it is just post behind the user back (like SatConstraint btw).

I don't want to keep constraints that rely on SatSolver (like NodoodConstraint and SatConstraint) and I will hopefully soon unplugged them by default, but that's another story.

cprudhom commented 7 years ago

Ok, I'll try to provide that asap.

jgFages commented 7 years ago

but there is still something I do not understand in what you say @mwahbi because (at least if you use the default LNS scheme of choco solver), once you are on a neighbohood, the set of frozen variables are actually somehow encoded in the search tree as decisions, so when you learn no goods, they should include the assignment of frozen variables... so if you then move to a different neighborhood, then previous nogoods should still be valid (potentially useless, but always valid)... no?

And the second thing I do not understand, is why would you reset the solver between two neighborhoods? Is the current framework too complex/inadapted?

cprudhom commented 7 years ago

An easy way to repost nogood constraint, is simply to get it before resetting the solver and then posting it once again.

Constriant ng = model.getNogoodStore();
model.getSolver().reset();
ng.post();

That does not help cleaning some nogoods from the store, but it is already not available.

jgFages commented 7 years ago

So if you want to remove nogoods:

s.reset();

If you want to clean nogoods but record them in the next solve:

s.reset();
s.setNoGoodsOnFail();

If you want to keep previous nogoods:

Constraint ng = model.getNogoodStore();
model.getSolver().reset();
ng.post();

right?

jgFages commented 7 years ago

Good, then I do not think we need anything more (i.e. maybe we could add one day a method to clean the nogoodstore without reseting the solver but we can already clean them through the reset method, so no hurry I think).

mwahbi commented 7 years ago

@jgFages I am not using the LNS scheme provided by choco solver, I implemented my own. For me frozen variables are not presented by decisions (I can not backtrack to them!) I represent them by posting dynamic constraints so I need to reset the solver in the next iteration because the frozen variables changes and my search is defined only on a part of unfrozen variables. Maybe it is a bad way to do thing!! Now why I need to do things like that? because I have parallel LNS some may lead to better UB some no, and it depends on how I can/will exploit the outputs of these parallel LNS (new solutions, new UB), I may need to keep some relevant nogoods mainly from explanations or delete those ones that are produced from solutions because when discovered my search was defined on the unfrozen variables. I hope it make sense for you! Another reason to reset the solver would be for setting correctly the limit for the new search and reset some other measures. Here I must say that I don't have the control on the whole problem!! I only have the right to make decisions for a subset of variables.

jgFages commented 7 years ago

Ok then now I understand :-) thank you!

mwahbi commented 7 years ago

Thank you