https://github.com/crillab/nacre_mini
Raw File
Tip revision: 10b171a8fe3b3d0a89f3296b00be35167631ed90 authored by Gaƫl Glorian on 07 May 2018, 16:07:40 UTC
Initial commit
Tip revision: 10b171a
HOWTO
1. Introduction
---------------
This parser allows to parse a XCSP3 (core) instance using SAX mode.

2. Contents
-----------
include/  contains all headers files.
include/private contains header files necessary for the parser but not for you.
src/ contains the source files needed to compile the parser
samples/ contains an example:
         XCSP3PrintCallbacks.h which prints each entry (variable/constraint...) on the console.
         main.cc which shows how to declare your parser.
         makefile which shows the  directives needed to compile your parser (make lib creates a library).
instances/ contains some instances:
         example.xml: a fake example that contains allmost cases. Usefull to test parser
         tsp.xml: it contains only extensional constraints and is satisfiable.
         obj.xml: a small example with an objective, optimal value is 11


3. Implementation
-----------------
You need to create a class that inherits XCSP3CoreCallbacks.h and to override all (or some)
functions of this class.

class MySolverCallbacks : public  XCSP3CoreCallbacks{....}

  3.1 Managing variables.
  -----------------------
For managing variables, it seems relevant to introduce a map for making the correspondence
between the variables of the parser and the variables in your solver.
For managing constraints, we suggest to add a reference (pointer) to the problem under construction.
Here, is an example, where the problem is created when reading the tag <instance>.

class MySolverCallbacks : public  XCSP3PrintCallbacks{
    public:
        MySolver::Problem *problem;
        std::map<string,MySolver::Variable*> mapping;

    void beginInstance(InstanceType type){
            problem = new MyProblem("");
    }

    void buildVariableInteger(string id, int minValue, int maxValue) override {
        MyVariable *v = problem->createVariable(id,new DomainRange(minValue,maxValue));
        mapping[variable->id] = v;
    }

    virtual void buildVariableInteger(string id, vector<int> &values) override {
        MyVariable *v = problem->createVariable(id,new MyDomainValue(variable->domain->values));
        mapping[variable->id] = v;
    }

    // This a function transforms a vector of XVariable in vector of MyVariable
    void toMyVariables(vector<XVariable*> &src, vector<MyVariable*> &dest) {
            for(int i = 0;i<src.size();i++)
                dest.push_back(mapping[src[i]->id]);
    }

}

Remark: The parser automatically flattens all variables from arrays and calls function buildVariableInteger
for each entry of the array (with the associated name x[0], x[1]....)


  3.2 Extensional constraints
  ---------------------------
Now, if you want to deal with extensional constraints, your callback must override 3 functions:

        // The main one
        //
        virtual void buildConstraintExtension(string id, vector<XVariable *> list, vector<vector<int> > &tuples, bool isSupport, bool hasStar) {
            if(hasStar) {
                // can you manage * in tuples??
            }
            vector<Variable*> vars;
            toMyVariables(list,vars);
            problem->createConstraintExtension(problem, id, vars, tuples, support);
        }


        virtual void buildConstraintExtension(string id, XVariable *variable, vector<int> &tuples, bool isSupport, bool hasStar) {
            // This function is called for unary extensional constraint.
            // This is easy to do.
        }


        // This function is called with group of constraint where the set of tuples is exactly the same
        // than the previous one (then, you can save time/memory using the same set of tuples.

        virtual void buildConstraintExtensionAs(string id, vector<XVariable *> list, bool isSupport, bool hasStar) {
            throw runtime_error("This extension constraint contains exactly the same tuples than previous one");
        }

  3.3 Intensional constraint
  --------------------------
You have two possibilities to deal with intensional constraints, depending the value of XCSP3CoreCallbacks::intensionUsingString.
If set to true (false by default), nothing is done to help you and you need to override this function:

void buildConstraintIntension(string id, string expr) {
            // The expression is the string defined in XCSP3 format.
        }

If set to false, then a tree is constructed (see class XCSP3Tree.h) and canonized. In such a case you need to override

void buildConstraintIntension(string id, Tree *tree) {
      // The expression is the tree.
}

You can evaluate the tree using the function tree->evaluate(map<string,int>) where the map contains a value for each variable in the tree.
See the file samples/testTree.cc for an example.


Furthermore, some primitives are recognized (if XCSP3CoreCallbacks::recognizeSpecialIntensionCases
is set to true (this is the case by default)). Then, you need to override these functions:
  * void buildConstraintPrimitive(string id, OrderType op, XVariable *x, int k, XVariable *y);   // x + k op y
  * void buildConstraintPrimitive(string id, OrderType op, XVariable *x, int k);                 // x op k op is <= or >=
  * void buildConstraintPrimitive(string id, XVariable *x, bool in, int min, int max);           // x in/notin k


You can disable this feature by setting the boolean XCSP3CoreCallbacks::recognizeSpecialIntensionCases to false.


  3.4 Other constraints
  ---------------------
  You can continue to override all functions of the class XCSP3CoreCallback depending the constraints your solver manages.
  Of course, depending the constraint,  different functions are called. Here, is an example with allDiff constraint.

    void newConstraintAllDiff(string id, vector<XVariable *> list){
            vector<Variable*> vars;
            toMyVariables(list,vars);
            problem->createConstraintAllDiff(constraint->id,vars);
    }

Remark: If a group of constraints is called, a call to buildConstraintXXX  is done for each arguments of the group (the same occurs for
slide constraints).


Remark: Note that the argument list of each function does not always provides the scope of the constraint: a variable can appear twice
in the list for example or a variable can appear in the list and also elsewhere (for example in the values array).

  3.5 Options
  -----------
  The class XCSP3CoreCallbacks contains some options. We already introduced recognizeSpecialIntensionCases and intensionUsingString (see section 3.3)
  Let us introduced the two other ones:
   - recognizeSpecialCountCases: this variable (set to true by default) enables the recognition of special count constraint:
            atleast, atmost, exactly, among, exctalyVariable
   -recognizeNValuesCases: this variable (set to true by default) enables the recognition of special nValues constraint (currently NotAllEqual).


4. Classes
----------
  As it is defined in XCSP3 report, blocks of constraints identify  constraints that are semantically linked.
  Groups of constraints (or single constraints, or variables) can have the attribute class used to identify them.
  Classes allow to define multiple models in one single file. For example, class symmetryBreaking identify all variables/constraints
  used to break symmetries.
  If you want to remove such variables/constraints, you need to call the function XCSP3CoreCallbacks::addClassToDiscard.

5. TODO
-------
 - Add some primitives constraints recognition
 - Check the validity of each entry.

back to top