Search in sources :

Example 21 with FasterList

use of jcog.list.FasterList in project narchy by automenta.

the class NarseseParser method popTerms.

FasterList<Term> popTerms(Op[] op) /* hint */
{
    FasterList tt = new FasterList(8);
    ArrayValueStack<Object> stack = (ArrayValueStack) getContext().getValueStack();
    while (!stack.isEmpty()) {
        Object p = pop();
        if (p instanceof Object[]) {
            // it's an array so unpack by pushing everything back onto the stack except the last item which will be used as normal below
            Object[] pp = (Object[]) p;
            if (pp.length > 1) {
                for (int i = pp.length - 1; i >= 1; i--) {
                    stack.push(pp[i]);
                }
            }
            p = pp[0];
        }
        if (p == functionalForm) {
            op[0] = ATOM;
            break;
        }
        // beginning of stack frame for this term
        if (p == Compound.class)
            break;
        if (p instanceof String) {
            // throw new RuntimeException("string not expected here");
            // Term t = $.the((String) p);
            tt.add(Atomic.the((String) p));
        } else if (p instanceof Term) {
            if (p == Null) {
                stack.clear();
                return new FasterList(1).addingAll(Null);
            }
            tt.add(p);
        } else if (p instanceof Op) {
            if (op != null)
                op[0] = (Op) p;
        }
    }
    tt.reverse();
    return tt;
}
Also used : Op(nars.Op) FasterList(jcog.list.FasterList) Term(nars.term.Term) ArrayValueStack(com.github.fge.grappa.stack.ArrayValueStack)

Example 22 with FasterList

use of jcog.list.FasterList in project narchy by automenta.

the class Builtin method registerFunctors.

