Custom "sumDouble()" function in OptaPlanner for constraints - java

I need a sum functionality that sums up double values for my ConstraintProviding functionality. Currently OptaPlanner offers sum() and sumBigDecimal() functionality, where the first is only summing integer values and the second BigDecimal values. So therefore I started with the compose approach as described in the manual chapter 6.4.5.3. for implementing my own functionality (didn't want to override the original one).
Deriving from there and taking the implementation of the sum functionality from the ConstraintCollector.java class of the OptaPlanner source code itself, I ended up with the following code:
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]);
}
within my "OwnConstraintProvider" class. But this doesn't work out. The error is:
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
I am aware that there must be a clearer relationship and calculation approach between the input A and the result.
Frankly speaking I have only recently starting Java programming seriously. So I can't sort out where I am mistaken in that case. In the manual of the current version used (8.19.0) there is "a generic sum() variant for summing up custom types" mentioned in chapter 6.4.5.1.3. but I have no glue about the details on that.
Can anybody give me a hint on this please.
Thanks in advance!

First of all, Radovan is completely correct in his answer. In fact, the potential score corruptions are the reason why sumDouble() is not provided. Instead, we provide sumBigDecimal(), which doesn't suffer from the same issue. However, it will suffer in terms of performance. The preferred solution is to use either sum() or sumLong(), using fixed-point arithmetic if necessary.
That said, implementing sumDouble() is relatively simple, and you do not need composition to achieve that:
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]);
}
Now, DefaultUniConstraintCollector is not a public type. But you can use an anonymous class instead:
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];
}
}
}
Use this at your own risk, and make sure you check for score corruptions, preferrably in a very long solver run.

Have you considered using a different type, e.g. long, to represent values you need to sum() in your constraint?
Using floating-point numbers in the score calculation is generally not recommended as it may lead to score corruption.

Related

Java implement accumulator class that provides a Collector

