xcsp3team / pycsp3

A Python Library for modeling combinatorial constrained problems
https://www.pycsp.org
MIT License
60 stars 9 forks source link

AllEqual Constraint Fails with Single-Value Domain in ACE Solver #50

Closed frestyle closed 3 weeks ago

frestyle commented 1 month ago

When using the ACE solver with PyCsp3, the AllEqual constraint (or NValues == 1) fails if a domain variable is limited to one value. This issue occurs even when the constraint should be satisfied trivially.

Steps to Reproduce

  1. Create a PyCsp3 model with a 2D VarArray where one column has a single-value domain.
  2. Apply an AllEqual constraint to the single-value column.
  3. Attempt to solve the model using the ACE solver.

Example Code

from pycsp3 import *

def main():
    clear()

    def domain_y(i,j):
        if j == 0:
            return set(range(10))
        elif j == 1:
            return set(range(1))  # Single-value domain
        else:
            return set(range(10))

    x = VarArray(size=[5,3], dom=domain_y)  

    satisfy(
        [
            AllEqual(x[0][1], x[1][1], x[2][1], x[3][1], x[4][1])
        ]
    )

    instance = compile()
    ace = solver(ACE)
    result = ace.solve(instance, verbose=True)

    if result is SAT:
        print("Solution: ", values(x))
    else:
        print(f"result {result.name}: ")

if __name__ == "__main__":
    main()

Current Behavior

The ACE solver fails to solve the model, producing the following error:

ACE v2.3

  instance
    name:main

  Loading variables...

! ERROR: 
  Use the solver option -ev for more details

Expected Behavior

The solver should recognize that the AllEqual constraint is trivially satisfied for the column with a single-value domain and proceed to solve the rest of the model.

Additional Context

Environment

Questions

  1. Is this a known limitation of the ACE solver when used with PyCSP3?
  2. Is there additional debugging information that can be provided to help investigate this issue?

Thank you for your assistance in resolving this problem.

xcsp3team commented 3 weeks ago

Thanks for pointing out the issue.

In general, if you have an XCSP3 instance (file), as e.g., TestAllEqual.xml:

<instance format="XCSP3" type="CSP">
  <variables>
    <array id="x" size="[5][3]">
      <domain for="x[0][0] x[0][2] x[1][0] x[1][2] x[2][0] x[2][2] x[3][0] x[3][2] x[4][0] x[4][2]"> 0 1 2 3 4 5 6 7 8 9 </domain>
      <domain for="x[][1]"> 0 </domain>
    </array>
  </variables>
  <constraints>
    <allEqual> x[][1] </allEqual>
  </constraints>
</instance>

If you use the option "-ev" java ace TestAllEqual.xml -ev you get the trace where the problem rises:

java.lang.Exception
    at utility.Kit.control(Kit.java:169)
    at utility.Kit.control(Kit.java:179)
    at constraints.global.AllEqual.<init>(AllEqual.java:97)
    at problem.Problem.allEqual(Problem.java:1644)
    at problem.XCSP3.buildCtrAllEqual(XCSP3.java:461)
    at org.xcsp.parser.loaders.CtrLoaderInteger.allEqual(CtrLoaderInteger.java:415)
    at org.xcsp.parser.loaders.CtrLoaderInteger.load(CtrLoaderInteger.java:202)
    at org.xcsp.parser.callbacks.XCallbacks.loadCtr(XCallbacks.java:542)
    at problem.XCSP3.loadCtr(XCSP3.java:345)
    at org.xcsp.parser.callbacks.XCallbacks.loadConstraints(XCallbacks.java:444)
    at org.xcsp.parser.callbacks.XCallbacks.loadConstraints(XCallbacks.java:422)
    at org.xcsp.parser.callbacks.XCallbacks.loadInstance(XCallbacks.java:305)
    at org.xcsp.parser.callbacks.XCallbacks.loadInstance(XCallbacks.java:328)
    at problem.XCSP3.model(XCSP3.java:159)
    at problem.Problem.<init>(Problem.java:720)
    at main.Head.buildProblem(Head.java:400)
    at main.Head.solveInstance(Head.java:431)
    at main.Head.run(Head.java:447

Here, the problem is the control made at line 97 of AllEqual.java If we replace, values.length >1 by values.length >=1, the problem is fixed (the propagator is fine for this extreme case).

You can also write if solve(options="ev") is SAT or in you code, ace.setting("-ev")

This has been fixed (and pushed) in the code on Github for ACE. (note that you can build a jar instance from this repository, and replace the jar from the PyCSP3 distribution, if deployed on your machine).

This will be part of the next PyCSP3 version (including Pypi one) that is planned around the beginning of september.

Best.

frestyle commented 3 weeks ago

Thank you so much for fixing this issue! really appreciate.