public static void registerFunctors(NAR nar) {
    for (Concept t : Builtin.statik) {
        nar.on(t);
    }
    nar.on(Functor.f1("varIntro", (x) -> {
        Pair<Term, Map<Term, Term>> result = DepIndepVarIntroduction.the.apply(x, nar.random());
        return result != null ? result.getOne() : Null;
    }));
    nar.on(Functor.f1((Atom) $.the("termlinkRandom"), (Term t) -> {
        @Nullable Concept c = nar.conceptualize(t);
        if (c == null)
            return Null;
        @Nullable PriReference<Term> tl = c.termlinks().sample(nar.random());
        if (tl == null)
            return Null;
        return tl.get();
    }));
    // nar.on(Functor.f("service", (TermContainer c) ->
    // $.sete(
    // nar.services().map(
    // (e) ->
    // $.p(e, $.the(e.getValue().state())))
    // .toArray(Term[]::new)
    // )
    // ));
    /**
     * subterm, but specifically inside an ellipsis. otherwise pass through
     */
    nar.on(Functor.f("esubterm", (Subterms c) -> {
        Term x = c.sub(0, null);
        if (x == null)
            return Null;
        Term index = c.sub(1, Null);
        if (index == Null)
            return Null;
        int which;
        if (index != null) {
            if (index instanceof Variable)
                return Null;
            which = $.intValue(index, -1);
            if (which < 0) {
                return Null;
            }
        } else {
            // random
            which = nar.random().nextInt(x.subs());
        }
        return x.sub(which);
    }));
    nar.on(Functor.f2((Atom) $.the("without"), (Term container, Term content) -> Op.without(container, x -> x.equals(content), nar.random())));
    nar.on(Functor.f2((Atom) $.the("withoutPosOrNeg"), (Term container, Term content) -> Op.without(container, x -> x.unneg().equals(content), nar.random())));
    /**
     * TODO rename this to 'dropAnyCommutive'
     * remove an element from a commutive conjunction (or set), at random, and try re-creating
     * the compound. wont necessarily work in all situations.
     * TODO move the type restriction to another functor to wrap this
     *
     * this also filter a single variable (depvar) from being a result
     */
    nar.on(Functor.f1((Atom) $.the("dropAnySet"), (Term t) -> {
        Op oo = t.op();
        if (oo == INT) {
            if (t instanceof Int.IntRange) {
                // select random location in the int and split either up or down
                Int.IntRange i = (Int.IntRange) t;
                Random rng = nar.random();
                if (i.min + 1 == i.max) {
                    // arity=2
                    return Int.the(rng.nextBoolean() ? i.min : i.max);
                } else if (i.min + 2 == i.max) {
                    // arity=3
                    switch(rng.nextInt(4)) {
                        case 0:
                            return Int.the(i.min);
                        case 1:
                            return Int.range(i.min, i.min + 1);
                        case 2:
                            return Int.range(i.min + 1, i.min + 2);
                        case 3:
                            return Int.the(i.max);
                        default:
                            throw new UnsupportedOperationException();
                    }
                } else {
                    int split = // midpoint, deterministic
                    (i.max + i.min) / 2;
                    // rng.nextInt(i.max-i.min-2);
                    return (rng.nextBoolean()) ? Int.range(i.min, split + 1) : Int.range(split + 1, i.max);
                }
            }
            // cant drop int by itself
            return Null;
        }
        if (!oo.in(SETi.bit | SETe.bit | SECTi.bit | SECTe.bit))
            // returning the original value may cause feedback loop in callees expcting a change in value
            return Null;
        int size = t.subs();
        switch(size) {
            case 0:
                assert (false) : "empty set impossible here";
                return Null;
            case 1:
                return Null;
            /* can't shrink below one element */
            case 2:
                int n = nar.random().nextInt(2);
                return oo.the(t.sub(n));
            default:
                Term[] y = Terms.dropRandom(nar.random(), t.subterms());
                return oo.the(y);
        }
    }));
    /**
     * depvar cleaning from commutive conj
     */
    nar.on(Functor.f1((Atom) $.the("ifConjCommNoDepVars"), (Term t) -> {
        if (!t.hasAny(VAR_DEP))
            return t;
        Op oo = t.op();
        if (oo != CONJ)
            return t;
        SortedSet<Term> s = t.subterms().toSetSorted();
        if (!s.removeIf(x -> x.unneg().op() == VAR_DEP))
            return t;
        return CONJ.the(t.dt(), s);
    }));
    /**
     * drops a random contained event, whether at first layer or below
     */
    nar.on(Functor.f1((Atom) $.the("dropAnyEvent"), (Term t) -> {
        Op oo = t.op();
        if (oo != CONJ)
            // returning the original value may cause feedback loop in callees expcting a change in value
            return Null;
        FasterList<LongObjectPair<Term>> ee = Conj.eventList(t);
        ee.remove(nar.random().nextInt(ee.size()));
        return Conj.conj(ee);
    // }
    // if (r instanceof Variable /*&& r.op()!=VAR_DEP*/)
    // return Null; //HACK dont allow returning a variable as an event during decomposition HACK TODO make more careful and return the only result if one subterm is a non-returnable variable
    // return r;
    }));
    nar.on(Functor.f2((Atom) $.the("conjEvent"), (Term c, Term when) -> {
        if (c.op() != CONJ || !(when instanceof Atom))
            return Null;
        // extract earliest or latest &| timeslice of events
        throw new TODO();
    // if (c.dt() == DTERNAL || c.dt() == 0) {
    // return c.sub(nar.random().nextInt(c.subs())); //choose a subterm at random
    // }
    // assert (c.subs() == 2);
    // int target;
    // switch (when.toString()) {
    // case "early":
    // target = 0;
    // break;
    // case "late":
    // target = 1;
    // break;
    // default:
    // throw new UnsupportedOperationException();
    // }
    // if (c.dt() < 0)
    // target = 1 - target;
    // return c.sub(target);
    }));
    /**
     * similar to without() but special handling for CONJ sub-events
     */
    nar.on(Functor.f2((Atom) $.the("conjWithout"), (Term conj, Term event) -> {
        if (conj.op() != CONJ || conj.impossibleSubTerm(event))
            return Null;
        FasterList<LongObjectPair<Term>> events = Conj.eventList(conj);
        IntArrayList found = new IntArrayList(2);
        int es = events.size();
        assert (es > 1);
        for (int i = 0; i < es; i++) {
            if (event.equalsRoot(events.get(i).getTwo())) {
                found.add(i);
            }
        }
        int fs = found.size(), r;
        switch(fs) {
            case 0:
                return Null;
            case 1:
                r = found.get(0);
                break;
            default:
                r = found.get(nar.random().nextInt(fs));
                break;
        }
        events.remove(r);
        return Conj.conj(events);
    // } else {
    // return nullToNull(Op.without(conj, event::equalsRoot, nar.random()));
    // }
    }));
    /**
     * extracts only the events preceding the specified events
     */
    nar.on(Functor.f2((Atom) $.the("conjDropIfLatest"), (Term conj, Term event) -> Conj.conjDrop(conj, event, false)));
    nar.on(Functor.f2((Atom) $.the("conjDropIfEarliest"), (Term conj, Term event) -> Conj.conjDrop(conj, event, true)));
    nar.on(Functor.f1Concept("belief", nar, (c, n) -> $.quote(n.belief(c, n.time()))));
    nar.on(Functor.f1Concept("goal", nar, (c, n) -> $.quote(n.goal(c, n.time()))));
    nar.on(f0("self", nar::self));
    nar.on(Functor.f1("the", what -> {
        if (what instanceof Atom) {
            switch(what.toString()) {
                case "sys":
                    return $.p($.quote(nar.emotion.summary()), $.quote(nar.concepts.summary()), $.quote(nar.emotion.summary()), $.quote(nar.exe.toString()));
            }
        }
        Object x = nar.concept(what);
        if (x == null)
            x = what;
        return $.quote($.p($.quote(x.getClass().toString()), $.quote(x.toString())));
    }));
    // /** slice(<compound>,<selector>)
    // selector :-
    // a specific integer value index, from 0 to compound size
    // (a,b) pair of integers, a range of indices */
    nar.on(Functor.f("slice", (args) -> {
        if (args.subs() == 2) {
            Term x = args.sub(0);
            if (x.subs() > 0) {
                int len = x.subs();
                Term index = args.sub(1);
                Op o = index.op();
                if (o == INT) {
                    // specific index
                    int i = ((Int) index).id;
                    if (i >= 0 && i < len)
                        return x.sub(i);
                    else
                        return False;
                } else if (o == PROD && index.subs() == 2) {
                    Term start = (index).sub(0);
                    if (start.op() == INT) {
                        Term end = (index).sub(1);
                        if (end.op() == INT) {
                            int si = ((Int) start).id;
                            if (si >= 0 && si < len) {
                                int ei = ((Int) end).id;
                                if (ei >= 0 && ei <= len) {
                                    if (si == ei)
                                        return Op.EmptyProduct;
                                    if (si < ei) {
                                        return $.p(Arrays.copyOfRange(x.subterms().arrayClone(), si, ei));
                                    }
                                }
                            }
                            // TODO maybe reverse order will return reversed subproduct
                            return False;
                        }
                    }
                }
            }
        }
        return null;
    }));
}
Also used : Concept(nars.concept.Concept) Atom(nars.term.atom.Atom) java.util(java.util) MathFunc(nars.op.MathFunc) Subst(nars.op.Subst) Variable(nars.term.var.Variable) nars.op.data(nars.op.data) Functor.f0(nars.term.Functor.f0) Int(nars.term.atom.Int) Op(nars.Op) Conj(nars.term.compound.util.Conj) User(jcog.User) Texts(jcog.Texts) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Pair(org.eclipse.collections.api.tuple.Pair) Concept(nars.concept.Concept) LongObjectPair(org.eclipse.collections.api.tuple.primitive.LongObjectPair) Term(nars.term.Term) ScriptException(javax.script.ScriptException) DepIndepVarIntroduction(nars.op.DepIndepVarIntroduction) Opjects(nars.op.java.Opjects) IntArrayList(org.eclipse.collections.impl.list.mutable.primitive.IntArrayList) UnifiedMap(org.eclipse.collections.impl.map.mutable.UnifiedMap) Predicate(java.util.function.Predicate) FasterList(jcog.list.FasterList) Functor(nars.term.Functor) ListFunc(nars.op.ListFunc) Terms(nars.term.Terms) Nullable(org.jetbrains.annotations.Nullable) TODO(jcog.TODO) java.io(java.io) Subterms(nars.subterm.Subterms) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) PriReference(jcog.pri.PriReference) Operator(nars.concept.Operator) Subterms(nars.subterm.Subterms) Op(nars.Op) TODO(jcog.TODO) Variable(nars.term.var.Variable) FasterList(jcog.list.FasterList) Term(nars.term.Term) PriReference(jcog.pri.PriReference) Atom(nars.term.atom.Atom) Int(nars.term.atom.Int) IntArrayList(org.eclipse.collections.impl.list.mutable.primitive.IntArrayList) Pair(org.eclipse.collections.api.tuple.Pair) LongObjectPair(org.eclipse.collections.api.tuple.primitive.LongObjectPair)

