我正在使用Optaplanner 7.38.0.Final
我实现了一个相对简单的模型,遇到了一些问题。
问题是,我想要不时地中断链以返回仓库,我认为没有必要创建另一个类来进行这种中断,并且在需要重新启动路由时,我包含了一个带有epoch second时间戳的规划变量(时间戳介于一个相对较小的范围之间,下面代码中的startoftrip
)。
Optaplanner能够使用给定的xml配置创建求解器,如果我在score calculator上创建一个断点,我可以检查VAR,并看到构造启发式能够创建一个有效的访问链,甚至设置时间戳变量的值。
但几毫秒后,当在第43行调用org.optaplanner.core.impl.heuristic.selector.move.generic.chained.chainedswapmove
构造函数(在上面给定版本的原始源代码上)时,求解器遇到NullPointerException
public ChainedSwapMove(List<GenuineVariableDescriptor<Solution_>> variableDescriptorList,
List<SingletonInverseVariableSupply> inverseVariableSupplyList, Object leftEntity, Object rightEntity) {
super(variableDescriptorList, leftEntity, rightEntity);
oldLeftTrailingEntityList = new ArrayList<>(inverseVariableSupplyList.size());
oldRightTrailingEntityList = new ArrayList<>(inverseVariableSupplyList.size());
for (SingletonInverseVariableSupply inverseVariableSupply : inverseVariableSupplyList) {
oldLeftTrailingEntityList.add(inverseVariableSupply.getInverseSingleton(leftEntity));
oldRightTrailingEntityList.add(inverseVariableSupply.getInverseSingleton(rightEntity));
}
}
变量inverseVariableSupplyList
似乎包含一个空引用(它在分析包含常规非链接PlanningVariable的variableDescriptorList时创建此空引用)
package X;
import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.variable.AnchorShadowVariable;
import org.optaplanner.core.api.domain.variable.InverseRelationShadowVariable;
import org.optaplanner.core.api.domain.variable.PlanningVariable;
import org.optaplanner.core.api.domain.variable.PlanningVariableGraphType;
import javax.persistence.Transient;
import java.io.Serializable;
import java.time.LocalDateTime;
@PlanningEntity
public class OptimizingVisit implements OptimizingStandstill , Serializable {
private static final long serialVersionUID = 9163651541108883957L;
private ContinuousBranchTripSolution solution;
private Order order;
private Long startOfTrip;
private Long start;
private Long arrivalTime;
private Long end;
private Long travelDuration;
private Long travelDistance;
private OptimizingStandstill previousStandstill;
private OptimizingVisit nextStandstill; //shadow variable
private OptimizingDriver optimizingDriver;
public OptimizingVisit() {
}
public OptimizingVisit(Order order, ContinuousBranchTripSolution solution) {
this.order = order;
this.solution = solution;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
@AnchorShadowVariable(sourceVariableName = "previousStandstill")
public OptimizingDriver getOptimizingDriver() {
return optimizingDriver;
}
public void setOptimizingDriver(OptimizingDriver optimizingDriver) {
this.optimizingDriver = optimizingDriver;
}
public Employee getDriver(){
return this.getOptimizingDriver().getDriver();
}
@PlanningVariable( valueRangeProviderRefs = "startTimeCandidates" )
public Long getStartOfTrip() {
return startOfTrip;
}
public void setStartOfTrip(Long startOfTrip) {
this.startOfTrip = startOfTrip;
}
public Long getTravelDuration() {
return travelDuration;
}
public void setTravelDuration(Long travelDuration) {
this.travelDuration = travelDuration;
}
public Long getTravelDistance() {
return travelDistance;
}
public void setTravelDistance(Long travelDistance) {
this.travelDistance = travelDistance;
}
@PlanningVariable( graphType = PlanningVariableGraphType.CHAINED , valueRangeProviderRefs = { "visitsRange" , "driversRange" } )
public OptimizingStandstill getPreviousStandstill() {
return previousStandstill;
}
public void setPreviousStandstill(OptimizingStandstill previousStandstill) {
this.previousStandstill = previousStandstill;
}
@Override
public OptimizingVisit getNextStandstill() {
return nextStandstill;
}
@Override
public void setNextStandstill(OptimizingVisit nextStandstill) {
this.nextStandstill = nextStandstill;
}
@Override
public Hexagon getHexagon() {
return this.getOrder().getShippingAddress().getHexagon();
}
public TimeRange getTimeRange() {
return new TimeRange( this.start , this.end );
}
/*Helper Methods*/
public long getRecursiveStart(){
if( this.getStartOfTrip() != null ) return this.getStartOfTrip() + 5*60;
if( this.start != null ) return this.start;
this.start = this.getPreviousStandstill().getRecursiveEnd();
return this.start;
}
public long getRecursiveArrivalTime(){
if( this.arrivalTime != null ) return this.arrivalTime;
this.arrivalTime = this.getRecursiveStart() + solution.getDistanceBetweenHexagons( this.getPreviousStandstill().getHexagon() , this.getHexagon() ).getDuration();
return this.arrivalTime;
}
@Override
public long getRecursiveEnd(){
if( this.end != null ) return this.end;
this.end = this.getRecursiveArrivalTime() + TripsOptimizer.standByDuration;
return this.end;
}
public boolean isEndOfTrip(){
return this.getNextStandstill() == null || ( ( OptimizingVisit ) this.getNextStandstill()).getStartOfTrip() != null;
}
public long endOfTrip(){
return this.getRecursiveEnd() + TripsOptimizer.standByDuration + solution.getDistanceBetweenHexagons( this.getHexagon() , this.getOptimizingDriver().getHexagon() ).getDuration();
}
@Override
public void cleanTimes() {
this.start = null;
this.arrivalTime = null;
this.end = null;
}
public long overlapWith( OptimizingVisit optimizingVisit ){
if( this.getRecursiveStart() > optimizingVisit.getRecursiveEnd() ) return 0;
if( this.getRecursiveEnd() < optimizingVisit.getRecursiveStart() ) return 0;
OptimizingVisit firstEvent;
OptimizingVisit lastEvent;
if( this.getRecursiveStart() < optimizingVisit.getRecursiveStart() ){
firstEvent = this;
lastEvent = optimizingVisit;
}else{
firstEvent = optimizingVisit;
lastEvent = this;
}
if( lastEvent.getRecursiveEnd() < firstEvent.getRecursiveEnd() ) return lastEvent.getRecursiveEnd() - lastEvent.getRecursiveStart();
return firstEvent.getRecursiveEnd() - lastEvent.getRecursiveStart();
}
public long getTimePenalization(){
if( this.order == null ) return 0;
long estimatedArrivalTime = this.getRecursiveArrivalTime();
TimeRange orderTimeRange = this.getOrder().getTimeRange();
if( estimatedArrivalTime > orderTimeRange.getEnd() ){
double secondsOfDifference = estimatedArrivalTime - orderTimeRange.getEnd();
return (long) Math.pow( secondsOfDifference , this.getOrder().isExpress() ? 2 : 1.5 );
}
if( estimatedArrivalTime > orderTimeRange.getStart() ) return 0;
return (long) Math.pow( orderTimeRange.getStart() - estimatedArrivalTime , 2 );
}
@Transient
public double getCarryOnCash() {
if( this.order == null ) return 0;
double r = 0;
if( this.order.isOnAdvanceMode() ){
for ( TransactionMatrix tm : this.order.getTransactionMatrix() ) {
if( !PaymentMethodType.CASH.equals( tm.getPaymentMethodType() ) ) continue;
r += tm.getAdvance();
}
}else{
for ( TransactionMatrix tm : this.order.getTransactionMatrix() ) {
if( !PaymentMethodType.CASH.equals( tm.getPaymentMethodType() ) ) continue;
r += tm.getAmount();
}
}
return r;
}
public long getEarlyOrLateSeconds(){
TimeRange orderTimeRange = this.getOrder().getTimeRange();
long arrivalTime = this.getRecursiveArrivalTime();
long r = 0;
if( arrivalTime < orderTimeRange.getStart() ) r += orderTimeRange.getStart() - arrivalTime;
if( arrivalTime > orderTimeRange.getEnd() ) r += arrivalTime - orderTimeRange.getEnd();
return r;
}
public long getContinuousOptimizationScore( ContinuousBranchTripSolution solution ) {
return 0;
/*if( !( this.getPreviousStandstill() instanceof OptimizingTrip ) ){
return this.getTimePenalization();
}
double r = 0;
OptimizingTrip trip = (OptimizingTrip) this.getPreviousStandstill();
for ( DriverShift shift : solution.getDriverShifts() ){
if( this.getOptimizingDriver().getDriver().computedIdHashCode() != shift.getDriver().computedIdHashCode() ) continue;
long seconds = Math.max( 0 , trip.getEnd() - shift.getAvailableUntilAsEpochSeconds() );
r += Math.pow( seconds * 2 , 2 );
}
r += 0.25d * Math.max( this.getCarryOnCash() - this.getOptimizingDriver().getDriver().getTrustLevel() , 0 );
if ( trip.getStart() > solution.getStart() ) {
r -= 0.5d * ( trip.getEnd() - solution.getStart() );
}
r += this.getTimePenalization();
return (long) r;*/
}
@Override
public String toString() {
return String.format("OptimizingVisit{ %s , %s , %s , %s , %s min early , %s min late }",
this.order.getNumber(),
this.getOrder().getLowerBoundDelivery(),
this.getPreviousStandstill() == null ? "" : LocalDateTime.ofEpochSecond( this.getRecursiveArrivalTime() , 0 , BitemporalModel.ZONE_OFFSET ),
this.getOrder().getUpperBoundDelivery(),
this.getPreviousStandstill() == null ? "" : Math.max( 0 , ( this.getOrder().getTimeRange().getStart() - this.getRecursiveArrivalTime() ) ) / 60,
this.getPreviousStandstill() == null ? "" : Math.max( 0 , ( this.getRecursiveArrivalTime() - this.getOrder().getTimeRange().getEnd() ) ) / 60
);
}
}
我们最近修复了1961年的计划,其症状与你们在这里的问题有显著的相似之处。请查看OptaPlanner 7.39.0.final(当它退出时)或更晚,您的问题可能会消失。
首先,感谢Angel Chang编写了像TokensRegex这样伟大的工具! 我的用例如下: 我的测试规则集中有两个提取规则。它们都有指定为结果的“action”字段,并且在action列表中都有“annotate”。当要匹配的第二个规则的表达式与第一个规则的结果无关时,它们就可以正常工作。但是当第二个规则的执行依赖于第一个规则的结果时,事情就崩溃了。 一个具体的例子: 我有以下句子:“共识估计
在制定时间表时,你必须遵守法律(硬性要求),该法律规定,作为一名员工,你每七天只能工作一定的时间。它没有说日历周的原因是在创建时间表时为雇主提供一些回旋空间(通常是提前4-16周)。一旦设置了此计划期的开始日期,在您想要进行完整的重新规划之前,该日期无法更改,但您需要通知员工。所以它可以被视为一个变量,直到你接受了时间表,然后它就变成了一个常数。当然,这是每个员工的个人情况。该开始日期将由您的第一
我是Optaplanner的新手,我一直在考虑将VRP扩展到一个不同的问题空间。我用的是6.1.0-final。这是一个很难计算的问题,但下面是: 规划实体-装运(扩展Standstill),由运输商(即货船)锚定规划变量-终端(货物目的地),当然隐含运输商(作为VRP示例中的Vehicle这样的影子变量) 在这个路径问题中,货物直接运输到一个终端,然后再运回工厂。即一个运输机服务于一个终点站,然
问题内容: 在Linux上的“ C”上, 我需要静态库来静态链接,还是需要足够的共享库?如果没有,为什么不呢?(它们不包含相同的数据吗?) 问题答案: 是的,您需要静态库来构建静态链接的可执行文件。 静态库是编译对象的捆绑包。静态链接到库时,实际上与获取该库的编译结果,将它们解压缩到当前项目中以及将它们当作自己的对象使用一样。 动态库已链接。这意味着一些信息,例如重定位,已经被修复并丢弃。 此外,
Berat有资格获得驾驶执照! Berat不能买酒! Berat的有效年龄:真 虽然,我优先考虑每个规则与突出关键字,“可以由酒精”规则仍然被解雇。它不应该被激发,因为在第一个规则中执行setValid(true),而在第二个规则中执行isValid()==false控件应该返回false,因此应该遗漏部分。
我们已经将我们的车辆路径问题建模为一个链式规划问题,即取货和送货问题。最重要的是,我们有一个定制的移动实现,它从车队中解开一对收货-送货对,并将其插入其他地方。 我们已经实现了一个早期退出:如果在链更新期间没有更新特定的阴影变量,我们将跳过链的其余部分。然而,只有当我们偶然地首先处理来自第一个实体的链时,这才起作用。 我们如何确保每次移动只更新链一次,从第一个更改的实体开始?