OptaPlanner 中的自定义 "sumDouble()" 函数用于约束
Custom "sumDouble()" function in OptaPlanner for constraints
我需要一个求和功能,它可以对我的 ConstraintProviding 功能的双精度值求和。当前 OptaPlanner 提供 sum() 和 sumBigDecimal() 功能,其中第一个仅对整数值求和,第二个 BigDecimal 值。因此,我开始使用手册第 6.4.5.3 章中描述的组合方法。用于实现我自己的功能(不想覆盖原来的功能)。
从那里派生并从 OptaPlanner 源代码本身的 ConstraintCollector.java class 中实现求和功能,我最终得到以下代码:
public static <A> UniConstraintCollector<A, ?, Double> sumDouble(ToDoubleFunction<A> groupValueMapping) {
return compose((resultContainer, a) -> {
double value = groupValueMapping.applyAsDouble(a);
resultContainer[0] += value;
return () -> resultContainer[0] -= value;
},
resultContainer -> resultContainer[0]);
}
在我的“OwnConstraintProvider”中 class。但这行不通。错误是:
java: method compose in interface java.lang.module.ModuleFinder cannot be applied to given types;
required: java.lang.module.ModuleFinder[]
found: (resultCon[...]ue; },(resultCon[...]er[0]
reason: varargs mismatch; java.lang.module.ModuleFinder is not a functional interface
multiple non-overriding abstract methods found in interface java.lang.module.ModuleFinder
我知道输入A和结果之间必须有一个更清晰的关系和计算方法。
坦率地说,我最近才开始认真地 Java 编程。所以我无法弄清楚在那种情况下我错在哪里。在当前使用的版本 (8.19.0) 的手册中,第 6.4.5.1.3 章中提到了“用于汇总自定义类型的通用 sum() 变体”。但我对这方面的细节一无所知。
谁能给我一些提示。
提前致谢!
您是否考虑过使用不同的类型,例如long
,以表示您需要在约束中 sum()
的值?
使用 floating-point numbers in the score calculation is generally not recommended 因为它可能会导致分数损坏。
首先,拉多万的回答是完全正确的。事实上,潜在的分数损坏是未提供 sumDouble()
的原因。相反,我们提供 sumBigDecimal()
,它不会遇到同样的问题。但是,它会在性能方面受到影响。首选解决方案是使用 sum()
或 sumLong()
,必要时使用 fixed-point 算法。
也就是说,实现 sumDouble()
相对简单,不需要组合来实现:
public static <A> UniConstraintCollector<A, ?, Double> sum(ToDoubleFunction<? super A> groupValueMapping) {
return new DefaultUniConstraintCollector<>(
() -> new double[1],
(resultContainer, a) -> {
int value = groupValueMapping.applyAsDouble(a);
resultContainer[0] += value;
return () -> resultContainer[0] -= value;
},
resultContainer -> resultContainer[0]);
}
现在,DefaultUniConstraintCollector
不是 public 类型。但是您可以使用匿名 class 代替:
public static <A> UniConstraintCollector<A, ?, Integer> sum(ToDoubleFunction<? super A> groupValueMapping) {
return new UniConstraintCollector<A, double[], Double>() {
@Override
public Supplier<double[]> supplier() {
return () -> new double[1];
}
@Override
public BiFunction<double[], A, Runnable> accumulator() {
return (resultContainer, a) -> {
double value = groupValueMapping.applyAsDouble(a);
resultContainer[0] += value;
return () -> resultContainer[0] -= value;
};
}
@Override
public Function<double[], Double> finisher() {
return resultContainer -> resultContainer[0];
}
}
}
使用它需要您自担风险,并确保您 check for score corruptions,最好是在一个很长的求解器中 运行。
我需要一个求和功能,它可以对我的 ConstraintProviding 功能的双精度值求和。当前 OptaPlanner 提供 sum() 和 sumBigDecimal() 功能,其中第一个仅对整数值求和,第二个 BigDecimal 值。因此,我开始使用手册第 6.4.5.3 章中描述的组合方法。用于实现我自己的功能(不想覆盖原来的功能)。
从那里派生并从 OptaPlanner 源代码本身的 ConstraintCollector.java class 中实现求和功能,我最终得到以下代码:
public static <A> UniConstraintCollector<A, ?, Double> sumDouble(ToDoubleFunction<A> groupValueMapping) {
return compose((resultContainer, a) -> {
double value = groupValueMapping.applyAsDouble(a);
resultContainer[0] += value;
return () -> resultContainer[0] -= value;
},
resultContainer -> resultContainer[0]);
}
在我的“OwnConstraintProvider”中 class。但这行不通。错误是:
java: method compose in interface java.lang.module.ModuleFinder cannot be applied to given types;
required: java.lang.module.ModuleFinder[]
found: (resultCon[...]ue; },(resultCon[...]er[0]
reason: varargs mismatch; java.lang.module.ModuleFinder is not a functional interface
multiple non-overriding abstract methods found in interface java.lang.module.ModuleFinder
我知道输入A和结果之间必须有一个更清晰的关系和计算方法。
坦率地说,我最近才开始认真地 Java 编程。所以我无法弄清楚在那种情况下我错在哪里。在当前使用的版本 (8.19.0) 的手册中,第 6.4.5.1.3 章中提到了“用于汇总自定义类型的通用 sum() 变体”。但我对这方面的细节一无所知。
谁能给我一些提示。
提前致谢!
您是否考虑过使用不同的类型,例如long
,以表示您需要在约束中 sum()
的值?
使用 floating-point numbers in the score calculation is generally not recommended 因为它可能会导致分数损坏。
首先,拉多万的回答是完全正确的。事实上,潜在的分数损坏是未提供 sumDouble()
的原因。相反,我们提供 sumBigDecimal()
,它不会遇到同样的问题。但是,它会在性能方面受到影响。首选解决方案是使用 sum()
或 sumLong()
,必要时使用 fixed-point 算法。
也就是说,实现 sumDouble()
相对简单,不需要组合来实现:
public static <A> UniConstraintCollector<A, ?, Double> sum(ToDoubleFunction<? super A> groupValueMapping) {
return new DefaultUniConstraintCollector<>(
() -> new double[1],
(resultContainer, a) -> {
int value = groupValueMapping.applyAsDouble(a);
resultContainer[0] += value;
return () -> resultContainer[0] -= value;
},
resultContainer -> resultContainer[0]);
}
现在,DefaultUniConstraintCollector
不是 public 类型。但是您可以使用匿名 class 代替:
public static <A> UniConstraintCollector<A, ?, Integer> sum(ToDoubleFunction<? super A> groupValueMapping) {
return new UniConstraintCollector<A, double[], Double>() {
@Override
public Supplier<double[]> supplier() {
return () -> new double[1];
}
@Override
public BiFunction<double[], A, Runnable> accumulator() {
return (resultContainer, a) -> {
double value = groupValueMapping.applyAsDouble(a);
resultContainer[0] += value;
return () -> resultContainer[0] -= value;
};
}
@Override
public Function<double[], Double> finisher() {
return resultContainer -> resultContainer[0];
}
}
}
使用它需要您自担风险,并确保您 check for score corruptions,最好是在一个很长的求解器中 运行。