Example 23 with FasterList

use of jcog.list.FasterList in project narchy by automenta.

the class Optimize method run.

public Result<X> run(int maxIterations, int repeats, FloatFunction<Supplier<X>> eval) {
    assert (repeats >= 1);
    final int dim = tweaks.size();
    double[] mid = new double[dim];
    // double[] sigma = new double[n];
    double[] min = new double[dim];
    double[] max = new double[dim];
    double[] inc = new double[dim];
    // double[] range = new double[dim];
    X example = subject.get();
    int i = 0;
    for (Tweak w : tweaks) {
        TweakFloat s = (TweakFloat) w;
        // initial guess: get from sample, otherwise midpoint of min/max range
        Object guess = s.get(example);
        mid[i] = guess != null ? ((float) guess) : ((s.getMax() + s.getMin()) / 2f);
        min[i] = (s.getMin());
        max[i] = (s.getMax());
        inc[i] = s.getInc();
        // range[i] = max[i] - min[i];
        // sigma[i] = Math.abs(max[i] - min[i]) * 0.75f; //(s.getInc());
        i++;
    }
    FasterList<DoubleObjectPair<double[]>> experiments = new FasterList<>(maxIterations);
    final double[] maxScore = { Double.NEGATIVE_INFINITY };
    ObjectiveFunction func = new ObjectiveFunction(point -> {
        double score;
        try {
            double sum = 0;
            for (int r = 0; r < repeats; r++) {
                Supplier<X> x = () -> subject(point);
                sum += eval.floatValueOf(x);
            }
            score = sum / repeats;
        } catch (Exception e) {
            logger.error("{} {} {}", this, point, e);
            score = Float.NEGATIVE_INFINITY;
        }
        if (trace)
            csv.out(ArrayUtils.add(point, (int) 0, score));
        maxScore[0] = Math.max(maxScore[0], score);
        // System.out.println(
        // n4(score) + " / " + n4(maxScore[0]) + "\t" + n4(point)
        // );
        experiments.add(pair(score, point));
        experimentIteration(point, score);
        return score;
    });
    if (trace)
        csv = new CSVOutput(System.out, Stream.concat(Stream.of("score"), tweaks.stream().map(t -> t.id)).toArray(String[]::new));
    experimentStart();
    try {
        solve(dim, func, mid, min, max, inc, maxIterations);
    } catch (Throwable t) {
        logger.info("solve {} {}", func, t);
    }
    return new Result<>(experiments, tweaks);
}
Also used : MultiDirectionalSimplex(org.apache.commons.math3.optim.nonlinear.scalar.noderiv.MultiDirectionalSimplex) Logger(org.slf4j.Logger) SortedSet(java.util.SortedSet) DoubleObjectPair(org.eclipse.collections.api.tuple.primitive.DoubleObjectPair) MathArrays(org.apache.commons.math3.util.MathArrays) FasterList(jcog.list.FasterList) LoggerFactory(org.slf4j.LoggerFactory) ArrayUtils(org.apache.commons.lang3.ArrayUtils) ObjectiveFunction(org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction) Supplier(java.util.function.Supplier) SimplexOptimizer(org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer) List(java.util.List) Stream(java.util.stream.Stream) MersenneTwister(org.apache.commons.math3.random.MersenneTwister) GoalType(org.apache.commons.math3.optim.nonlinear.scalar.GoalType) Map(java.util.Map) PrimitiveTuples.pair(org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples.pair) CSVOutput(jcog.meter.event.CSVOutput) InitialGuess(org.apache.commons.math3.optim.InitialGuess) MaxEval(org.apache.commons.math3.optim.MaxEval) Pair(org.eclipse.collections.api.tuple.Pair) FloatFunction(org.eclipse.collections.api.block.function.primitive.FloatFunction) Joiner(com.google.common.base.Joiner) SimpleBounds(org.apache.commons.math3.optim.SimpleBounds) FasterList(jcog.list.FasterList) ObjectiveFunction(org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction) DoubleObjectPair(org.eclipse.collections.api.tuple.primitive.DoubleObjectPair) CSVOutput(jcog.meter.event.CSVOutput)

