Search in sources :

Example 1 with Conjunction

use of com.yahoo.document.predicate.Conjunction in project vespa by vespa-engine.

the class FeatureConjunctionTransformer method convertConjunction.

/**
 * Conversion rules:
 *  1) A {@link FeatureConjunction} may only consist of FeatureSets having unique keys.
 *     If multiple {@link FeatureSet} share the same key, they have to be placed into separate FeatureConjunctions.
 *  2) A FeatureConjunction must have at least 2 operands.
 *  3) Any operand that is not a FeatureSet, negated or not,
 *     (e.g {@link FeatureRange}) cannot be placed into a FeatureConjunction.
 *  4) All FeatureSets may only have a single value.
 *
 *  See the tests in FeatureConjunctionTransformerTest for conversion examples.
 */
private static Predicate convertConjunction(Conjunction conjunction, long nValidOperands) {
    List<Predicate> operands = conjunction.getOperands();
    // All operands are instance of FeatureSet are valid and may therefor be placed into a single FeatureConjunction.
    if (nValidOperands == operands.size()) {
        return new FeatureConjunction(operands);
    }
    List<Predicate> invalidFeatureConjunctionOperands = new ArrayList<>();
    List<Map<String, Predicate>> featureConjunctionOperandsList = new ArrayList<>();
    featureConjunctionOperandsList.add(new TreeMap<>());
    for (Predicate operand : operands) {
        if (FeatureConjunction.isValidFeatureConjunctionOperand(operand)) {
            addFeatureConjunctionOperand(featureConjunctionOperandsList, operand);
        } else {
            invalidFeatureConjunctionOperands.add(operand);
        }
    }
    // Create a Conjunction root.
    Conjunction newConjunction = new Conjunction();
    newConjunction.addOperands(invalidFeatureConjunctionOperands);
    // For all operand partitions: create FeatureConjunction if partition has more than a single predicate.
    for (Map<String, Predicate> featureConjunctionOperands : featureConjunctionOperandsList) {
        Collection<Predicate> values = featureConjunctionOperands.values();
        if (featureConjunctionOperands.size() == 1) {
            // Add single operand directly to root conjunction.
            newConjunction.addOperands(values);
        } else {
            newConjunction.addOperand(new FeatureConjunction(new ArrayList<>(values)));
        }
    }
    return newConjunction;
}
Also used : FeatureConjunction(com.yahoo.document.predicate.FeatureConjunction) ArrayList(java.util.ArrayList) FeatureConjunction(com.yahoo.document.predicate.FeatureConjunction) Conjunction(com.yahoo.document.predicate.Conjunction) TreeMap(java.util.TreeMap) Map(java.util.Map) Predicate(com.yahoo.document.predicate.Predicate)

Example 2 with Conjunction

use of com.yahoo.document.predicate.Conjunction in project vespa by vespa-engine.

the class PredicateTreeAnnotator method assignIntervalLabels.

/**
 * Visits the predicate tree in depth-first order and assigns intervals for features in
 * {@link com.yahoo.document.predicate.FeatureSet} and {@link com.yahoo.document.predicate.FeatureRange}.
 */
