我正在寻找一种将Boolean
表达式转换为threshold
表达式的可能方法。
例如,我得到了boolean
表达式:
((A & B)|(C & D)) | ((A | B) & (C | D))
它实际上意味着从以下集合中选择任意两个:
{A,B,C,D}
如果我们使用阈值表达式,我们可以将其表示为:
A,B,C,D 2outof4
但我找不到办法让这项工作。
有可能的方法吗?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~
实际上,我想知道的是:
给出一个布尔表达式,如:
((A & B)|(C & D)) | ((A | B) & (C | D))
是否可以识别表达式实际上是从集合中选择2个元素{A,B,C,D} ?
然后输出类似
的内容A,B,C,D 2outof4
答案 0 :(得分:0)
您可以使用Stream
,filter
,然后使用count
元素
if (Stream.of(A, B, C, D).filter(x -> x).count() >= 2)
答案 1 :(得分:0)
好的,总而言之,您要确定布尔表达式是否为组合生成器。
我相信下面列出的代码可以实现这一目标。您可以看到它包含一个与您的示例结构相同的表达式:
or(
or(
and(value("A"), value("B")),
and(value("C"), value("D"))
), and(
or(value("A"), value("B")),
or(value("C"), value("D"))
)
);
然后用作DSL来生成组合:
{A,B}
{A,C}
{A,D}
{B,C}
{B,D}
{C,D}
然后检查生成的组合以查看它们是否满足以下条件:
如果组合满足这些要求,那么布尔表达式必须是从 N 中选择 r 值的生成器。
最后一行输出是:
Optional[{A,B,C,D} 2 of 4]
表示表达式是一个用于从4中选择2个值的生成器。
以下是完整的实施:
import java.util.*;
import static java.util.Collections.singleton;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;
class Combinations {
static <T> Set<T> union(Collection<T> lhs, Collection<T> rhs) {
final Set<T> result = new HashSet<>(lhs);
result.addAll(rhs);
return result;
}
static <T> String collToString(Collection<T> l) {
return l.stream()
.map(Object::toString)
.collect(joining(",", "{", "}"));
}
static <T> Set<Set<T>> value(T value) {
return singleton(singleton(value));
}
static <T> Set<Set<T>> or(Set<Set<T>> lhs, Set<Set<T>> rhs) {
return union(lhs, rhs);
}
static <T> Set<Set<T>> and(Set<Set<T>> lhs, Set<Set<T>> rhs) {
return lhs.stream()
.flatMap(ls -> rhs.stream().map(rs -> union(ls, rs)))
.collect(toSet());
}
static class Choose<T> {
private static int binomial(final int n, final int r) {
int ret = 1;
for (int k = 0; k < r; k++) {
ret = ret * (n-k) /(k+1);
}
return ret;
}
static <T> Optional<Choose<T>> of(Set<Set<T>> sst) {
final Set<Integer> sizes = sst.stream().map(Set::size).collect(toSet());
if (sizes.size() != 1) {
return Optional.empty();
} else {
final int r = sizes.iterator().next();
final Set<T> values = sst.stream().flatMap(Set::stream).collect(toSet());
final int n = values.size();
final int ncr = binomial(n, r);
if (sst.size() == ncr) {
return Optional.of(new Choose<>(values, r));
} else {
return Optional.empty();
}
}
}
public final Set<T> values;
public final int r;
Choose(Set<T> values, int r) {
this.values = values;
this.r = r;
}
@Override
public String toString() {
return collToString(values) + " " + r + " of " + values.size();
}
}
public static void main(String[] args) {
// Generate the combinations.
final Set<Set<String>> combos =
or(
or(
and(value("A"), value("B")),
and(value("C"), value("D"))
), and(
or(value("A"), value("B")),
or(value("C"), value("D"))
)
);
// Print the combinations to stdout.
combos.stream()
.map(ss -> collToString(ss))
.forEach(System.out::println);
Optional<Choose<String>> choose = Choose.of(combos);
System.out.println(choose);
}
}