Example 24 with FasterList

use of jcog.list.FasterList in project narchy by automenta.

the class Tweaks method discover.

/**
 * auto discovers tweaks by reflecting a sample of the subject
 */
public Tweaks<X> discover(Discovery<X> each) {
    // sample instance
    X x = (this.subjects.get());
    ObjectGraph o = new ObjectGraph() {

        @Override
        protected boolean access(Object root, FasterList<Pair<Class, Accessor>> path, Object target) {
            if (this.nodes.containsKey(target))
                // prevent cycle
                return false;
            Class<?> targetType = target.getClass();
            if (!Tweaks.this.includeClass(targetType))
                return false;
            if (tweakable(targetType)) {
                each.discovered((X) root, path.clone(), targetType);
            }
            return !Primitives.unwrap(target.getClass()).isPrimitive();
        }

        @Override
        public boolean recurse(Object x) {
            Class<?> xc = x.getClass();
            return Tweaks.this.includeClass(xc) && !tweakable(xc);
        }

        @Override
        public boolean includeValue(Object v) {
            return Tweaks.this.includeClass(v.getClass());
        }

        @Override
        public boolean includeClass(Class<?> c) {
            return Tweaks.this.includeClass(c);
        }

        @Override
        public boolean includeField(Field f) {
            int m = f.getModifiers();
            if (!Modifier.isPublic(m) || !Tweaks.this.includeField(f))
                return false;
            Class<?> t = Primitives.wrap(f.getType());
            boolean primitive = Primitives.unwrap(f.getType()).isPrimitive();
            if (tweakable(t)) {
                return (!primitive || !Modifier.isFinal(m));
            } else
                // explore further into Object's, final or not
                return !primitive;
        }
    };
    o.add(DEFAULT_DEPTH, x);
    return this;
}
Also used : Field(java.lang.reflect.Field) FasterList(jcog.list.FasterList) ObjectGraph(jcog.data.graph.ObjectGraph)