A Collector has three generic types:
public interface Collector<T, A, R>
With A being the mutable accumulation type of the reduction operation (often hidden as an implementation detail).
If I want to create my custom collector, I need to create two classes:
one for the custom accumulation type
one for the custom collector itself
Is there any library function/trick that takes the accumulation type and provides a corresponding Collector?
Simple example
This example is extra simple to illustrate the question, I know I could use reduce for this case, but this is not what I am looking for. Here is a more complex example that sharing here would make the question too long, but it is the same idea.
Let's say I want to collect the sum of a stream and return it as a String.
I can implement my accumulator class:
public static class SumCollector {
Integer value;
public SumCollector(Integer value) {
this.value = value;
}
public static SumCollector supply() {
return new SumCollector(0);
}
public void accumulate(Integer next) {
value += next;
}
public SumCollector combine(SumCollector other) {
return new SumCollector(value + other.value);
}
public String finish(){
return Integer.toString(value);
}
}
And then I can create a Collector from this class:
Collector.of(SumCollector::supply, SumCollector::accumulate, SumCollector::combine, SumCollector::finish);
But it seems strange to me that they all refer to the the other class, I feel that there is a more direct way to do this.
What I could do to keep only one class would be implements Collector<Integer, SumCollector, String> but then every function would be duplicated (supplier() would return SumCollector::supply, etc).
There is no requirement for the functions to be implemented as methods of the container class.
This is how such a sum collector would be typically implemented
public static Collector<Integer, ?, Integer> sum() {
return Collector.of(() -> new int[1],
(a, i) -> a[0] += i,
(a, b) -> { a[0] += b[0]; return a; },
a -> a[0],
Collector.Characteristics.UNORDERED);
}
But, of course, you could also implement it as
public static Collector<Integer, ?, Integer> sum() {
return Collector.of(AtomicInteger::new,
AtomicInteger::addAndGet,
(a, b) -> { a.addAndGet(b.intValue()); return a; },
AtomicInteger::intValue,
Collector.Characteristics.UNORDERED, Collector.Characteristics.CONCURRENT);
}
You first have to find a suitable mutable container type for your collector. If no such type exists, you have to create your own class. The functions can be implemented as a method reference to an existing method or as a lambda expression.
For the more complex example, I don’t know of a suitable existing type for holding an int and a List, but you may get away with a boxed Integer, like this
final Map<String, Integer> map = …
List<String> keys = map.entrySet().stream().collect(keysToMaximum());
public static <K> Collector<Map.Entry<K,Integer>, ?, List<K>> keysToMaximum() {
return Collector.of(
() -> new AbstractMap.SimpleEntry<>(new ArrayList<K>(), Integer.MIN_VALUE),
(current, next) -> {
int max = current.getValue(), value = next.getValue();
if(value >= max) {
if(value > max) {
current.setValue(value);
current.getKey().clear();
}
current.getKey().add(next.getKey());
}
}, (a, b) -> {
int maxA = a.getValue(), maxB = b.getValue();
if(maxA <= maxB) return b;
if(maxA == maxB) a.getKey().addAll(b.getKey());
return a;
},
Map.Entry::getKey
);
}
But you may also create a new dedicated container class as an ad-hoc type, not visible outside the particular collector
public static <K> Collector<Map.Entry<K,Integer>, ?, List<K>> keysToMaximum() {
return Collector.of(() -> new Object() {
int max = Integer.MIN_VALUE;
final List<K> keys = new ArrayList<>();
}, (current, next) -> {
int value = next.getValue();
if(value >= current.max) {
if(value > current.max) {
current.max = value;
current.keys.clear();
}
current.keys.add(next.getKey());
}
}, (a, b) -> {
if(a.max <= b.max) return b;
if(a.max == b.max) a.keys.addAll(b.keys);
return a;
},
a -> a.keys);
}
The takeaway is, you don’t need to create a new, named class to create a Collector.
I want to focus the wording of one point of your question, because I feel like it could be the crux of the underlying confusion.
If I want to create my custom collector, I need to create two classes:
one for the custom accumulation type
one for the custom collector itself
No, you need to create only one class, that of your custom accumulator. You should use the appropriate factory method to instantiate your custom Collector, as you demonstrate yourself in the question.
Perhaps you meant to say that you need to create two instances. And that is also incorrect; you need to create a Collector instance, but to support the general case, many instances of the accumulator can be created (e.g., groupingBy()). Thus, you can't simply instantiate the accumulator yourself, you need to provide its Supplier to the Collector, and delegate to the Collector the ability to instantiate as many instances as required.
Now, think about the overloaded Collectors.of() method you feel is missing, the "more direct way to do this." Clearly, such a method would still require a Supplier, one that would create instances of your custom accumulator. But Stream.collect() needs to interact with your custom accumulator instances, to perform accumulate and combine operations. So the Supplier would have to instantiate something like this Accumulator interface:
public interface Accumulator<T, A extends Accumulator<T, A, R>, R> {
/**
* #param t a value to be folded into this mutable result container
*/
void accumulate(T t);
/**
* #param that another partial result to be merged with this container
* #return the combined results, which may be {#code this}, {#code that}, or a new container
*/
A combine(A that);
/**
* #return the final result of transforming this intermediate accumulator
*/
R finish();
}
With that, it's then straightforward to create Collector instances from an Supplier<Accumulator>:
static <T, A extends Accumulator<T, A, R>, R>
Collector<T, ?, R> of(Supplier<A> supplier, Collector.Characteristics ... characteristics) {
return Collector.of(supplier,
Accumulator::accumulate,
Accumulator::combine,
Accumulator::finish,
characteristics);
}
Then, you'd be able to define your custom Accumulator:
final class Sum implements Accumulator<Integer, Sum, String> {
private int value;
#Override
public void accumulate(Integer next) {
value += next;
}
#Override
public Sum combine(Sum that) {
value += that.value;
return this;
}
#Override
public String finish(){
return Integer.toString(value);
}
}
And use it:
String sum = ints.stream().collect(Accumulator.of(Sum::new, Collector.Characteristics.UNORDERED));
Now… it works, and there's nothing too horrible about it, but is all the Accumulator<A extends Accumulator<A>> mumbo-jumbo "more direct" than this?
final class Sum {
private int value;
private void accumulate(Integer next) {
value += next;
}
private Sum combine(Sum that) {
value += that.value;
return this;
}
#Override
public String toString() {
return Integer.toString(value);
}
static Collector<Integer, ?, String> collector() {
return Collector.of(Sum::new, Sum::accumulate, Sum::combine, Sum::toString, Collector.Characteristics.UNORDERED);
}
}
And really, why have an Accumulator dedicated to collecting to a String? Wouldn't reduction to a custom type be more interesting? Something that along the lines of IntSummaryStatistics that has other useful methods like average() alongside toString()? This approach is a lot more powerful, requires only one (mutable) class (the result type) and can encapsulate all of its mutators as private methods rather than implementing a public interface.
So, you're welcome to use something like Accumulator, but it doesn't really fill a real gap in the core Collector repertoire.
It sounds like you want to supply only the reduction function itself, not all of the other things that come with a generic Collector. Perhaps you're looking for Collectors.reducing.
public static <T> Collector<T,?,T> reducing(T identity, BinaryOperator<T> op)
Then, to sum values, you would write
Collectors.reducing(0, (x, y) -> x + y);
or, in context,
Integer[] myList = new Integer[] { 1, 2, 3, 4 };
var collector = Collectors.reducing(0, (x, y) -> x + y);
System.out.println(Stream.of(myList).collect(collector)); // Prints 10

