Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.

 View Only
Expand all | Collapse all

CPOptimizer Element Expressions

  • 1.  CPOptimizer Element Expressions

    Posted Mon December 08, 2014 04:46 PM

    Originally posted by: Chris McNeil


    I'm using CPOptimizer using the Java interface (not OPL) to build the model.  I inherited this model where a list of Situations (by integer ID) are built as constraints using a set of other constraints.  For example, I have a question that should exist conditionally based on Situation 545 being TRUE.  Under the covers Situation 545 "means" that question MajorLineOfBusiness = "Car" AND StateOfIssue = "IL" AND Market = "CHICAGO".  Running this model today this conditional constraint is built as (for display purposes only):

           cp.add(cp.IfThenElse(cp.and(cp.eq("MLOB", "Cars", cp.and(cp.eq(STATE, "IL"), cp.eq(MARKET, "CHICAGO"))), trueConstraint, falseConstraint));

    Clearly, if I could understand exactly how the element() indexing scheme worked, I could reduce these constraints down to something like:

           cp.add(cp.IfThenElse(cp.eq(SituationDomain contains 545), trueConstraint, falseConstraint)

     

    I believe it would execute much faster (we're talking several thousand logical constraints tied to many Situations) and the code would be much cleaner.

    I can see that I need a compatibility table between Situations and MLOB, State, and Market thereby reducing the Situations domain properly, and I don't expect that Situations will ever become fixed (it isn't my intention to solve for Situations). But I do need to know (by Situation ID) if the actual ID still exists in the CURRENT domain of dvar Situations.

    When I try something like:

    IloIntVar x = cp.intVar(0, 3);

    int[] xVals = new int[]{0, 1, 2, 3};

    IloIntVar[] mySet = cp.intVarArray(4, 0, 1);

    IloIntVar indexOfX = cp.intVar(0, 3);

    cp.add(cp.eq(x, cp.element(xVals, indexOfX)));

    cp.add(cp.eq(cp.element(mySet, indexOfX), 1));

    if ( cp.propagate() ) {

    System.out.println(" Domains reduced: ");

    displayDomain(cp, "x", x);  // Convenience method

    displayDomain(cp, "mySet[0]", mySet[0]);

    displayDomain(cp, "mySet[1]", mySet[1]);

    displayDomain(cp, "mySet[2]", mySet[2]);

    displayDomain(cp, "mySet[3]", mySet[3]);

    The active domains for each mySet[] dvar are always [0,1]

    Does this mean that element expressions of this type are never fixed?  I need to be able to create individual constraint for a single ID value, not necessarily for all ID values at once.

    Any light shed on this reification would be greatly appreciated.  Oh, I'm using CPOptimizer 12.6 (64-bit) on Windows 2012 with 64-bit JVM.

    Thanks!


    #CPOptimizer
    #DecisionOptimization


  • 2.  Re: CPOptimizer Element Expressions

    Posted Thu December 11, 2014 12:58 PM

    Originally posted by: ChrisBr


    Dear Chris,

    First, about the fact that "The active domains for each mySet[] dvar are always [0,1]".
    This is normal as long as (in this piece of code) there isn't any constraint which would reduce the domains. If we add one constraint, you'll see the propagated domain reduction on the "mySet" variables.
    For example let's examine the following:

    With the aim of avoiding the confusion between indices and values, lets change the domain of x such that it takes its values between 10..13 instead of 0..3.
         IloIntVar x = cp.intVar(10, 13);
        int[] xVals = new int[]{10, 11, 12, 13};

    Then we add the following constraint on x:
         cp.add(cp.eq(x, 12));
    After the propagate, the domain of mySet[2] is reduced to the value 1.

    In this sample, the propagation is from x to mySet.
    The propagation can be in the opposite (from mySet to x), for example, instead of the constraint which fixes the value of x, we can add some constraints which fix the values of myset:
         cp.add(cp.eq(mySet[2], 1));
       cp.add(cp.eq(cp.sum(mySet), 1));

    After the propagate, the domain of x is reduced to the value 12.
    Note that we need to state that only one variable in the array mySet can be equal to 1.Without this constraint, "cp.eq(cp.element(mySet, indexOfX), 1)" cannot propagate any value for the variable indexOfX because the other values remain possible.

    I hope this clarifies the element expression behaviour.

    About your specific needs, I'm not sure to understand them. Could you be more precise if you need more help?

    Regards,

    Chris.
     


    #CPOptimizer
    #DecisionOptimization


  • 3.  Re: CPOptimizer Element Expressions

    Posted Fri December 12, 2014 11:39 AM

    Originally posted by: Chris McNeil


    Thank you for the reply.  About my specific needs, I have a list of value combinations comprised of a "key" value and associated data values for 3 'questions'.  For example, the first record of over 17,000 records is [0000001, 'KY', 'Plan[144]', 'Option[007].  This data record has assigned a value of 0000001 to question values (State == 'KY') and (Plan == 'Plan[144]' and (Option == 'Option[007]').   However, rather than use a simple constraint, my pre-processing code simpy builds my constraints internally as:

    IF ((State == 'KY') AND (Plan == 'Plan[144]') AND (Option == 'Option[007]')) THEN TrueConstraint ELSE FalseConstraint

    I'm not really using the TrueConstraint and FalseConstraint, but it conveys the idea properly.

    What I'm trying now is create a Compatibility Table between the new ProducyKey dvar [1..17000+] and the relevent classifier dvars (State, Plan, and Option), listing all 17,000+ combinations.  Once the model propagates and I start "answering" my classifier "questions" (State, Plan, and Option), the compatibility table constraint has its domain reduced accordingly.  So I'd like to replace the logical constraint listed above with the MUCH simpler:

    IF (ProductKey[0000001] == 1) THEN TrueConstraint ELSE FalseConstraint

    And I have a need for the ProductKey dvar to remain multi-valued, meaning that I don't ever expect this dvar to be fixed to a single value.  Its sole purpose will be to drive an Element constraint to tell me when specific product "key" values are still in existence.

    So, for example, let's say that I've answered my 3 controlling questions and  the ProductKey dvar domain is reduced to : [234, 256, 8890, 12883, 15777, 17637].  I'd expect that my indexed Element (Boolean) dvars would all be 0 for every index value between 0 and 17000, with the exception of index positions: 234, 256, 8890, 12883, 15777, and 17637, whose Element dvars would be fixed to 1.

    I could use a custom logical constraint, I suppose, to set this array of boolean dvars but was hoping for a built-in solution.

    Does this appear like a sound approach?


    #CPOptimizer
    #DecisionOptimization


  • 4.  Re: CPOptimizer Element Expressions

    Posted Fri December 12, 2014 12:57 PM

    Originally posted by: ChrisBr


    Dear Chris,

    Lets assume:

    "for example, let's say that I've answered my 3 controlling questions and  the ProductKey dvar domain is reduced to : [234, 256, 8890, 12883, 15777, 17637].  I'd expect that my indexed Element (Boolean) dvars would all be 0 for every index value between 0 and 17000, with the exception of index positions: 234, 256, 8890, 12883, 15777, and 17637, whose Element dvars would be fixed to 1."

    So you expect that
       Element[234] == 1
       Element[256] == 1
       ...


    What would happen when ProductKey dvar domain is reduced again and, for example, 256 is removed from the domain?

    I don't understand what are dvars in your example, and also what are their domains?
    You wrote:
       IF (ProductKey[0000001] == 1)
    and
       ProductKey dvar domain is reduced to : [234, 256, 8890, 12883, 15777, 17637]

    Could you give us a little piece of code (with much less than 17000 combinations) with the aim that we'll be able to help you?

    Regards,

    Chris.
     


    #CPOptimizer
    #DecisionOptimization