Reputation: 1
I am trying to reuse the project job scheduling example in the 7.4.1.Final distribution. I changed projectJobSchedulingSolverConfig.xml
file to use
<scoreDrl>org/optaplanner/examples/projectjobscheduling/solver/projectJobSchedulingScoreRules.drl</scoreDrl>
instead of <incrementalScoreCalculatorClass>org.optaplanner.examples.projectjobscheduling.solver.score.ProjectJobSchedulingIncrementalScoreCalculator</incrementalScoreCalculatorClass>
.
To be clearer:
I only change this part of projectJobSchedulingSolverConfig.xml
file:
<scoreDirectorFactory>
<!--<incrementalScoreCalculatorClass>org.optaplanner.examples.projectjobscheduling.solver.score.ProjectJobSchedulingIncrementalScoreCalculator</incrementalScoreCalculatorClass>-->
<scoreDrl>org/optaplanner/examples/projectjobscheduling/solver/projectJobSchedulingScoreRules.drl</scoreDrl>
</scoreDirectorFactory>
But then I encountered compilation error:
Exception in thread "main" java.lang.IllegalStateException: There are errors in a score DRL:
Error Messages:
Message [id=1, kieBase=defaultKieBase, level=ERROR, path=org/optaplanner/examples/projectjobscheduling/solver/projectJobSchedulingScoreRules.drl, line=95, column=0
text=Rule Compilation error The operator - is undefined for the argument type(s) Comparable]
---
Warning Messages:
---
Info Messages:
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:507)
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildScoreDirectorFactory(ScoreDirectorFactoryConfig.java:331)
at org.optaplanner.core.config.solver.SolverConfig.buildSolver(SolverConfig.java:220)
at org.optaplanner.core.impl.solver.AbstractSolverFactory.buildSolver(AbstractSolverFactory.java:61)
at org.optaplanner.examples.common.app.CommonApp.createSolver(CommonApp.java:103)
at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:97)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:84)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:80)
at org.optaplanner.examples.projectjobscheduling.app.ProjectJobSchedulingApp.main(ProjectJobSchedulingApp.java:34)
I did not modify the projectJobSchedulingScoreRules.drl
file, but here is the file content:
/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.optaplanner.examples.projectjobscheduling.solver;
dialect "java"
import org.optaplanner.core.api.score.buildin.bendable.BendableScoreHolder;
import org.optaplanner.examples.projectjobscheduling.domain.Allocation;
import org.optaplanner.examples.projectjobscheduling.domain.ExecutionMode;
import org.optaplanner.examples.projectjobscheduling.domain.Job;
import org.optaplanner.examples.projectjobscheduling.domain.JobType;
import org.optaplanner.examples.projectjobscheduling.domain.Project;
import org.optaplanner.examples.projectjobscheduling.domain.ResourceRequirement;
import org.optaplanner.examples.projectjobscheduling.domain.resource.Resource;
import org.optaplanner.examples.projectjobscheduling.solver.score.capacity.NonrenewableResourceCapacityTracker;
import org.optaplanner.examples.projectjobscheduling.solver.score.capacity.RenewableResourceCapacityTracker;
import org.optaplanner.examples.projectjobscheduling.solver.score.capacity.ResourceCapacityTracker;
import org.optaplanner.examples.projectjobscheduling.solver.score.drools.RenewableResourceUsedDay;
global BendableScoreHolder scoreHolder;
// ############################################################################
// Hard constraints
// ############################################################################
rule "nonrenewableResourceCapacity"
when
$resource : Resource(renewable == false, $capacity : capacity)
accumulate(
ResourceRequirement(resource == $resource,
$executionMode : executionMode,
$requirement : requirement)
and Allocation(executionMode == $executionMode);
$used : sum($requirement);
$used > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, 0, $capacity - $used);
end
rule "renewableResourceUsedDay"
salience 1 // Do these rules first (optional, for performance)
when
ResourceRequirement(resourceRenewable == true, $executionMode : executionMode, $resource : resource)
Allocation(executionMode == $executionMode,
$startDate : startDate, $endDate : endDate)
then
for (int i = $startDate; i < $endDate; i++) {
insertLogical(new RenewableResourceUsedDay($resource, i));
}
end
rule "renewableResourceCapacity"
when
RenewableResourceUsedDay($resource : resource, $capacity : resourceCapacity, $usedDay : usedDay)
accumulate(
ResourceRequirement(resource == $resource,
$executionMode : executionMode,
$requirement : requirement)
and Allocation(executionMode == $executionMode, $usedDay >= startDate, $usedDay < endDate);
$used : sum($requirement);
$used > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, 0, $capacity - $used);
end
// ############################################################################
// Soft constraints
// ############################################################################
rule "totalProjectDelay"
when
Allocation(jobType == JobType.SINK, endDate != null, $endDate : endDate,
$criticalPathEndDate : projectCriticalPathEndDate)
then
scoreHolder.addSoftConstraintMatch(kcontext, 0, $criticalPathEndDate - $endDate);
end
rule "totalMakespan"
when
accumulate(
Allocation(jobType == JobType.SINK, $endDate : endDate);
$maxProjectEndDate : max($endDate)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, 1, -$maxProjectEndDate);
end
Have anyone encountered similar issue? Any clue how to fix it? Thanks in advance.
Upvotes: 0
Views: 413
Reputation: 1109
As yurloc explain, the result of max() drools accumulation function was a comparable object, and that's why it can't be negated using the - operator. This answer just another alternative to yurloc answer :
rule "totalMakespan"
when
$maxProjectEndDate : Number() from accumulate(
Allocation(jobType == JobType.SINK, $endDate : endDate);
max($endDate)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, 1, -$maxProjectEndDate.intValue());
end
Upvotes: 1
Reputation: 2358
The error message is:
The operator - is undefined for the argument type(s) Comparable
This is a result of a limitation of the max()
Drools accumulator function, which is not generic and its return type is always Comparable
even if you feed it with Integer
argument. Therefore the type of the $maxProjectEndDate
variable is Comparable
(which is not a number) and so you cannot negate its value using the -
operator.
As a quick fix, you can cast it to Integer
before negating it in the totalMakespan
rule:
scoreHolder.addSoftConstraintMatch(kcontext, 1, -((Integer) $maxProjectEndDate));
Upvotes: 3