Example 25 with FasterList

use of jcog.list.FasterList in project narchy by automenta.

the class MyConcurrentRadixTree method removeHavingAcquiredWriteLock.

public boolean removeHavingAcquiredWriteLock(SearchResult searchResult, boolean recurse) {
    SearchResult.Classification classification = searchResult.classification;
    switch(classification) {
        case EXACT_MATCH:
            Node found = searchResult.found;
            Node parent = searchResult.parentNode;
            Object v = found.getValue();
            if (!recurse && ((v == null) || (v == VoidValue.SINGLETON))) {
                // No need to remove it...
                return false;
            }
            List<X> reinsertions = new FasterList<>(0);
            if (v != null && v != VoidValue.SINGLETON) {
                X xv = (X) v;
                boolean removed = tryRemove(xv);
                if (!recurse) {
                    if (!removed)
                        // remove was disabled for this entry
                        return false;
                } else {
                    if (!removed) {
                        // continue removing below then reinsert afterward
                        reinsertions.add(xv);
                    }
                }
            }
            // Proceed with deleting the node...
            FasterList<Node> childEdges = found.getOutgoingEdges();
            int numChildren = childEdges.size();
            if (numChildren > 0) {
                if (!recurse) {
                    if (numChildren > 1) {
                        // This node has more than one child, so if we delete the value from this node, we still need
                        // to leave a similar node in place to act as the split between the child edges.
                        // Just delete the value associated with this node.
                        // -> Clone this node without its value, preserving its child nodes...
                        @SuppressWarnings("NullableProblems") Node cloned = createNode(found.getIncomingEdge(), null, found.getOutgoingEdges(), false);
                        // Re-add the replacement node to the parent...
                        parent.updateOutgoingEdge(cloned);
                    } else if (numChildren == 1) {
                        // Node has one child edge.
                        // Create a new node which is the concatenation of the edges from this node and its child,
                        // and which has the outgoing edges of the child and the value from the child.
                        Node child = childEdges.get(0);
                        AbstractBytes concatenatedEdges = concatenate(found.getIncomingEdge(), child.getIncomingEdge());
                        Node mergedNode = createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false);
                        // Re-add the merged node to the parent...
                        parent.updateOutgoingEdge(mergedNode);
                    }
                } else {
                    // collect all values from the subtree, call onRemove for them. then proceed below with removal of this node and its value
                    forEach(found, (k, f) -> {
                        boolean removed = tryRemove(f);
                        if (!removed) {
                            reinsertions.add(f);
                        }
                    });
                    numChildren = 0;
                }
            }
            if (numChildren == 0) {
                if (reinsertions.size() == 1) {
                    // in this case make no further changes
                    return false;
                }
                // Node has no children. Delete this node from its parent,
                // which involves re-creating the parent rather than simply updating its child edge
                // (this is why we need parentNodesParent).
                // However if this would leave the parent with only one remaining child edge,
                // and the parent itself has no value (is a split node), and the parent is not the root node
                // (a special case which we never merge), then we also need to merge the parent with its
                // remaining child.
                FasterList<Node> currentEdgesFromParent = parent.getOutgoingEdges();
                // Create a list of the outgoing edges of the parent which will remain
                // if we remove this child...
                int cen = currentEdgesFromParent.size();
                FasterList<Node> newEdgesOfParent = new FasterList<>(0, new Node[cen]);
                boolean differs = false;
                for (int i = 0; i < cen; i++) {
                    Node node = currentEdgesFromParent.get(i);
                    if (node != found) {
                        newEdgesOfParent.add(node);
                    } else {
                        differs = true;
                    }
                }
                if (!differs)
                    // re-use original
                    newEdgesOfParent = currentEdgesFromParent;
                // Note the parent might actually be the root node (which we should never merge)...
                boolean parentIsRoot = (parent == root);
                Node newParent;
                if (newEdgesOfParent.size() == 1 && parent.getValue() == null && !parentIsRoot) {
                    // Parent is a non-root split node with only one remaining child, which can now be merged.
                    Node parentsRemainingChild = newEdgesOfParent.get(0);
                    // Merge the parent with its only remaining child...
                    AbstractBytes concatenatedEdges = concatenate(parent.getIncomingEdge(), parentsRemainingChild.getIncomingEdge());
                    newParent = createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot);
                } else {
                    // Parent is a node which either has a value of its own, has more than one remaining
                    // child, or is actually the root node (we never merge the root node).
                    // Create new parent node which is the same as is currently just without the edge to the
                    // node being deleted...
                    newParent = createNode(parent.getIncomingEdge(), parent.getValue(), newEdgesOfParent, parentIsRoot);
                }
                // Re-add the parent node to its parent...
                if (parentIsRoot) {
                    // Replace the root node...
                    this.root = newParent;
                } else {
                    // Re-add the parent node to its parent...
                    searchResult.parentNodesParent.updateOutgoingEdge(newParent);
                }
            }
            reinsertions.forEach(this::put);
            return true;
        default:
            return false;
    }
}
Also used : AbstractBytes(jcog.data.byt.AbstractBytes) FasterList(jcog.list.FasterList)

Aggregations

FasterList (jcog.list.FasterList)48 Term (nars.term.Term)17 List (java.util.List)7 Truth (nars.truth.Truth)5 Pair (org.eclipse.collections.api.tuple.Pair)5 Nullable (org.jetbrains.annotations.Nullable)5 Map (java.util.Map)4 Predicate (java.util.function.Predicate)4 NAR (nars.NAR)4 Task (nars.Task)4 LongObjectPair (org.eclipse.collections.api.tuple.primitive.LongObjectPair)4 java.util (java.util)3 Supplier (java.util.function.Supplier)3 Util (jcog.Util)3 MapNodeGraph (jcog.data.graph.MapNodeGraph)3 NALTask (nars.task.NALTask)3 Bool (nars.term.atom.Bool)3 Test (org.junit.jupiter.api.Test)3 RoaringBitmap (org.roaringbitmap.RoaringBitmap)3 MultimapBuilder (com.google.common.collect.MultimapBuilder)2