JACK: JASE Example



// A simple SChoice which enumerates a set of Finite Domains variables

public class SFDEnuChoice implements SChoice
{
    
    final private ObjectContainer vars; // variables to be enumerated
    final private ObjectContainer varNames; // only for toString()
    final private int curVar;           // index of the variable in
                                        // this particular choice
    final private SChoice continuation; // if we are finished, try
                                        // this (outputs the solution, etc.)
    private boolean isFailure; // last call to choose() resulted in a
                               // failure
    final private boolean trace;        // debug?
    
    public SFDEnuChoice(ObjectContainer vars,ObjectContainer varNames,
              int curVar,SChoice continuation,boolean trace)
    {
        this.vars=vars;
        this.varNames=varNames;
        this.curVar=curVar;
        this.continuation=continuation;
        this.trace=trace;
    }

    public SChoice choose(ConstraintSystem system,boolean firstChoice)
    {
        isFailure=false;

        Object variable=vars.get(curVar);

        // If the variable is bound, we basically do nothing.
        boolean variableIsBound=system.hasVarValue(variable);

        // Query the domain of the variable (by reading out the
        // fdEnu constraint)

        UDConstraint domainConstraint=null;
        Object firstValue=null;
        boolean hasMoreValues=false;
        nl domain=null;

        if (!variableIsBound) 
        {
            // Note that getVariableDomainConstraint() does exactly
            // the same here as getVariableDomain(), since we already
            // know that the variable is not bound.
            domainConstraint=FDUtil.getVariableDomainConstraint(system,
                                                                variable);

            if (domainConstraint!=null)
                domain=((nl)domainConstraint.getArgAt(1));

            // Empty domain -> nothing can be done. This case should not
            // happen, but does sometimes (investigate XXX TODO)
            if (domain==null || domain.first==null)
            {
                isFailure=true;
                return null;
            }

            firstValue=domain.first;
            hasMoreValues=(domain.rest!=null);
        }

        if (firstChoice)
        {
            if (!variableIsBound)
            {




                // Fix the variable to its first value

                // We can assume that the domain is not empty; in that
                // case, the solver would have removed it already.
                
                // Bind the variable (for value recovery)

                system.setVarValue(variable,firstValue);    
                
                // Also, insert a fdEnu constraint (the fd solver
                // doesn't work with bound variables). Note: although
                // this of not necessary, and of course takes a bit of
                // time, the benefit of smaller variable domains
                // outweights it for, e.g., 5-Queens, so it seems
                // worthwile.

                system.removeGoalConstraint(domainConstraint); // for performance only
                system.addGoalConstraint(new FDENUConstraint(variable,
                                                             new nl(firstValue)));
                







                // Perform a solving step

                if (!callGoal(system)) return null;


            }





            // If that was the last value, return the continuation;
            // else create an enumerator for the next variable

            if (curVar+1>=vars.size())
                return continuation;

            return new SFDEnuChoice(vars,varNames,curVar+1,continuation,trace);



        }
        else // second choice
        {

            // If no more values, we fail.

            if (variableIsBound || !hasMoreValues)
            {
                isFailure=true;
                return null;
            }





            // Remove the first value from the variable domain

            system.removeGoalConstraint(domainConstraint); // for performance only
            system.addGoalConstraint(new FDENUConstraint(variable,
                                                         domain.rest));

            // The following works, too, but is slightly less efficient:
            //      system.addGoalConstraint(new FDNEConstraint(variable,
            //                                                  firstValue));







            // Perform a solving step

            if (!callGoal(system)) 
                return null;







            // We can continue with this same SChoice

            // No problem in re-using the instance, because all member
            // variables of SFDEnuChoice are "final" anyway. Note that
            // this won't work if a subclass has its own member
            // variables, in which case we need to clone this object.

            return this;



        }


    }

    public boolean failed()
    {
        return isFailure;
    }

    public void reset()
    {
        isFailure=false;
    }





    // Activate the constraint solver
    private boolean callGoal(ConstraintSystem system)
    {

        if (!system.callGoal(trace))
        {
            
            isFailure=true;
            return false;

        }
        
        return true;

    }


    public String toString()
    {
        return "SFDEnuChoice["+varNames+", current="+curVar+"]";
    }
}

Last modified: Mon Apr 9 12:13:54 CEST 2001