Vavr: Howto flatmap collection inside optional object

Is any easiest way to write this code below, without using toStream()?
import io.vavr.collection.List;
import io.vavr.control.Option;
import lombok.Value;
public class VavrDemo {
public static void main(String[] args) {
Foo bar = new Foo(List.of(new Bar(1), new Bar(2)));
Number value = Option.some(bar)
.toStream() // <- WTF?!?
.flatMap(Foo::getBars)
.map(Bar::getValue)
.sum();
System.out.println(value);
}
#Value
static class Foo {
private List<Bar> bars;
}
#Value
static class Bar {
private int value;
}
}
Option is a so-called Monad. This just tells us that the flatMap function follows specific laws, namely
Let
A, B, C be types
unit: A -> Monad<A> a constructor
f: A -> Monad<B>, g: B -> Monad<C> functions
a be an object of type A
m be an object of type Monad<A>
Then all instances of the Monad interface should obey the Functor laws (omitted here) and the three control laws:
Left identity: unit(a).flatMap(f) ≡ f a
Right identity: m.flatMap(unit) ≡ m
Associativity: m.flatMap(f).flatMap(g) ≡ m.flatMap(x -> f.apply(x).flatMap(g))
Currently Vavr has (simplified):
interface Option<T> {
<U> Option<U> flatMap(Function<T, Option<U>> mapper) {
return isEmpty() ? none() : mapper.apply(get());
}
}
This version obeys the Monad laws.
It is not possible to define an Option.flatMap the way you want that still obeys the Monad laws. For example imagine a flatMap version that accepts a function with an Iterable as result. All Vavr collections have such a flatMap method but for Option it does not make sense:
interface Option<T> {
<U> Option<U> flatMap(Function<T, Iterable<U>> mapper) {
if (isEmpty()) {
return none();
} else {
Iterable<U> iterable = mapper.apply(get());
if (isEmpty(iterable)) {
return none();
} else {
U resultValue = whatToDoWith(iterable); // ???
return some(resultValue);
}
}
}
}
You see? The best thing we can do is to take just one element of the iterable in case it is not empty. Beside it does not give use the result you may have expected (in VavrTest above), we can proof that this 'phantasy' version of flatMap does break the Monad laws.
If you are stuck in such a situation, consider to change your calls slightly. For example the VavrTest can be expressed like this:
Number value = Option.some(bar)
.map(b -> b.getBars().map(Bar::getValue).sum())
.getOrElse(0);
I hope this helps and the Monad section above does not completely scare you away. In fact, developers do not need to know anything about Monads in order to take advantage of Vavr.
Disclaimer: I'm the creator of Vavr (formerly: Javaslang)
How about using .fold() or .getOrElse()?
Option.some(bar)
.fold(List::<Bar>empty, Foo::getBars)
.map(Bar::getValue)
.sum();
Option.some(bar)
.map(Foo::getBars)
.getOrElse(List::empty)
.map(Bar::getValue)
.sum();

Java 8 Streams: simplifying o1 -> Objects.equals(o1.getSome().getSomeOther(), o2.getSome().getSomeOther()) in a stream

Given the following code:
stream.filter(o1 -> Objects.equals(o1.getSome().getSomeOther(),
o2.getSome().getSomeOther())
How could that possibly be simplified?
Is there some equals-utility that lets you first extract a key just like there is Comparator.comparing which accepts a key extractor function?
Note that the code itself (getSome().getSomeOther()) is actually generated from a schema.
EDIT: (after discussing with a collegue and after revisiting: Is there a convenience method to create a Predicate that tests if a field equals a given value?)
We now have come to the following reusable functional interface:
#FunctionalInterface
public interface Property<T, P> {
P extract(T object);
default Predicate<T> like(T example) {
Predicate<P> equality = Predicate.isEqual(extract(example));
return (value) -> equality.test(extract(value));
}
}
and the following static convenience method:
static <T, P> Property<T, P> property(Property<T, P> property) {
return property;
}
The filtering now looks like:
stream.filter(property(t -> t.getSome().getSomeOther()).like(o2))
What I like on this solution in respect to the solution before: it clearly separates the extraction of the property and the creation of the Predicate itself and it states more clearly what is going on.
Previous solution:
<T, U> Predicate<T> isEqual(T other, Function<T, U> keyExtractFunction) {
U otherKey = keyExtractFunction.apply(other);
return t -> Objects.equals(keyExtractFunction.apply(t), otherKey);
}
which results in the following usage:
stream.filter(isEqual(o2, t -> t.getSome().getSomeOther())
but I am more then happy if anyone has a better solution.
I think that your question's approach is more readable than your answer's one. And I also think that using inline lambdas is fine, as long as the lambda is simple and short.
However, for maintainance, readability, debugging and testability reasons, I always move the logic I'd use in a lambda (either a predicate or function) to one or more methods. In your case, I would do:
class YourObject {
private Some some;
public boolean matchesSomeOther(YourObject o2) {
return this.getSome().matchesSomeOther(o2.getSome());
}
}
class Some {
private SomeOther someOther;
public boolean matchesSomeOther(Some some2) {
return Objects.isEqual(this.getSomeOther(), some2.getSomeOther());
}
}
With these methods in place, your predicate now becomes trivial:
YourClass o2 = ...;
stream.filter(o2::matchesSomeOther)

How can my method accept any type of Number, as a method argument? (Java generics)

My CustomNumber class extends the Number class (implements all the method, but not listed here). The class has a division method, which should work as the following: I can give to it any type of Number argument, and always get a the calculation without precision loss. That is why I'm thinking about double values. But in this case, I can't call this method with anything else, but Double Objects. How can I make this method, any maybe the whole class 100% generic?
public class CustomNumber<T> extends java.lang.Number {
java.lang.Number value;
public CustomNumber(java.lang.Number value) {
this.value = value;
}
public static CustomNumber<Double> division(Number a, Number b) {
return new CustomNumber<>(a.doubleValue() / b.doubleValue());
}
}
In this respect, Java is extremely annoying.
They dogmatically disallowed operator overloading (although Scala has it), so you are compelled to code / into a method called divide or similar, and so on.
For more specifics see how the arbitrary precision libraries such as BigInteger are implemented, and base your solution from that.
One a plus point in Java, you might get away with using BigDecimal and doing away with your idea entirely. Although the code you end up with when performing complex mathematical operations with it is practically unreadable. (For this reason I resort to using C++ with a JNI).
If this was what you were trying, it doesn’t work:
CustomNumber<Integer> quotient = division(5, 3);
We get “Type mismatch: cannot convert from CustomNumber<Double> to CustomNumber<Integer>”. For an obvious reason. Even though the numbers you tried to divide were autoboxed into Integer.
The straightforward solution is to drop the generics completely:
public class CustomNumber extends java.lang.Number {
// ...
public static CustomNumber division(Number a, Number b) {
return new CustomNumber(a.doubleValue() / b.doubleValue());
}
}
Now we have no problem doing:
CustomNumber quotient = division(5, 3);
System.out.println(quotient);
With an appropriate toString method in your class this should print:
1.6666666666666667
java.lang.Number offers very few methods. Division, for instance, doesn't really do the same thing for each type. 1.0d/2.0d is 0.5d but 1/2 is 0. So you're going have to decide which you're doing. Also note the double does not exactly represent long or, say, BigInteger.
To map various forms of numbers to your common interpretation, you'll need an adapter layer. There may be ore than one way to map a numeric type.
public interface CustomNumber<THIS extends CustomNumber<THIS>> {
THIS divide(THIS other);
}
public final class LongNumber extends CustomNumber<LongNumber> {
// (Note, you don't actually need to overload this,
// but it does prevent the likes of LongNumber.of(aDouble).)
public static LongNumber of(Long value) {
return new LongNumber(value);
}
public static LongNumber of(AtomicLong value) {
return new LongNumber(value);
}
private final Number value;
private LongNumber(Number value) {
this.value = value;
}
#Override public LongNumber divide(LongNumber other) {
return this.longValue() / other.longValue();
}
}
You might want to have an adapter for the same types that deal with, say, bankers' rounding. I don't want to even think about how to implement that. Or full on saturated arithmetic. So here's is a sign preserving alternative implementation (still does division by zero):
#Override public SignPreservingLongNumber divide(
SignPreservingLongNumber other
) {
long dividend = this.longValue();
long divisor = other.longValue();
return (
dividend == Long.MIN_VALUE &&
divisor == -1
) ? Long.MAX_VALUE : dividend/divisor;
}

