为什么求解后 PlanningVariable 的值没有变化? #OptaPlanner
Why the value of PlanningVariable doesn't change after solving ? # OptaPlanner
我正在使用 Optaplanner 进行医院床位分配项目。我正在使用 spring boot、spring JPA 和 postgres 作为数据库。我已经用@PlanningEntity和@PlanningSolution注解设置了所有classes,set
@PlanningVariable,用drool写constraints,用'.xml'文件配置。求解planning variable的值后,在我的cas"bed"中,没有变化!!
这是主要的class:
@SpringBootApplication(scanBasePackages = { "com.asma.optaplanner.demo" })
public class OptaPlannerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(OptaPlannerDemoApplication.class, args);
}
@Bean
public CommandLineRunner demoData(PatientAdmissionScheduleHelper helper) {
return args -> {
SolverFactory<PatientAdmissionSchedule> solverfactory = SolverFactory.createFromXmlResource("Solver_Config.xml");
helper.initilizeDataBase();
System.out.println("before solving");
Solver<PatientAdmissionSchedule> solver = solverfactory.buildSolver();
PatientAdmissionSchedule unsolvedSchedule = helper.getSchedule();
unsolvedSchedule.getAdmissionList().forEach(admission -> {
System.out.println(admission.toString());
});
solver.solve(unsolvedSchedule);
PatientAdmissionSchedule solvedSchedule = solver.getBestSolution();
System.out.println("after solving");
solvedSchedule.getAdmissionList().forEach(admission -> {
System.out.println(admission.toString());
});
};
}
结果:
before solving
2020-06-03 21:33:05.256 WARN 9228 --- [ main] o.d.c.kie.builder.impl.KieBuilderImpl : File 'Constraint.drl' is in folder '' but declares package 'com.asma.optaplanner.demo'. It is advised to have a correspondance between package and folder names.
PatientName patient1bed=Bed [externalCode= bed11, room= Room [name=room1, capacity=2], indexInRoom=1], From 1, To5
PatientName patient2bed=Bed [externalCode= bed12, room= Room [name=room1, capacity=2], indexInRoom=2], From 2, To4
2020-06-03 21:33:06.208 INFO 9228 --- [ main] o.o.core.impl.solver.DefaultSolver : Solving started: time spent (77), best score (-80hard/0soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
2020-06-03 21:37:06.210 INFO 9228 --- [ main] o.o.c.i.l.DefaultLocalSearchPhase : Local Search phase (0) ended: time spent (240079), best score (0hard/0soft), score calculation speed (38961/sec), step total (418).
2020-06-03 21:37:06.222 INFO 9228 --- [ main] .c.i.c.DefaultConstructionHeuristicPhase : Construction Heuristic phase (1) ended: time spent (240091), best score (0hard/0soft), score calculation speed (1222/sec), step total (2).
2020-06-03 21:37:06.222 INFO 9228 --- [ main] o.o.core.impl.solver.DefaultSolver : Solving ended: time spent (240091), best score (0hard/0soft), score calculation speed (38946/sec), phase total (2), environment mode (REPRODUCIBLE).
after solving
2020-06-03 21:37:06.226 INFO 9228 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-06-03 21:37:06.238 ERROR 9228 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at com.asma.optaplanner.demo.OptaPlannerDemoApplication.main(OptaPlannerDemoApplication.java:18) [classes/:na]
Caused by: java.lang.NullPointerException: null
at com.asma.optaplanner.demo.model.Admission.toString(Admission.java:120) ~[classes/:na]
at com.asma.optaplanner.demo.OptaPlannerDemoApplication.lambda(OptaPlannerDemoApplication.java:40) [classes/:na]
at java.util.ArrayList.forEach(Unknown Source) ~[na:1.8.0_171]
at com.asma.optaplanner.demo.OptaPlannerDemoApplication.lambda[=11=](OptaPlannerDemoApplication.java:39) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
... 5 common frames omitted
Constraint.drl :
package com.asma.optaplanner.demo;
//list any import classes here.
dialect "java"
import com.asma.optaplanner.demo.model.Admission ;
import com.asma.optaplanner.demo.model.AdmissionDemand ;
import com.asma.optaplanner.demo.model.Room ;
import com.asma.optaplanner.demo.model.Bed ;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
//declare any global variables here
global HardSoftScoreHolder scoreHolder;
//Hard Constraints
//same gender at the same room in the same night
rule "SameRoomGenderconstraint"
when
$leftAdmission: Admission(
bed != null,
$room : Room,
$leftFrom : DateFromIndex,
$leftTo : DateToIndex,
$leftGender : gender)
$rightAdmission : Admission(
room == $room,
DateToIndex >= $leftFrom ,
DateFromIndex <= $leftTo ,
$rightFrom : DateFromIndex,
$rightTo : dateToIndex,
gender == $leftGender)
then
scoreHolder.addHardConstraintMatch(kcontext,
-10 * (1 + Math.max($leftTo, $rightTo) - Math.max($leftFrom, $rightFrom)));
end
rule "2PatientInTheSameBed"
//include attributes such as "salience" here...
when
$leftAdmission: Admission(
bed != null,
$bed : bed,
$leftFrom : dateFromIndex,
$leftTo : dateToIndex,
$leftId : id)
$rightAdmission: Admission(
bed == $bed,
dateToIndex >= $leftFrom ,
dateFromIndex <= $leftTo ,
$rightFrom : dateFromIndex,
$rightTo : dateToIndex,
id != $leftId)
then
scoreHolder.addHardConstraintMatch(kcontext,
-5 * (1 + Math.max($leftTo, $rightTo) - Math.max($leftFrom, $rightFrom)));
end
当您在 Spring 手动启动中创建 SolverFactory(而不是使用 optaplanner-spring-boot-starter
自动装配它)时,请传递 ClassLoader 参数以避免常见问题。
如果您复制了 optaplanner-example 的 PatientAdmissionSchedule
域 类,请注意它在 @PlanningVariable
上有 nullable=true
,因此它可以 return 未分配的实体.事实上,如果您没有约束(通常是中等约束)来最小化它,则所有实体都可能被分配为 null。
如果你的@PlanningSolution.PlanningEntity :(@PlanningEntityCollectionProperty / @PlanningEntityProperty) 没有改变,你应该检查你的 drool 文件,调试 .drl 文件可能有点困难,你可以试试 ConstraintProvider通过java的接口,解决routine/rule会更容易理解。
另外,更改与 "ranged properties" 注释的“@ValueRangeProvider”相关,您可以从中 plan/optimize 您的解决方案。
我正在使用 Optaplanner 进行医院床位分配项目。我正在使用 spring boot、spring JPA 和 postgres 作为数据库。我已经用@PlanningEntity和@PlanningSolution注解设置了所有classes,set
@PlanningVariable,用drool写constraints,用'.xml'文件配置。求解planning variable的值后,在我的cas"bed"中,没有变化!!
这是主要的class:
@SpringBootApplication(scanBasePackages = { "com.asma.optaplanner.demo" })
public class OptaPlannerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(OptaPlannerDemoApplication.class, args);
}
@Bean
public CommandLineRunner demoData(PatientAdmissionScheduleHelper helper) {
return args -> {
SolverFactory<PatientAdmissionSchedule> solverfactory = SolverFactory.createFromXmlResource("Solver_Config.xml");
helper.initilizeDataBase();
System.out.println("before solving");
Solver<PatientAdmissionSchedule> solver = solverfactory.buildSolver();
PatientAdmissionSchedule unsolvedSchedule = helper.getSchedule();
unsolvedSchedule.getAdmissionList().forEach(admission -> {
System.out.println(admission.toString());
});
solver.solve(unsolvedSchedule);
PatientAdmissionSchedule solvedSchedule = solver.getBestSolution();
System.out.println("after solving");
solvedSchedule.getAdmissionList().forEach(admission -> {
System.out.println(admission.toString());
});
};
}
结果:
before solving
2020-06-03 21:33:05.256 WARN 9228 --- [ main] o.d.c.kie.builder.impl.KieBuilderImpl : File 'Constraint.drl' is in folder '' but declares package 'com.asma.optaplanner.demo'. It is advised to have a correspondance between package and folder names.
PatientName patient1bed=Bed [externalCode= bed11, room= Room [name=room1, capacity=2], indexInRoom=1], From 1, To5
PatientName patient2bed=Bed [externalCode= bed12, room= Room [name=room1, capacity=2], indexInRoom=2], From 2, To4
2020-06-03 21:33:06.208 INFO 9228 --- [ main] o.o.core.impl.solver.DefaultSolver : Solving started: time spent (77), best score (-80hard/0soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
2020-06-03 21:37:06.210 INFO 9228 --- [ main] o.o.c.i.l.DefaultLocalSearchPhase : Local Search phase (0) ended: time spent (240079), best score (0hard/0soft), score calculation speed (38961/sec), step total (418).
2020-06-03 21:37:06.222 INFO 9228 --- [ main] .c.i.c.DefaultConstructionHeuristicPhase : Construction Heuristic phase (1) ended: time spent (240091), best score (0hard/0soft), score calculation speed (1222/sec), step total (2).
2020-06-03 21:37:06.222 INFO 9228 --- [ main] o.o.core.impl.solver.DefaultSolver : Solving ended: time spent (240091), best score (0hard/0soft), score calculation speed (38946/sec), phase total (2), environment mode (REPRODUCIBLE).
after solving
2020-06-03 21:37:06.226 INFO 9228 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-06-03 21:37:06.238 ERROR 9228 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
at com.asma.optaplanner.demo.OptaPlannerDemoApplication.main(OptaPlannerDemoApplication.java:18) [classes/:na]
Caused by: java.lang.NullPointerException: null
at com.asma.optaplanner.demo.model.Admission.toString(Admission.java:120) ~[classes/:na]
at com.asma.optaplanner.demo.OptaPlannerDemoApplication.lambda(OptaPlannerDemoApplication.java:40) [classes/:na]
at java.util.ArrayList.forEach(Unknown Source) ~[na:1.8.0_171]
at com.asma.optaplanner.demo.OptaPlannerDemoApplication.lambda[=11=](OptaPlannerDemoApplication.java:39) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) [spring-boot-2.3.1.BUILD-SNAPSHOT.jar:2.3.1.BUILD-SNAPSHOT]
... 5 common frames omitted
Constraint.drl :
package com.asma.optaplanner.demo;
//list any import classes here.
dialect "java"
import com.asma.optaplanner.demo.model.Admission ;
import com.asma.optaplanner.demo.model.AdmissionDemand ;
import com.asma.optaplanner.demo.model.Room ;
import com.asma.optaplanner.demo.model.Bed ;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
//declare any global variables here
global HardSoftScoreHolder scoreHolder;
//Hard Constraints
//same gender at the same room in the same night
rule "SameRoomGenderconstraint"
when
$leftAdmission: Admission(
bed != null,
$room : Room,
$leftFrom : DateFromIndex,
$leftTo : DateToIndex,
$leftGender : gender)
$rightAdmission : Admission(
room == $room,
DateToIndex >= $leftFrom ,
DateFromIndex <= $leftTo ,
$rightFrom : DateFromIndex,
$rightTo : dateToIndex,
gender == $leftGender)
then
scoreHolder.addHardConstraintMatch(kcontext,
-10 * (1 + Math.max($leftTo, $rightTo) - Math.max($leftFrom, $rightFrom)));
end
rule "2PatientInTheSameBed"
//include attributes such as "salience" here...
when
$leftAdmission: Admission(
bed != null,
$bed : bed,
$leftFrom : dateFromIndex,
$leftTo : dateToIndex,
$leftId : id)
$rightAdmission: Admission(
bed == $bed,
dateToIndex >= $leftFrom ,
dateFromIndex <= $leftTo ,
$rightFrom : dateFromIndex,
$rightTo : dateToIndex,
id != $leftId)
then
scoreHolder.addHardConstraintMatch(kcontext,
-5 * (1 + Math.max($leftTo, $rightTo) - Math.max($leftFrom, $rightFrom)));
end
当您在 Spring 手动启动中创建 SolverFactory(而不是使用 optaplanner-spring-boot-starter
自动装配它)时,请传递 ClassLoader 参数以避免常见问题。
如果您复制了 optaplanner-example 的 PatientAdmissionSchedule
域 类,请注意它在 @PlanningVariable
上有 nullable=true
,因此它可以 return 未分配的实体.事实上,如果您没有约束(通常是中等约束)来最小化它,则所有实体都可能被分配为 null。
如果你的@PlanningSolution.PlanningEntity :(@PlanningEntityCollectionProperty / @PlanningEntityProperty) 没有改变,你应该检查你的 drool 文件,调试 .drl 文件可能有点困难,你可以试试 ConstraintProvider通过java的接口,解决routine/rule会更容易理解。 另外,更改与 "ranged properties" 注释的“@ValueRangeProvider”相关,您可以从中 plan/optimize 您的解决方案。