private static void assignIntervalLabels(Predicate predicate, int begin, int end, boolean isNegated, AnnotatorContext context) {
    // Otherwise, conjunctions and disjunctions must be switched if negated (De Morgan's law).
    if (predicate instanceof Conjunction) {
        List<Predicate> children = ((Conjunction) predicate).getOperands();
        int current = begin;
        for (int i = 0; i < children.size(); i++) {
            Predicate child = children.get(i);
            int subTreeSize = context.subTreeSizes.get(child);
            if (i == children.size() - 1) {
                // Last child (and sometimes the only one)
                assignIntervalLabels(child, current, end, isNegated, context);
            // No need to update/touch current since this is the last child.
            } else if (i == 0) {
                // First child
                int next = context.leftNodeLeaves + subTreeSize + 1;
                assignIntervalLabels(child, current, next - 1, isNegated, context);
                current = next;
            } else {
                // Middle children
                int next = current + subTreeSize;
                assignIntervalLabels(child, current, next - 1, isNegated, context);
                current = next;
            }
        }
    } else if (predicate instanceof FeatureConjunction) {
        // Register FeatureConjunction as it was a FeatureSet with a single child.
        // Note: FeatureConjunction should never be negated as AndOrSimplifier will push negations down to
        // the leafs (FeatureSets).
        int zStarEnd = isNegated ? calculateZStarIntervalEnd(end, context) : end;
        IndexableFeatureConjunction indexable = new IndexableFeatureConjunction((FeatureConjunction) predicate);
        int interval = Interval.fromBoundaries(begin, zStarEnd);
        context.featureConjunctions.computeIfAbsent(indexable, (k) -> new ArrayList<>()).add(interval);
        if (isNegated) {
            registerZStarInterval(begin, end, zStarEnd, context);
        }
        context.leftNodeLeaves += 1;
    } else if (predicate instanceof Disjunction) {
        // the values will be same as that of the parent OR node
        for (Predicate child : ((Disjunction) predicate).getOperands()) {
            assignIntervalLabels(child, begin, end, isNegated, context);
        }
    } else if (predicate instanceof FeatureSet) {
        FeatureSet featureSet = (FeatureSet) predicate;
        int zStarEnd = isNegated ? calculateZStarIntervalEnd(end, context) : end;
        for (String value : featureSet.getValues()) {
            long featureHash = Feature.createHash(featureSet.getKey(), value);
            int interval = Interval.fromBoundaries(begin, zStarEnd);
            registerFeatureInterval(featureHash, interval, context.intervals);
        }
        if (isNegated) {
            registerZStarInterval(begin, end, zStarEnd, context);
        }
        context.leftNodeLeaves += 1;
    } else if (predicate instanceof Negation) {
        assignIntervalLabels(((Negation) predicate).getOperand(), begin, end, !isNegated, context);
    } else if (predicate instanceof FeatureRange) {
        FeatureRange featureRange = (FeatureRange) predicate;
        int zStarEnd = isNegated ? calculateZStarIntervalEnd(end, context) : end;
        int interval = Interval.fromBoundaries(begin, zStarEnd);
        for (RangePartition partition : featureRange.getPartitions()) {
            long featureHash = PredicateHash.hash64(partition.getLabel());
            registerFeatureInterval(featureHash, interval, context.intervals);
        }
        for (RangeEdgePartition edgePartition : featureRange.getEdgePartitions()) {
            long featureHash = PredicateHash.hash64(edgePartition.getLabel());
            IntervalWithBounds intervalWithBounds = new IntervalWithBounds(interval, (int) edgePartition.encodeBounds());
            registerFeatureInterval(featureHash, intervalWithBounds, context.intervalsWithBounds);
        }
        if (isNegated) {
            registerZStarInterval(begin, end, zStarEnd, context);
        }
        context.leftNodeLeaves += 1;
    } else {
        throw new UnsupportedOperationException("Cannot handle predicate of type " + predicate.getClass().getSimpleName());
    }
}
Also used : RangePartition(com.yahoo.document.predicate.RangePartition) IndexableFeatureConjunction(com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction) Negation(com.yahoo.document.predicate.Negation) Predicate(com.yahoo.document.predicate.Predicate) Disjunction(com.yahoo.document.predicate.Disjunction) FeatureConjunction(com.yahoo.document.predicate.FeatureConjunction) IndexableFeatureConjunction(com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction) FeatureConjunction(com.yahoo.document.predicate.FeatureConjunction) IndexableFeatureConjunction(com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction) Conjunction(com.yahoo.document.predicate.Conjunction) FeatureRange(com.yahoo.document.predicate.FeatureRange) FeatureSet(com.yahoo.document.predicate.FeatureSet) RangeEdgePartition(com.yahoo.document.predicate.RangeEdgePartition) IntervalWithBounds(com.yahoo.search.predicate.index.IntervalWithBounds)

Example 3 with Conjunction

use of com.yahoo.document.predicate.Conjunction in project vespa by vespa-engine.

the class PredicateTreeAnalyzer method aggregatePredicateStatistics.

// First analysis pass. Traverses tree in depth-first order. Determines the sub-tree sizes and counts the occurrences
// of each feature (used by min-feature calculation in second pass).
// Returns the size of the analyzed subtree.
private static int aggregatePredicateStatistics(Predicate predicate, boolean isNegated, AnalyzerContext context) {
    if (predicate instanceof Negation) {
        return aggregatePredicateStatistics(((Negation) predicate).getOperand(), !isNegated, context);
    } else if (predicate instanceof Conjunction) {
        return ((Conjunction) predicate).getOperands().stream().mapToInt(child -> {
            int size = aggregatePredicateStatistics(child, isNegated, context);
            context.subTreeSizes.put(child, size);
            return size;
        }).sum();
    } else if (predicate instanceof FeatureConjunction) {
        if (isNegated) {
            context.hasNegationPredicate = true;
            return 2;
        }
        // Count the number of identical feature conjunctions - use the id from IndexableFeatureConjunction as key
        IndexableFeatureConjunction ifc = new IndexableFeatureConjunction((FeatureConjunction) predicate);
        incrementOccurrence(context.conjunctionOccurrences, ifc.id);
        // Handled as leaf in interval algorithm - count a single child
        return 1;
    } else if (predicate instanceof Disjunction) {
        return ((Disjunction) predicate).getOperands().stream().mapToInt(child -> aggregatePredicateStatistics(child, isNegated, context)).sum();
    } else if (predicate instanceof FeatureSet) {
        if (isNegated) {
            context.hasNegationPredicate = true;
            return 2;
        } else {
            FeatureSet featureSet = (FeatureSet) predicate;
            for (String value : featureSet.getValues()) {
                incrementOccurrence(context.featureOccurrences, Feature.createHash(featureSet.getKey(), value));
            }
            return 1;
        }
    } else if (predicate instanceof FeatureRange) {
        if (isNegated) {
            context.hasNegationPredicate = true;
            return 2;
        } else {
            incrementOccurrence(context.featureOccurrences, PredicateHash.hash64(((FeatureRange) predicate).getKey()));
            return 1;
        }
    } else {
        throw new UnsupportedOperationException("Cannot handle predicate of type " + predicate.getClass().getSimpleName());
    }
}
Also used : Disjunction(com.yahoo.document.predicate.Disjunction) Negation(com.yahoo.document.predicate.Negation) FeatureConjunction(com.yahoo.document.predicate.FeatureConjunction) IndexableFeatureConjunction(com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction) IndexableFeatureConjunction(com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction) FeatureConjunction(com.yahoo.document.predicate.FeatureConjunction) IndexableFeatureConjunction(com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction) Conjunction(com.yahoo.document.predicate.Conjunction) FeatureRange(com.yahoo.document.predicate.FeatureRange) FeatureSet(com.yahoo.document.predicate.FeatureSet)

Example 4 with Conjunction

use of com.yahoo.document.predicate.Conjunction in project vespa by vespa-engine.

the class AndOrSimplifier method simplifySubTree.

public Predicate simplifySubTree(Predicate predicate, boolean negated) {
    if (predicate == null) {
        return null;
    }
    if (predicate instanceof Negation) {
        return simplifySubTree(((Negation) predicate).getOperand(), !negated);
    } else if (predicate instanceof Conjunction) {
        List<Predicate> in = ((Conjunction) predicate).getOperands();
        List<Predicate> out = new ArrayList<>(in.size());
        for (Predicate operand : in) {
            operand = simplifySubTree(operand, negated);
            if (operand instanceof Conjunction) {
                out.addAll(((Conjunction) operand).getOperands());
            } else {
                out.add(operand);
            }
        }
        if (negated) {
            return new Disjunction(out);
        }
        ((Conjunction) predicate).setOperands(out);
    } else if (predicate instanceof Disjunction) {
        List<Predicate> in = ((Disjunction) predicate).getOperands();
        List<Predicate> out = new ArrayList<>(in.size());
        for (Predicate operand : in) {
            operand = simplifySubTree(operand, negated);
            if (operand instanceof Disjunction) {
                out.addAll(((Disjunction) operand).getOperands());
            } else {
                out.add(operand);
            }
        }
        if (negated) {
            return new Conjunction(out);
        }
        ((Disjunction) predicate).setOperands(out);
    } else {
        if (negated) {
            return new Negation(predicate);
        }
    }
    return predicate;
}
Also used : Disjunction(com.yahoo.document.predicate.Disjunction) Negation(com.yahoo.document.predicate.Negation) Conjunction(com.yahoo.document.predicate.Conjunction) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) Predicate(com.yahoo.document.predicate.Predicate)