Can I have function types in Java's Enum like Swift?

Is it possible to write an equivalent code in Java for the following swift code? In fact, I want to know if it's possible to have a case of functions inside Java's enum (X, Y in MyEnum)
enum MyEnum{
case X((Int) -> String)
case Y((Double) -> Int)
}
No, you can't; at least, not if you want the differing types to be available when you use the enum. All enum values have to have the same type.
When you want "enum" values to have heterogenous types, you could use a class with static final fields:
final class MyHeterogeneousEnum {
private MyHeterogeneousEnum() {} // Not instantiable.
static final Function<Integer, String> X = ...;
static final Function<Double, Integer> Y = ...;
}
which allows you to use the values with their full type information:
String s = MyHeterogeneousEnum.X.apply(123);
Integer i = MyHeterogeneousEnum.Y.apply(999.0);
Of course, you don't have useful methods like name(), or values() to iterate over the constants in this class, nor is it inherently serializable. You can make implement these yourself - but for values() you have to use wildcards in the return type, in order that all values can be returned:
static Iterable<Function<?, ?>> values() {
return Collections.unmodifiableList(Arrays.asList(X, Y));
}
However, note that a Function with a wildcard input type parameter is pretty much useless: you can't actually pass anything into it (other than null); so the values() method has limited utility.
It is possible (technically), but it might not be that useful, as creating a simple class, that consumes a Function instance.
As you might already know, in Java, the enums represent one or more constants of the same type, which could have their own properties - this include java.util.Function instances. However, these Function instances cannot be passed dynamically at Runtime, but should be rather set at compile time, so that the constant is created.
Of course, you could make each enum constant have a different typed Function, by just creating the enum's constructor Generic:
enum MyEnum {
X((String x) -> "Hello"), Y((Double d) -> 1);
Function<?, ?> function;
MyEnum(Function<?, ?> function) {
this.function = function;
}
}
This, however, is not quite useful (although it compiles just fine). The Function in X doesn't use it's String parameter and returns a fixed value. So does the one in Y.
I'd rather introduce two separate instances of the same class:
class Instance<T, U> {
private Function<T, U> function;
public Instance(Function<T, U> function) {
this.function = function;
}
}
This will allow you to dynamically pass a Function instance, instead of setting it at compile-time.
Yes for sure you can, in java enums can be more that just constants... every one of it values can be an anonymous class (take a look to TimeUnit.class for example)
now, you can do somthing like:
interface IFunction {
double getY(double x);
}
enum Function implements IFunction {
LINE {
#Override
public double getY(double x) {
return x;
}
},
SINE {
#Override
public double getY(double x) {
return Math.sin(x);
}
}
}
and then the implementation
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Function.LINE.getY(i));
System.out.println(Function.SINE.getY(i));
}
}

Categories