Modify Optaplanner Vehicle Routing Problem vehicleRoutingScoreRules.drl to erase Hard constraint - optaplanner

I want to modify the optaplanner example vehicle routing problem to erase Hard contraint and convert it to vrp no cvrp. I try to comment Hard contraints at vehicleRoutingScoreRule.drl, but it does not change anything.
//############################################################################
// Hard constraints
// ############################################################################
/*rule "vehicleCapacity"
when
$vehicle : Vehicle($capacity : capacity)
accumulate(
Customer(
vehicle == $vehicle,
$demand : demand);
$demandTotal : sum($demand);
$demandTotal > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, $capacity - $demandTotal);
end
*/

Done!, it was that in the classpath i didn't remove the optaplanner-examples.jar.
Thanks,

Related

Drools rule using accumulate

Hello I it is my first time involved in drools project. I have created some simple rules that work fine, however I have trouble with more complex rules that use the accumulate function. Below I have this rule.
rule "1"
no-loop
when
$msg : Declaration(header.totalGrossMassMeasure != null,
header.totalGrossMassMeasure.compareTo(BigDecimal.ZERO) > 0 )
result : ValidationResult()
$netValue : Number() from accumulate (
GoodsItemsType($net : netNetWeightMeasure),
sum($net.doubleValue())
)
eval($netValue.doubleValue() > ($msg.getHeader().getTotalGrossMassMeasure().doubleValue() + (0.45 * $msg.getGoodsItems().size())))
then
RulesValidationError error = new RulesValidationError();
error.setErrorType(ErrorType.INCORECT_VALUE);
result.getErrorsList().add(error);
end
the concept is to sum the net value from a list of goodsItemType object and compare the sum to the total gross mass measure multiplied by one buffer number. The problem is I have been trying last couple of days not being able to fire the rule with anything. Could someone please help me?

Drools Knapsack Optaplanner

I try to solve the Knapsack-Problem with the Optaplanner by using drools. Did someone this before? This refers to the example by optaplanner.
Thanks for your help
I have implemented these rules as follows:
rule "weigth"
dialect "java"
when
$knapsack : Knapsack($capacity : capacity)
$weightTotal : Number(intValue > $capacity) from accumulate(
Item(
$weight : weight),
sum($weight)
)
then
scoreHolder.addHardConstraintMatch(kcontext, $capacity - $weightTotal.intValue())
end
Presuming Item is your planning entity and that it has a planning variable boolean used, then you 'll want to only check the items that are used == true:
... from accumulate(
Item(used == true,
$weight : weight),
sum($weight)
)

Drools accumulate method that returns zero if no matching source fact

I am trying to implement a rule in Drools that calculates the sum of a some property of a fact. That works great using accumulate and sum. The problem is that when there are not fact that matches the criteria in the source part of the accumulate method the rule is not executed.
I would like the sum method to return zero if no fact is matching and that the rest of the when clauses is checked. Is that possible somehow?
Update:
I am using Drools 6.0.1
The problem seems to lie in the the and clause. Here is a code that is my problem.
rule "accu"
when
$n: Number()
from accumulate( $o: Order() and OrderLine( $v: quantity ),
sum($v))
then
System.out.println("*#*#*#*#*#*#*#*#*#* Accu has fired *#*#*#*#*#*#*#*#*#");
end
With only Order or OrderLine it works. I have a feeling I am attacking the problem the wrong way. In my real case the value I want to sum up is in the OrderLine but the criteria is in another class.
$ol : OrderLine($q : quantity)
and
$ac : ArticleClass(orderLine == $ol, crtiteria1=efg, criteria2=abc)
But accumulate does return 0 when there are no matching elements.
rule accu
when
$n: Number()
from accumulate( Fact( prop == "C", $v: value ),
sum($v))
then
//...
end
This fires in the absence of Fact facts with prop == "C" and it fires if there are no Fact facts at all. (Drools 5.5.0)
Please provide full code reproducing the error, Drools version, etc.

Salience value nos working correctly when mixing XLS and DRL files?

I have different rules defined in DRL text files and XLS spreadsheet files. My XLS rules are executed first I am not able to understand why. The example is to manage a form with different categories and answers. The answer has a score that is used to return the user some information.
My first DRL rule is to sum all scores from all questions in a category:
package Form;
import ...;
rule "Sum Category Score"
salience 500
when
$form : SubmittedForm();
$cat : CategoryWithScore(score == null) from $form.categories;
$categoryScore : Number() from
accumulate($q : Question() from $cat.getQuestions(),
init( int $total = 0 ),
action( $total += $q.getAnswer().getScore(); ),
reverse( $total -= $q.getAnswer().getScore(); ),
result( $total )
);
then
$cat.setScore($categoryScore);
end
And with a XLS file, I define the result of a category depending on the total score.
As we can see, the DRL file has salience 500 and the XLS file has salience 250. Then I expect that the DRL rule is executed first.
If I print the XLS in rule format, everything seems correct:
package ScoreClassification;
//generated from Decision Table
import ...;
no-loop true
salience 250
// rule values at B13, header at B8
rule "Form Score Classification_13"
when
$form : SubmittedForm(); $cat : CategoryWithScore($cat.getText() == 'Cat1', $cat.getScore() >= 0, $cat.getScore() < 40) from $form.getCategoriesWithScore();
then
$cat.setResult('Good');
end
// rule values at B14, header at B8
...
I have put some simple System.out.println in the methods getScore and setScore of the category, to see what is happening. And I can see that getScore is executed first! (and has null value) and later setScore that assign correctly the value.
Why salience is not respected?
Three things.
First, you must use modify to effect a change of a fact in working memory.
rule "Sum Category Score"
...
then
modify( $cat ){ setScore( $categoryScore ) }
end
Otherwise, rule evaluation will never see the changed value.
Added after OPs 1st comment
Second, if the modification is in an object held in a collection within a fact and extracted using from, things begin to get murky. I avoid this, and recommend you to do the same. Insert the CategoryWithScore facts, and your problem is solved. (You may have to ascertain that the selected CategoryWithScore facts belong to the same SubmittedForm, if there is more than one form in WM at the same time.)
Third, it is a common misconception that priority (or salience) has an effect on the ordere of left hand side evaluations, and can be used to delay the evaluation of a rule where, constraint expressions may run into NPEs. It is best practice to write constraints so that null values result in a short-circuited false.
If you think that this clutters rules: yes, you are right. But even pure Java code is more robust when class members are set to some default or out-of-band value (might be -1 in your case) rather than left at null.

Conceptual meaning of 'not' keyword; evaluating between objects

I am trying to find a BucketTotal object which has the smallest total in a Drools Planner project. I adapted this from example code.
rule "insertMinimumBucketTotal"
when
$b : BucketTotal($total : total)
not BucketTotal(total > $total) // CONFUSED HERE
then
insertLogical(new MinimumBucketTotal($total));
end
As far as my reasoning went, it meant "find BucketTotal object $b, such that there doesnt exist another BucketTotal object whose total is greater than total of $b".
Turns out, it meant the opposite (and I corrected it).
Please explain how Drools reasons that statement to find $b.
Indeed your are confusing things. "not" means "not exists". So if you want to find the minimum total you can do:
rule "minimum"
when
BucketTotal( $min : total )
not BucketTotal( total < $min )
then
// do something with $min
end
The above is usually the more performant way of doing it, but you can also use accumulate if you prefer:
rule "minimum"
when
accumulate( BucketTotal( $total : total ),
$min : min( $total ) )
then
// do something with $min
end

Resources