Example 5 with Conjunction

use of com.yahoo.document.predicate.Conjunction in project vespa by vespa-engine.

the class NotNodeReorderer method processSubTree.

/**
 * @return true if the predicate ends in a negation.
 */
public boolean processSubTree(Predicate predicate) {
    if (predicate == null) {
        return false;
    }
    if (predicate instanceof Negation) {
        // All negations are for leaf-nodes after AndOrSimplifier has run.
        return true;
    } else if (predicate instanceof Conjunction) {
        List<Predicate> in = ((Conjunction) predicate).getOperands();
        List<Predicate> out = new ArrayList<>(in.size());
        List<Predicate> positiveChildren = new ArrayList<>(in.size());
        for (Predicate operand : in) {
            if (processSubTree(operand)) {
                out.add(operand);
            } else {
                positiveChildren.add(operand);
            }
        }
        out.addAll(positiveChildren);
        ((Conjunction) predicate).setOperands(out);
        return positiveChildren.isEmpty();
    } else if (predicate instanceof Disjunction) {
        List<Predicate> in = ((Disjunction) predicate).getOperands();
        List<Predicate> out = new ArrayList<>(in.size());
        List<Predicate> negativeChildren = new ArrayList<>(in.size());
        for (Predicate operand : in) {
            if (processSubTree(operand)) {
                negativeChildren.add(operand);
            } else {
                out.add(operand);
            }
        }
        out.addAll(negativeChildren);
        ((Disjunction) predicate).setOperands(out);
        return !negativeChildren.isEmpty();
    }
    return false;
}
Also used : Disjunction(com.yahoo.document.predicate.Disjunction) Negation(com.yahoo.document.predicate.Negation) Conjunction(com.yahoo.document.predicate.Conjunction) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) Predicate(com.yahoo.document.predicate.Predicate)

Aggregations

Conjunction (com.yahoo.document.predicate.Conjunction)11 Disjunction (com.yahoo.document.predicate.Disjunction)9 Negation (com.yahoo.document.predicate.Negation)9 Predicate (com.yahoo.document.predicate.Predicate)7 FeatureConjunction (com.yahoo.document.predicate.FeatureConjunction)5 FeatureRange (com.yahoo.document.predicate.FeatureRange)5 FeatureSet (com.yahoo.document.predicate.FeatureSet)5 ArrayList (java.util.ArrayList)4 IndexableFeatureConjunction (com.yahoo.search.predicate.index.conjunction.IndexableFeatureConjunction)3 List (java.util.List)3 BooleanPredicate (com.yahoo.document.predicate.BooleanPredicate)2 Map (java.util.Map)2 Test (org.junit.Test)2 Document (com.yahoo.document.Document)1 PredicateFieldValue (com.yahoo.document.datatypes.PredicateFieldValue)1 PredicateHash (com.yahoo.document.predicate.PredicateHash)1 PredicateOperator (com.yahoo.document.predicate.PredicateOperator)1 RangeEdgePartition (com.yahoo.document.predicate.RangeEdgePartition)1 RangePartition (com.yahoo.document.predicate.RangePartition)1 SerializationTestUtils.deserializeDocument (com.yahoo.document.serialization.SerializationTestUtils.deserializeDocument)1