Change penalty evaluation implementation to use less random numbers.
This commit is contained in:
parent
37c12a7fdd
commit
fd08d1be9b
|
@ -39,7 +39,9 @@ public class PenaltyNode {
|
||||||
private final IPenalty<?> penalty;
|
private final IPenalty<?> penalty;
|
||||||
/** Child nodes to test when this node applies. */
|
/** Child nodes to test when this node applies. */
|
||||||
private final PenaltyNode[] childNodes;
|
private final PenaltyNode[] childNodes;
|
||||||
/** Indicate that the result is set with the first child node that applies. */
|
/**
|
||||||
|
* Indicate that the result is set with the first child node that applies.
|
||||||
|
*/
|
||||||
private final boolean abortOnApply;
|
private final boolean abortOnApply;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,12 +68,15 @@ public class PenaltyNode {
|
||||||
* @param random
|
* @param random
|
||||||
* @param probability
|
* @param probability
|
||||||
* @param penalty
|
* @param penalty
|
||||||
|
* Note that child penalties are still evaluated, if penalty is
|
||||||
|
* not null and abortOnApply is set.
|
||||||
* @param childNodes
|
* @param childNodes
|
||||||
* May be null.
|
* May be null. No scaling/normalizing is applied here.
|
||||||
* @param abortOnApply
|
* @param abortOnApply
|
||||||
* Evaluating child nodes: abort as soon as a child node applies.
|
* Evaluating child nodes: abort as soon as a child node applies.
|
||||||
*/
|
*/
|
||||||
public PenaltyNode(Random random, double probability, IPenalty<?> penalty, Collection<PenaltyNode> childNodes, boolean abortOnApply) {
|
public PenaltyNode(Random random, double probability, IPenalty<?> penalty,
|
||||||
|
Collection<PenaltyNode> childNodes, boolean abortOnApply) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
this.probability = probability;
|
this.probability = probability;
|
||||||
this.penalty = penalty;
|
this.penalty = penalty;
|
||||||
|
@ -87,20 +92,69 @@ public class PenaltyNode {
|
||||||
* @return If this node applies (, which does not necessarily mean that
|
* @return If this node applies (, which does not necessarily mean that
|
||||||
* anything has been appended to results).
|
* anything has been appended to results).
|
||||||
*/
|
*/
|
||||||
public boolean evaluate(final IPenaltyList results) {
|
public final boolean evaluate(final IPenaltyList results) {
|
||||||
|
// (Set final to ensure return behavior.)
|
||||||
if (probability < 1.0 && random.nextDouble() > probability) {
|
if (probability < 1.0 && random.nextDouble() > probability) {
|
||||||
// This node does not apply
|
// This node does not apply
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (penalty != null) {
|
add(results);
|
||||||
penalty.addToPenaltyList(results);
|
|
||||||
}
|
|
||||||
for (int i = 0 ; i < childNodes.length; i++) {
|
|
||||||
if (childNodes[i].evaluate(results) && abortOnApply) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add this node and evaluate children (add applicable ancestor-penalties to
|
||||||
|
* the list).
|
||||||
|
*
|
||||||
|
* @param results
|
||||||
|
*/
|
||||||
|
protected void add(final IPenaltyList results) {
|
||||||
|
if (penalty != null) {
|
||||||
|
/*
|
||||||
|
* TODO: Consider abortOnApply taking effect here (typically this is
|
||||||
|
* a leaf, if penalty is not null, but that isn't enforced yet).
|
||||||
|
*/
|
||||||
|
penalty.addToPenaltyList(results);
|
||||||
|
}
|
||||||
|
if (childNodes.length > 0) {
|
||||||
|
if (abortOnApply) {
|
||||||
|
evaluateChildrenFCFS(results);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
evaluateAllChildren(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For choice of children one random
|
||||||
|
* @param results
|
||||||
|
*/
|
||||||
|
protected void evaluateChildrenFCFS(final IPenaltyList results) {
|
||||||
|
final double ref = random.nextDouble(); // No scale contained yet.
|
||||||
|
double floor = 0.0;
|
||||||
|
for (int i = 0 ; i < childNodes.length; i++) {
|
||||||
|
final PenaltyNode childNode = childNodes[i];
|
||||||
|
final double nextFloor = floor + childNode.probability;
|
||||||
|
// TODO: Configurable catch-all amount.
|
||||||
|
if (nextFloor >= ref || nextFloor >= 0.999) {
|
||||||
|
childNode.add(results);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
floor = nextFloor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each of children can apply, which means for each child at least one
|
||||||
|
* further random number is generated.
|
||||||
|
*
|
||||||
|
* @param results
|
||||||
|
*/
|
||||||
|
protected void evaluateAllChildren(final IPenaltyList results) {
|
||||||
|
for (int i = 0 ; i < childNodes.length; i++) {
|
||||||
|
childNodes[i].evaluate(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue