运行我的问题的解算器时,我收到以下错误消息:
Exception executing consequence for rule "addMarks" in com.abcdl.be.solver: [Error: getEndTime(): null]
[Near : {... getEndTime() ....}]
...
消息说规则中的getEndTime()方法" addMarks"返回null。 这是drools文件:
// ############################################################################
// Hard constraints
// ############################################################################
rule "RespectDependencies" // Respect all the dependencies in the input file
when
Dependency(respected() == false)
then
scoreHolder.addHardConstraintMatch(kcontext, 0, -1);
end
rule "addMarks" //insert a Mark each time a process chain starts or ends
when
Node($startTime : getStartTime(), $endTime : getEndTime())
then
insertLogical(new Mark($startTime));
insertLogical(new Mark($endTime));
end
rule "resourcesLimit" // At any time, The number of resources used must not exceed the total number of resources available
when
Mark($startTime: time)
Mark(time > $startTime, $endTime : time)
not Mark(time > $startTime, time < $endTime)
$total : Number(intValue > Global.getInstance().getAvailableResources() ) from
accumulate(Node(getEndTime() >=$endTime, getStartTime()<= $startTime, $res : resources), sum($res))
then
scoreHolder.addHardConstraintMatch(kcontext, 1, (Global.getInstance().getAvailableResources() - $total.intValue()) * ($endTime - $startTime));
end
rule "masterDataManagement" // Parallel loading is forbidden
when
$n1 : Node(md != "", $md : md, $id : id)
$n2 : Node(id > $id, md == $md) // We make sure to check only different nodes through the condition "id > $id"
eval(Graph.getInstance().getPaths($n1, $n2).size() == 0)
then
scoreHolder.addHardConstraintMatch(kcontext, 2, -1);
end
// ############################################################################
// Soft constraints
// ############################################################################
rule "MaximizeResources" //Maximize use of available resources at any time
when
Mark($startTime: time)
Mark(time > $startTime, $endTime : time)
not Mark(time > $startTime, time < $endTime)
$total : Number(intValue < Global.getInstance().getAvailableResources() ) from
accumulate(Node(getEndTime() >=$endTime, getStartTime()<= $startTime, $res : resources), sum($res))
then
scoreHolder.addHardConstraintMatch(kcontext, 0, ($total.intValue() - Global.getInstance().getAvailableResources()) * ($endTime - $startTime));
end
rule "MinimizeTotalTime" // Minimize the total process time
when
Problem($totalTime : getTotalTime())
then
scoreHolder.addSoftConstraintMatch(kcontext, 1, -$totalTime);
end
Node是规划实体,返回null的方法getStartTime()和getEndTime()在规划实体中定义
规划实体代码:
@PlanningEntity(difficultyComparatorClass = NodeDifficultyComparator.class)
public class Node extends ProcessChain {
private Node parent; // Planning variable: changes during planning, between score calculations
private int id; // Used as an identifier for each node. Different nodes cannot have the same id
public Node(String name, String type, int time, int resources, String md, int id)
{
super(name, "", time, resources, "", type, md);
this.delay = "";
this.id = id;
}
public Node()
{
super();
this.delay = "";
}
@PlanningVariable(valueRangeProviderRefs = {"parentRange"}, nullable = false)
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String toString()
{
if(this.type.equals("AND"))
return delay;
if(!this.md.isEmpty())
return Tools.excerpt(name+" : "+this.md);
return Tools.excerpt(name);
}
public boolean equals( Object o ) {
if (o == this)
return true;
if (o instanceof Node) {
return
this.name.equals(((Node)o).name);
} else {
return false;
}
}
// ************************************************************************
// Complex methods
// ************************************************************************
public int getStartTime()
{
return Graph.getInstance().getNode2times().get(this).getFirst();
}
public int getEndTime()
{
return Graph.getInstance().getNode2times().get(this).getSecond();
}
@ValueRangeProvider(id = "parentRange")
public Collection<Node> getPossibleParents()
{
Collection<Node> nodes = Graph.getInstance().getNodes();
nodes.remove(this); // We remove this node from the list
nodes.remove(Graph.getInstance().getParents(this)); // We remove its parents from the list
return nodes;
}
/**
* The normal methods {@link #equals(Object)} and {@link #hashCode()} cannot be used because the rule engine already
* requires them (for performance in their original state).
* @see #solutionHashCode()
*/
public boolean solutionEquals(Object o) {
if (this == o) {
return true;
} else if (o instanceof Node) {
Node other = (Node) o;
return new EqualsBuilder()
.append(name, other.name)
.isEquals();
} else {
return false;
}
}
/**
* The normal methods {@link #equals(Object)} and {@link #hashCode()} cannot be used because the rule engine already
* requires them (for performance in their original state).
* @see #solutionEquals(Object)
*/
public int solutionHashCode() {
return new HashCodeBuilder()
.append(name)
.toHashCode();
}
这是非常奇怪的原因node2times()。get()不会为Graph类中的所有节点返回null。我做了一个测试,以确保:
public class Graph {
private ArrayList<Node> nodes;
...
public void test()
{
for(Node node : nodes)
{
int time = 0;
try{
time = getNode2times().get(node).getFirst();
System.out.print(node+" : "+"Start time = "+time);
}
catch(NullPointerException e)
{
System.out.println("StartTime is null for node : " +node);
}
try{
time = node.getEndTime();
System.out.println(" End time = "+time);
}
catch(NullPointerException e)
{
System.out.println("EndTime is null for node : " +node);
}
}
}
...
}
答案 0 :(得分:2)
您正在超载Node.equals()
,但没有Node.hashCode()
。
您正在使用地图:节点到时间(如果我可以信任您使用的名称)。
这违反了将对象用作HashMap中的键的合同。