Optaplanner:动态添加/删除约束

问题描述

我有这样的问题。我需要根据当前的多个实体对象生成两个不同的计划。

我的计划订单实体类

@Data
@PlanningEntity
public class Planorder  implements Serializable {

@PlanningId
private String id;


private String drawingNo;


private String itemName;


private String jdJhzl;


private String actualQuantity1;


private String pddj1;


private String actualQuantity2;


private String rsdj1;



private String actualQuantity3;


private String opdj1;


private String actualQuantity4;


private String trdj1;


private String annual;


private String monthly;


private String materialCode;


private String pa8;


private String tosell2;


private String status;


private ProductionLine productionLine;

@PlanningVariable(valueRangeProviderRefs={'productionLineRange'})
public ProductionLine getProductionLine() {
    return productionLine;
}

public void setProductionLine(ProductionLine productionLine) {
    this.productionLine = productionLine;
}

public Planorder(String id,String drawingNo,String itemName,String jdJhzl,String actualQuantity1,String pddj1,String actualQuantity2,String rsdj1,String actualQuantity3,String opdj1,String actualQuantity4,String trdj1,String annual,String monthly,String materialCode,String pa8,String tosell2,String status,ProductionLine productionLine) {
    this.id = id;
    this.drawingNo = drawingNo;
    this.itemName = itemName;
    this.jdJhzl = jdJhzl;
    this.actualQuantity1 = actualQuantity1;
    this.pddj1 = pddj1;
    this.actualQuantity2 = actualQuantity2;
    this.rsdj1 = rsdj1;
    this.actualQuantity3 = actualQuantity3;
    this.opdj1 = opdj1;
    this.actualQuantity4 = actualQuantity4;
    this.trdj1 = trdj1;
    this.annual = annual;
    this.monthly = monthly;
    this.materialCode = materialCode;
    this.pa8 = pa8;
    this.tosell2 = tosell2;
    this.status = status;
    this.productionLine = productionLine;
}

public Planorder() {
}
}

我的库存实体类别:

@Data

public class Inventory implements Serializable {

private static final long serialVersionUID = 1L;


private Long id;


private String ckbh;


private String cklx;


private String wlbh;


private Double kcsl;


private Double kcfzsl;


private Integer operate;
}

我的客户实体类别:

@Data
public class ProductionLine implements Serializable {

private static final long serialVersionUID = 1L;

@PlanningId
private String id;


private String onlyKey;


private String lineId;


private String line;


private String itemNumber;


private String itemName;


private String dailyEnergy;
}

我的计划分配班:

@PlanningSolution
public class PlanAssignment{

@PlanningId
private Long id;


private HardSoftscore score;


@ValueRangeProvider(id = 'productionLineRange')
@ProblemFactCollectionProperty
private List<ProductionLine> productionLineList;


@ValueRangeProvider(id = 'planorderRange')
@PlanningEntityCollectionProperty
private List<Planorder> planorderList;


public PlanAssignment(List<ProductionLine> productionLineList,List<Planorder> planorderList) {
    this.productionLineList = productionLineList;
    this.planorderList = planorderList;
}

public PlanAssignment() {
}

@Planningscore
public HardSoftscore getscore() {
    return score;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public void setscore(HardSoftscore score) {
    this.score = score;
}

public List<ProductionLine> getProductionLineList() {
    return productionLineList;
}

public void setProductionLineList(List<ProductionLine> productionLineList) {
    this.productionLineList = productionLineList;
}

public List<Planorder> getPlanorderList() {
    return planorderList;
}

public void setPlanorderList(List<Planorder> planorderList) {
    this.planorderList = planorderList;
}
}

我的约束实现类:

public class PlanConstraintProvider implements ConstraintProvider {


@Override
public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
    return new Constraint[]{
            yarnTypeMatch(constraintFactory),clientLevel_used(constraintFactory)
    };
}


private Constraint yarnTypeMatch(ConstraintFactory constraintFactory){
    return constraintFactory.from(Planorder.class)
            .filter(planorder ->planorder.getProductionLine()!=null)
            .filter(planorder-> !planorder.getProductionLine().getItemName().equals(planorder.getItemName()))
            .penalizeConfigurable('yarn type match',HardSoftscore.ofHard(10000));

}



private  Constraint clientLevelUsed(ConstraintFactory constraintFactory){
  
    return constraintFactory.from(Client.class)
            .ifExists(Planorder.class,Joiners.equal(client -> client,Planorder::getPa8 ))
            .penalizeConfigurable('client level used',HardSoftscore.ONE_HARD,client->Integer.parseInt(client.getClientLevel()));
}
}

我的约束配置注释类:

@ConstraintConfiguration
public class PlanConstraintConfiguration {

@ConstraintWeight('yarn type match')
public HardSoftscore yarnTypeMatch = HardSoftscore.ofHard(1);

@ConstraintWeight('client level used')
public HardSoftscore clientLevelUsed = HardSoftscore.ofHard(2);

}

XML配置:

<solver>

<solutionClass>com.zbxx.iem.scheduling.domain.PlanAssignment</solutionClass>
<entityClass>com.zbxx.iem.scheduling.domain.Planorder</entityClass>


<scoreDirectorFactory>
 <constraintProviderClass>...solver.PlanConstraintProvider</constraintProviderClass>
</scoreDirectorFactory>

<termination>
    <secondsspentLimit>10</secondsspentLimit>
</termination>

控制器调用

   SolverFactory<PlanAssignment> solverFactory = 
    SolverFactory.createFromXmlResource('planConfiguration.xml');
    Solver<PlanAssignment> solver = solverFactory.buildSolver();

    PlanAssignment planAssignment = new PlanAssignment(productionLineList,planorderList);
    PlanAssignment solve = solver.solve(planAssignment);

我的想法的实现是:用户在UI界面中选择不同的约束,并将它们与参数一起传递给求解器。 Solver动态加载不同的约束并根据转移的约束开始求解,我的想法的实现是:用户在UI界面中选择不同的约束,并将它们与参数一起传递给求解器。规划求解器动态加载不同的约束条件,并根据转移的约束条件开始解决它们,之所以这样做,是因为我不需要在月度计划中考虑半成品库存的变化和其他一些变量,但是我需要在每周计划中考虑半成品库存的变化和其他变量

解决方法

查看文档中的@ConstraintConfiguration@ConstraintWeight。通过将约束的权重设置为HardSoftScore.ZERO可以很容易地禁用约束。