net.jqwik.engine.properties.arbitraries.exhaustive.SetExhaustiveGenerator Maven / Gradle / Ivy
package net.jqwik.engine.properties.arbitraries.exhaustive;
import java.util.*;
import net.jqwik.api.*;
import net.jqwik.engine.support.*;
import static net.jqwik.engine.support.MathSupport.factorial;
class SetExhaustiveGenerator implements ExhaustiveGenerator> {
private final Arbitrary elementArbitrary;
private final long maxCount;
private final int minSize;
private final int maxSize;
static Optional calculateMaxCount(Arbitrary> elementArbitrary, int minSize, int maxSize) {
Optional extends ExhaustiveGenerator>> exhaustiveElement = elementArbitrary.exhaustive();
if (!exhaustiveElement.isPresent())
return Optional.empty();
long elementMaxCount = exhaustiveElement.get().maxCount();
long sum = 0;
for (int n = minSize; n <= maxSize; n++) {
if (n == 0) { // empty set
sum += 1;
continue;
}
if (elementMaxCount < n) { // empty set
continue;
}
if (elementMaxCount > 20) {
// MathSupport.factorial() only works till 20
return Optional.empty();
}
long choices = 0;
try {
// TODO: Use more efficient binomial calculation, e.g. from
// https://rosettacode.org/wiki/Evaluate_binomial_coefficients#Java
// and move it to MathSupport
choices = factorial(elementMaxCount) / (factorial(elementMaxCount - n) * factorial(n));
} catch (ArithmeticException ae) {
return Optional.empty();
}
if (choices > ExhaustiveGenerators.MAXIMUM_ACCEPTED_MAX_COUNT || choices < 0) { // Stop when break off point reached
return Optional.empty();
}
sum += choices;
}
return Optional.of(sum);
}
SetExhaustiveGenerator(Arbitrary elementArbitrary, long maxCount, int minSize, int maxSize) {
this.elementArbitrary = elementArbitrary;
this.minSize = minSize;
this.maxSize = maxSize;
this.maxCount = maxCount;
}
@Override
public Iterator> iterator() {
return Combinatorics.setCombinations(elementArbitrary.exhaustive().get(), minSize, maxSize);
}
@Override
public long maxCount() {
return maxCount;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy