xcsp3team / XCSP3-CPP-Parser

XCSP3 Core Parser in C++
MIT License
19 stars 11 forks source link

Tree sovler #18

Closed rafa-hub closed 5 years ago

rafa-hub commented 6 years ago

Hi,

I'm trying to use the parser to process files with intensional constraints. I can see that the following method is called: void buildConstraintPrimitive(string id,OrderType , XVariable x, int k, XVariable y){}

but the string id comes void. Besides, I can not see any formula to instantiate the Tree class solver. I see that the parser reads it, but I don't know how to access it.

Thank you in advance,

audemard commented 6 years ago

Hellon the id in the constraint declaration is optional. In such a case, it is equal to void.

Regarding the second question, I am not sure to understand it well. With a expression constraint : You have to pay attention to these variables in the parser bool intensionUsingString; if intensionUsingString= false (default) the parser constructs a Tree and the you have to override void buildConstraintIntension(string id, Tree *tree)

After that, you need to do the following to evaluate a tree : with an expression with two variables x and y : std::map tuple; tuple["x"] = 10; tuple["y"] = 20; tree->evaluate(tuple).

if intensionUsingString = true, you have to override : virtual void buildConstraintIntension(string id, string expr);

Please, let me know if I am not clear. Best. Gilles.

rafa-hub commented 6 years ago

Hi Gilles,

Thank you for your help. I would like to process files like:

ne(sub(%0,%1),%2) x[0] 1 x[1] x[0] 2 x[2] x[0] 3 x[3] x[94] 1 x[95]

And to solve the intension formula for the possible values of the tuples. I see that the callback method is buildConstraintPrimitive() and it does not work for me if I don't have the formula string in this context.

I couldn't see the parser calling to buildConstraintIntension() method.

Could you please be so kind to help me to cope with this?

Kind regards, Rafael

audemard commented 6 years ago

Hello, when dealing with your expression I obtain : intension constraint using canonized tree: : ne(sub(x[1],x[2])) with the XCSP3PrintCallbacks.h (which just prints all entries).

Then, you need to override the callback void buildConstraintIntension(string id, Tree *tree) the tree will allow you to evaluate the expression using the function Tree::evaluate

Gilles.

rafa-hub commented 6 years ago

Thank you Gilles for your help, I followed your instructions and it works.

Please, let me state what I have seen, and please, let me know your opinion.

If intensionUsingString=false when an expression has logical operators => void buildConstraintIntension(string id, Tree tree) is called. if the expression only contains quantity comparators => void buildConstraintPrimitive(string id,OrderType , XVariable x, int k, XVariable *y) is called.

If intensionUsingString=true Then void buildConstraintIntension(string id, Tree *string) is called anyway and it works fine.

But I have to change the code of the following method: XCSP3Manager::newConstraintIntension(XConstraintIntension *constraint) in order to avoid an exception to be thrown. I don't like to modify your code, if you have any better solution for that, I'll be greatful.

kind regards, Rafael

xcsp3team commented 6 years ago

Could you show me the modification you made in the code of this function.

Kind regards. Gilles.

rafa-hub commented 6 years ago

The modification is as follows, please, let me know if it is correct or if there are better options.

void XCSP3Manager::newConstraintIntension(XConstraintIntension *constraint) {

// Modified ................................................
if(callback->intensionUsingString) {
    callback->buildConstraintIntension(constraint->id, constraint->function);
    return;
}
// ...............................................

if(callback->intensionUsingString && callback->recognizeSpecialIntensionCases)
    throw std::runtime_error("You have to choose: using string or be able to recognize special intension constraints");
if(discardedClasses(constraint->classes))
    return;
 if(callback->intensionUsingString) {
    callback->buildConstraintIntension(constraint->id, constraint->function);
    return;
}
xcsp3team commented 6 years ago

You raise an interesting question.

My original code was : if(callback->intensionUsingString && callback->recognizeSpecialIntensionCases) throw std::runtime_error("You have to choose: using string or be able to recognize special intension constraints");

I wanted to highlight to users that if they use intensionUsingString, the parser is not able to recognize the primitives.

Are you using intensionUsingString ? If yes, you must disable recognizeSpecialIntensionCases

In your code, the runtime_error can never be called.

rafa-hub commented 6 years ago

Thank you Gilles for your help.

audemard commented 6 years ago

You are welcome.

rafa-hub commented 6 years ago

If you don't mind, I have another point to comment.

So, as far as I see, what happens is that:

if intensionUsingString is false: then I have the tuples, but I don't have the formula.

if intensionUsingString is true: then I have the formula, but I don't have the tuples.

Dealing with Extension Constraints, with list variables I am able to keep all the tuples when buildConstraintExtension() is called the first time, so I can use the tuples every time buildConstraintExtensionAs() is called.

Could it be possible to do something similar with Intension Constraints?

rafa-hub commented 5 years ago

Hi! I am working on this again and I see you have done a great job with tree solving. Thank you for your effort. I see that now the Tree object can be send as a parameter, and then all data is available at the method. I would like to comment a small issue that it didn't happen before. At the method:

void buildConstraintPrimitive(string id, OrderType , XVariable x, int k, XVariable y){}

I have verified that OrderType has the same value of 0 for le and ge. I have verified that OrderType has the same value of 1 for lt and gt. With all versions of the parser, I think that OderType for ge was 2 and for gt was 3. am I right? Could it be possible to change it?

rafa-hub commented 5 years ago

Sorry for a typo, "with all versions of the parser", I would like to write: "with old versions of the parser."

audemard commented 5 years ago

Hello thanks for your feedback. In fact, I standardize all expressions (using function canonize) and then, in case of x > y I change the expression in y < x then, you only have LE (or EQ or NE) operator in this callback.

rafa-hub commented 5 years ago

Thank for your answer, it looks a cleaner solution. Thank you for your help.