It's not a problem of not finding solutions well enough, but of finding the
right solutions.
Our application is for product configuration to prepare customer quotations. A typical product model has around 500 features with 4 values on average but up to several hundred for a few features, 150 conditional assignments and about 600 restriction tables ("AllowedAssignments") with 1 to 10 columns (features) each and containing 140,000 lines in total for all tables. Of the restriction tables about half are to be only conditionally enforced based on a comparison expression involving the product features.
The model is too complex for users to find valid solutions manually, so we use Google OR-Tools to look for solutions. The tool is being used to find solutions only, not to optimize.
The product model represents the background, and additional constraints result from user decisions on certain features. The user proceeds by selecting values feature by feature. After each user decision, a request for a solution is generated to assign the rest of the features their preferred default values that are compatible with the decisions made so far. Since the solution request is done after each "user click" and has to finish before the user can proceed, it needs to return quickly.
Since the propagation is quite strong, the solutions are usually found with no or minimal backtracking (60% with no backtracking, only 10% having more than 8 failures during search).
One of the main requirements for the solutions is that they set the preferred default values. There is a ranking of features from most important to least important, and a ranking of the values from most preferred to least preferred. The ranking is not always such that the most preferred values of each feature lead to a consistent solution. For example, although the values for motor power are ranked from smallest to largest, smaller motor power being preferred, there may be another more important feature "motor type" which prevents the absolute smallest motor from being selected. If the motor power is decided first, selecting the absolute smallest motor, then the more important feature "motor type" can't get its preferred value since it has been propagated out of its domain.
Although it would be mathematically possible to define an objective function-- e.g. make an 800-bit number whose highest order bits represent the values for the most important feature, the next most significant the second most important, etc. and try to maximize the number during the solution-- such an objective will not fit in a long variable and probably more importantly, will turn the problem from a simple constraint propagation with little backtracking into an optimization problem. Our suspicion is that this would drive up the solution time, which directly affects the reaction time per click for the user.
The other suggestion, to instantiate the variables one by one in the preferred order, would entail that we worry about the backtracking in case of conflict on our side, where it certainly won't profit from the optimization of exactly this function in the solver.
We also use the custom decision builders to generate conflict resolution suggestions when the user decisions are not compatible with the model. The algorithm is described in the attachment, which we presented at the OR2021 International Conference on Operations Research hosted by the University of Bern. We use a technique similar to the one I described in the SO answer to turn constraints on and off. During the minimal conflict search, sets of constraints are tried using Assignments to their enforcement variables. We need to control exactly which constraints are active or not, turning them off and on, at each step of the algorithm.
-