Search in sources :

Example 31 with FunctionType

use of com.sri.ai.expresso.type.FunctionType in project aic-expresso by aic-sri-international.

the class GrinderUtil method getTypeExpression.

/**
	 * Returns the type of given expression according to registry.
	 */
public static Expression getTypeExpression(Expression expression, Registry registry) {
    Expression result;
    if (FormulaUtil.isApplicationOfBooleanConnective(expression)) {
        result = makeSymbol("Boolean");
    } else if (expression.getSyntacticFormType().equals(FunctionApplication.SYNTACTIC_FORM_TYPE) && list(SUM, PRODUCT, MAX).contains(expression.getFunctor().toString())) {
        Expression argument = expression.get(0);
        if (argument.getSyntacticFormType().equals(IntensionalSet.SYNTACTIC_FORM_TYPE)) {
            IntensionalSet intensionalSetArgument = (IntensionalSet) argument;
            Expression head = intensionalSetArgument.getHead();
            // NOTE: Need to extend the registry as the index expressions in the quantifier may
            // declare new types (i.e. function types).
            Registry headRegistry = registry.extendWith(intensionalSetArgument.getIndexExpressions());
            result = getTypeExpression(head, headRegistry);
        } else if (argument.getSyntacticFormType().equals(ExtensionalSets.SYNTACTIC_FORM_TYPE)) {
            List<Expression> arguments = ((AbstractExtensionalSet) argument).getElementsDefinitions();
            result = getTypeOfCollectionOfNumericExpressionsWithDefaultInteger(arguments, registry);
        } else if (expression.hasFunctor(MAX)) {
            // MAX can also be applied to a bunch of numbers
            result = getTypeOfCollectionOfNumericExpressionsWithDefaultInteger(expression.getArguments(), registry);
        } else {
            throw new Error(expression.getFunctor() + " defined for sets only but got " + expression.get(0));
        }
    } else if (Equality.isEquality(expression) || Disequality.isDisequality(expression)) {
        result = makeSymbol("Boolean");
    } else if (expression.equals(FunctorConstants.REAL_INTERVAL_CLOSED_CLOSED) || expression.equals(FunctorConstants.REAL_INTERVAL_CLOSED_OPEN) || expression.equals(FunctorConstants.REAL_INTERVAL_OPEN_CLOSED) || expression.equals(FunctorConstants.REAL_INTERVAL_OPEN_OPEN)) {
        result = FunctionType.make(parse("Set"), parse("Number"), parse("Number"));
    } else if (IfThenElse.isIfThenElse(expression)) {
        Expression thenType = getTypeExpression(IfThenElse.thenBranch(expression), registry);
        Expression elseType = getTypeExpression(IfThenElse.elseBranch(expression), registry);
        if (thenType != null && elseType != null && (thenType.equals("Number") && isIntegerOrReal(elseType) || isIntegerOrReal(thenType) && elseType.equals("Number"))) {
            result = makeSymbol("Number");
        } else if (thenType != null && elseType != null && (thenType.equals("Integer") && elseType.equals("Real") || thenType.equals("Real") && elseType.equals("Integer"))) {
            result = makeSymbol("Real");
        } else if (thenType != null && (elseType == null || thenType.equals(elseType))) {
            result = thenType;
        } else if (elseType != null && (thenType == null || elseType.equals(thenType))) {
            result = elseType;
        } else if (thenType == null) {
            throw new Error("Could not determine the types of then and else branches of '" + expression + "'.");
        } else if (thenType.equals("Integer") && elseType.hasFunctor(INTEGER_INTERVAL)) {
            // TODO: I know, I know, this treatment of integers and interval is terrible... will fix at some point
            result = thenType;
        } else if (thenType.hasFunctor(INTEGER_INTERVAL) && elseType.equals("Integer")) {
            result = elseType;
        } else if (thenType.hasFunctor(INTEGER_INTERVAL) && elseType.hasFunctor(INTEGER_INTERVAL)) {
            IntegerInterval thenInterval = (IntegerInterval) thenType;
            IntegerInterval elseInterval = (IntegerInterval) elseType;
            Expression minimumLowerBound = LessThan.simplify(apply(LESS_THAN, thenInterval.getNonStrictLowerBound(), elseInterval.getNonStrictLowerBound()), registry).booleanValue() ? thenInterval.getNonStrictLowerBound() : elseInterval.getNonStrictLowerBound();
            Expression maximumUpperBound = GreaterThan.simplify(apply(GREATER_THAN, thenInterval.getNonStrictUpperBound(), elseInterval.getNonStrictUpperBound()), registry).booleanValue() ? thenInterval.getNonStrictUpperBound() : elseInterval.getNonStrictUpperBound();
            if (minimumLowerBound.equals(MINUS_INFINITY) && maximumUpperBound.equals(INFINITY)) {
                result = makeSymbol("Integer");
            } else {
                result = apply(INTEGER_INTERVAL, minimumLowerBound, maximumUpperBound);
            }
        } else {
            throw new Error("'" + expression + "' then and else branches have different types (" + thenType + " and " + elseType + " respectively).");
        }
    } else if (isCardinalityExpression(expression)) {
        result = makeSymbol("Integer");
    } else if (isNumericFunctionApplication(expression)) {
        List<Expression> argumentTypes = mapIntoList(expression.getArguments(), e -> getTypeExpression(e, registry));
        int firstNullArgumentTypeIndexIfAny = Util.getIndexOfFirstSatisfyingPredicateOrMinusOne(argumentTypes, t -> t == null);
        if (firstNullArgumentTypeIndexIfAny != -1) {
            throw new Error("Cannot determine type of " + expression.getArguments().get(firstNullArgumentTypeIndexIfAny) + ", which is needed for determining type of " + expression);
        }
        /**
			 * commonDomain is the co-domain shared by all argument function types, or empty tuple for arguments that are not function-typed.
			 * Therefore, if no argument is function-typed, it will be equal to the empty tuple.
			 */
        Expression commonDomain = getCommonDomainIncludingConversionOfNonFunctionTypesToNullaryFunctions(argumentTypes, registry);
        if (commonDomain == null) {
            throw new Error("Operator " + expression.getFunctor() + " applied to arguments of non-compatible types: " + expression + ", types of arguments are " + argumentTypes);
        }
        boolean noArgumentIsFunctionTyped = commonDomain.equals(EMPTY_TUPLE) && !thereExists(argumentTypes, t -> t.hasFunctor(FunctorConstants.FUNCTION_TYPE));
        Expression resultCoDomain;
        if (thereExists(argumentTypes, t -> Util.equals(getCoDomainOrItself(t), "Number"))) {
            resultCoDomain = makeSymbol("Number");
        } else if (thereExists(argumentTypes, t -> Util.equals(getCoDomainOrItself(t), "Real"))) {
            resultCoDomain = makeSymbol("Real");
        } else if (thereExists(argumentTypes, t -> isRealInterval(getCoDomainOrItself(t)))) {
            resultCoDomain = makeSymbol("Real");
        } else {
            resultCoDomain = makeSymbol("Integer");
        }
        if (noArgumentIsFunctionTyped) {
            result = resultCoDomain;
        } else {
            result = apply(FUNCTION_TYPE, commonDomain, resultCoDomain);
        }
    } else if (expression.hasFunctor(FunctorConstants.INTEGER_INTERVAL) || expression.hasFunctor(FunctorConstants.REAL_INTERVAL_CLOSED_CLOSED) || expression.hasFunctor(FunctorConstants.REAL_INTERVAL_OPEN_CLOSED) || expression.hasFunctor(FunctorConstants.REAL_INTERVAL_CLOSED_OPEN) || expression.hasFunctor(FunctorConstants.REAL_INTERVAL_OPEN_OPEN)) {
        result = makeSymbol("Set");
    } else if (isComparisonFunctionApplication(expression)) {
        result = makeSymbol("Boolean");
    } else if (expression.hasFunctor(FunctorConstants.FUNCTION_TYPE)) {
        // very vague type for now
        result = apply(FUNCTION_TYPE, makeSymbol("Set"), makeSymbol("Set"));
    } else if (Sets.isIntensionalMultiSet(expression)) {
        IntensionalSet set = (IntensionalSet) expression;
        // NOTE: Need to extend the registry as the index expressions in the quantifier may
        // declare new types (i.e. function types).
        Registry headRegistry = registry.extendWith(set.getIndexExpressions());
        Expression headType = getTypeExpression(set.getHead(), headRegistry);
        result = new DefaultIntensionalMultiSet(list(), headType, TRUE);
    } else if (Sets.isExtensionalSet(expression)) {
        // very vague type for now
        result = apply(FUNCTION_TYPE, makeSymbol("Set"));
    } else if (expression.hasFunctor(FunctorConstants.INTERSECTION) || expression.hasFunctor(FunctorConstants.UNION) || expression.hasFunctor(FunctorConstants.INTENSIONAL_UNION)) {
        // very vague type for now
        result = apply(FUNCTION_TYPE, makeSymbol("Set"));
    } else if (expression.getSyntacticFormType().equals(Symbol.SYNTACTIC_FORM_TYPE)) {
        if (expression.getValue() instanceof Integer) {
            result = makeSymbol("Integer");
        } else if (expression.getValue() instanceof Double) {
            result = makeSymbol("Real");
        } else if (expression.getValue() instanceof Rational) {
            Rational rational = (Rational) expression.getValue();
            boolean isInteger = rational.isInteger();
            result = makeSymbol(isInteger ? "Integer" : "Real");
        } else if (expression.getValue() instanceof Number) {
            result = makeSymbol("Number");
        } else if (expression.getValue() instanceof String && expression.isStringLiteral()) {
            result = makeSymbol("String");
        } else if (expression.getValue() instanceof Boolean) {
            result = makeSymbol("Boolean");
        } else if (expression.equals(Expressions.INFINITY) || expression.equals(Expressions.MINUS_INFINITY)) {
            result = makeSymbol("Number");
        } else {
            result = registry.getTypeOfRegisteredSymbol(expression);
            if (result == null) {
                Type type = getFirstSatisfyingPredicateOrNull(registry.getTypes(), t -> t.contains(expression));
                if (type != null) {
                    result = parse(type.getName());
                }
            }
        }
    } else if (expression.hasFunctor(FunctorConstants.GET) && expression.numberOfArguments() == 2 && Expressions.isNumber(expression.get(1))) {
        Expression argType = getTypeExpression(expression.get(0), registry);
        if (TupleType.isTupleType(argType)) {
            TupleType tupleType = (TupleType) GrinderUtil.fromTypeExpressionToItsIntrinsicMeaning(argType, registry);
            result = parse(tupleType.getElementTypes().get(expression.get(1).intValue() - 1).toString());
        } else {
            throw new Error("get type from tuple for '" + expression + "' currently not supported.");
        }
    } else if (expression.hasFunctor(FunctorConstants.TUPLE_TYPE)) {
        // Is a type expression already.
        result = expression;
    } else if (expression.getSyntacticFormType().equals(FunctionApplication.SYNTACTIC_FORM_TYPE)) {
        Expression functionType = getTypeExpression(expression.getFunctor(), registry);
        if (functionType == null) {
            throw new Error("Type of '" + expression.getFunctor() + "' required, but unknown to registry.");
        }
        Expression coDomain = FunctionType.getCodomain(functionType);
        List<Expression> argumentsTypesList = FunctionType.getArgumentList(functionType);
        if (expression.getArguments().size() != argumentsTypesList.size()) {
            throw new Error("Function " + expression.getFunctor() + " is of type " + functionType + " but has incorrect number of arguments = " + expression.getArguments());
        }
        for (int idx = 0; idx < expression.getArguments().size(); idx++) {
            Expression arg = expression.get(idx);
            Expression argExprType = argumentsTypesList.get(idx);
            Type argType = registry.getType(argExprType);
            if (!isSubtypeOf(arg, argType, registry)) {
                throw new Error("Function " + expression.getFunctor() + " is of type " + functionType + " but has arguments that are not legal subtypes [#" + idx + "] = " + expression.getArguments());
            }
        }
        result = coDomain;
    } else if (Tuple.isTuple(expression)) {
        List<Expression> elementTypes = expression.getArguments().stream().map(element -> getTypeExpression(element, registry)).collect(Collectors.toList());
        result = TupleType.make(elementTypes);
    } else if (expression instanceof QuantifiedExpressionWithABody) {
        QuantifiedExpressionWithABody quantifiedExpressionWithABody = (QuantifiedExpressionWithABody) expression;
        // NOTE: Need to extend the registry as the index expressions in the quantifier may
        // declare new types (i.e. function types).
        Registry quantifiedExpressionWithABodyRegistry = registry.extendWith(quantifiedExpressionWithABody.getIndexExpressions());
        result = getTypeExpression(quantifiedExpressionWithABody.getBody(), quantifiedExpressionWithABodyRegistry);
    } else if (expression instanceof LambdaExpression) {
        LambdaExpression lambdaExpression = (LambdaExpression) expression;
        Collection<Expression> domain = IndexExpressions.getIndexDomainsOfQuantifiedExpression(lambdaExpression);
        IndexExpressionsSet indexExpressions = lambdaExpression.getIndexExpressions();
        Registry lambdaExpressionWithABodyRegistry = registry.extendWith(indexExpressions);
        Expression coDomain = getTypeExpression(lambdaExpression.getBody(), lambdaExpressionWithABodyRegistry);
        result = Expressions.apply(FUNCTION_TYPE, domain, coDomain);
    } else if (expression instanceof AbstractExpressionWrapper) {
        Expression innerExpression = ((AbstractExpressionWrapper) expression).getInnerExpression();
        result = getTypeExpression(innerExpression, registry);
    } else {
        throw new Error("GrinderUtil.getType does not yet know how to determine the type of this sort of expression: " + expression);
    }
    return result;
}
Also used : SUM(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.SUM) CountingFormula(com.sri.ai.expresso.api.CountingFormula) LESS_THAN_OR_EQUAL_TO(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.LESS_THAN_OR_EQUAL_TO) FALSE(com.sri.ai.expresso.helper.Expressions.FALSE) Expressions(com.sri.ai.expresso.helper.Expressions) Rational(com.sri.ai.util.math.Rational) Expression(com.sri.ai.expresso.api.Expression) Util.getFirstSatisfyingPredicateOrNull(com.sri.ai.util.Util.getFirstSatisfyingPredicateOrNull) GreaterThan(com.sri.ai.grinder.sgdpllt.library.number.GreaterThan) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) Symbol(com.sri.ai.expresso.api.Symbol) Map(java.util.Map) Util.thereExists(com.sri.ai.util.Util.thereExists) Sets(com.sri.ai.grinder.sgdpllt.library.set.Sets) Function(com.google.common.base.Function) DefaultIntensionalMultiSet(com.sri.ai.expresso.core.DefaultIntensionalMultiSet) AbstractExtensionalSet(com.sri.ai.expresso.core.AbstractExtensionalSet) Collection(java.util.Collection) Util.list(com.sri.ai.util.Util.list) RealInterval(com.sri.ai.expresso.type.RealInterval) Set(java.util.Set) Util.mapIntoList(com.sri.ai.util.Util.mapIntoList) IntensionalSet(com.sri.ai.expresso.api.IntensionalSet) GREATER_THAN_OR_EQUAL_TO(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.GREATER_THAN_OR_EQUAL_TO) Collectors(java.util.stream.Collectors) IfThenElse(com.sri.ai.grinder.sgdpllt.library.controlflow.IfThenElse) QuantifiedExpressionWithABody(com.sri.ai.expresso.api.QuantifiedExpressionWithABody) IntegerExpressoType(com.sri.ai.expresso.type.IntegerExpressoType) Util.getFirstOrNull(com.sri.ai.util.Util.getFirstOrNull) List(java.util.List) IndexExpressions(com.sri.ai.grinder.sgdpllt.library.indexexpression.IndexExpressions) Predicate(com.google.common.base.Predicate) CARDINALITY(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.CARDINALITY) FUNCTION_TYPE(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.FUNCTION_TYPE) TIMES(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.TIMES) TRUE(com.sri.ai.expresso.helper.Expressions.TRUE) FunctorConstants(com.sri.ai.grinder.sgdpllt.library.FunctorConstants) GREATER_THAN(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.GREATER_THAN) IntStream(java.util.stream.IntStream) Tuple(com.sri.ai.expresso.api.Tuple) Categorical(com.sri.ai.expresso.type.Categorical) INFINITY(com.sri.ai.expresso.helper.Expressions.INFINITY) Util.mapIntoArrayList(com.sri.ai.util.Util.mapIntoArrayList) IntegerInterval(com.sri.ai.expresso.type.IntegerInterval) Disequality(com.sri.ai.grinder.sgdpllt.library.Disequality) ArrayList(java.util.ArrayList) TupleType(com.sri.ai.expresso.type.TupleType) Expressions.apply(com.sri.ai.expresso.helper.Expressions.apply) FormulaUtil(com.sri.ai.grinder.sgdpllt.library.FormulaUtil) Expressions.parse(com.sri.ai.expresso.helper.Expressions.parse) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet) Registry(com.sri.ai.grinder.api.Registry) PLUS(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.PLUS) LessThan(com.sri.ai.grinder.sgdpllt.library.number.LessThan) DIVISION(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.DIVISION) INTEGER_INTERVAL(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.INTEGER_INTERVAL) LinkedList(java.util.LinkedList) Util.arrayList(com.sri.ai.util.Util.arrayList) Equality(com.sri.ai.grinder.sgdpllt.library.Equality) Util.ifAllTheSameOrNull(com.sri.ai.util.Util.ifAllTheSameOrNull) LambdaExpression(com.sri.ai.expresso.api.LambdaExpression) Type(com.sri.ai.expresso.api.Type) MAX(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.MAX) RealExpressoType(com.sri.ai.expresso.type.RealExpressoType) MINUS_INFINITY(com.sri.ai.expresso.helper.Expressions.MINUS_INFINITY) ExtensionalSets(com.sri.ai.grinder.sgdpllt.library.set.extensional.ExtensionalSets) PRODUCT(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.PRODUCT) DefaultUniversallyQuantifiedFormula(com.sri.ai.expresso.core.DefaultUniversallyQuantifiedFormula) Context(com.sri.ai.grinder.sgdpllt.api.Context) Integer.parseInt(java.lang.Integer.parseInt) Beta(com.google.common.annotations.Beta) AbstractExpressionWrapper(com.sri.ai.expresso.helper.AbstractExpressionWrapper) FunctionType(com.sri.ai.expresso.type.FunctionType) FunctionApplication(com.sri.ai.expresso.api.FunctionApplication) Expressions.makeSymbol(com.sri.ai.expresso.helper.Expressions.makeSymbol) FunctionIterator.functionIterator(com.sri.ai.util.collect.FunctionIterator.functionIterator) LESS_THAN(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.LESS_THAN) EXPONENTIATION(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.EXPONENTIATION) MINUS(com.sri.ai.grinder.sgdpllt.library.FunctorConstants.MINUS) EMPTY_TUPLE(com.sri.ai.expresso.api.Tuple.EMPTY_TUPLE) Util(com.sri.ai.util.Util) AbstractExtensionalSet(com.sri.ai.expresso.core.AbstractExtensionalSet) Rational(com.sri.ai.util.math.Rational) DefaultIntensionalMultiSet(com.sri.ai.expresso.core.DefaultIntensionalMultiSet) IntensionalSet(com.sri.ai.expresso.api.IntensionalSet) AbstractExpressionWrapper(com.sri.ai.expresso.helper.AbstractExpressionWrapper) TupleType(com.sri.ai.expresso.type.TupleType) Util.mapIntoList(com.sri.ai.util.Util.mapIntoList) List(java.util.List) Util.mapIntoArrayList(com.sri.ai.util.Util.mapIntoArrayList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Util.arrayList(com.sri.ai.util.Util.arrayList) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet) IntegerInterval(com.sri.ai.expresso.type.IntegerInterval) Registry(com.sri.ai.grinder.api.Registry) IntegerExpressoType(com.sri.ai.expresso.type.IntegerExpressoType) TupleType(com.sri.ai.expresso.type.TupleType) Type(com.sri.ai.expresso.api.Type) RealExpressoType(com.sri.ai.expresso.type.RealExpressoType) FunctionType(com.sri.ai.expresso.type.FunctionType) QuantifiedExpressionWithABody(com.sri.ai.expresso.api.QuantifiedExpressionWithABody) Expression(com.sri.ai.expresso.api.Expression) LambdaExpression(com.sri.ai.expresso.api.LambdaExpression) Collection(java.util.Collection) LambdaExpression(com.sri.ai.expresso.api.LambdaExpression)

Example 32 with FunctionType

use of com.sri.ai.expresso.type.FunctionType in project aic-expresso by aic-sri-international.

the class InversionSimplifier method applyInversion.

private static Expression applyInversion(Expression summationIndexedByFunction, Expression summationIndexFunctionName, FunctionType summationIndexFunctionType, List<Expression> originalQuantifierOrder, List<Expression> inversionQuantifierOrder, Context context) {
    Expression result;
    int indexOfSummationIndexedByFunction = inversionQuantifierOrder.indexOf(summationIndexedByFunction);
    // NOTE: only products will bubble up before the summation.
    List<Expression> productsBefore = inversionQuantifierOrder.subList(0, indexOfSummationIndexedByFunction);
    Expression lastQuantifierHead = getHead(originalQuantifierOrder.get(originalQuantifierOrder.size() - 1));
    Context innerContext = context;
    for (Expression quantifier : originalQuantifierOrder) {
        innerContext = innerContext.extendWith(getIndexExpressions(quantifier));
    }
    Context lastQuantifierHeadContext = innerContext;
    // TODO - remove temporary hack which collapses the function's argument domains
    // due to all the domain arguments being treated as constants. Instead should be using
    // set expression types on singletons.				
    // Determine which domain arguments from the summation function can be collapsed
    List<Expression> productsBeforeIndices = new ArrayList<>();
    for (Expression productBefore : productsBefore) {
        productsBeforeIndices.add(getIndexAndType(productBefore).first);
    }
    Set<Integer> domainArgsToRemove = new HashSet<>();
    Set<Integer> domainArgsHaveVar = new HashSet<>();
    new SubExpressionsDepthFirstIterator(lastQuantifierHead).forEachRemaining(e -> {
        if (e.hasFunctor(summationIndexFunctionName)) {
            for (int i = 0; i < e.numberOfArguments(); i++) {
                if (lastQuantifierHeadContext.getTheory().isVariable(e.get(0), lastQuantifierHeadContext)) {
                    domainArgsHaveVar.add(i);
                }
                if (productsBeforeIndices.contains(e.get(i)) || Util.thereExists(new SubExpressionsDepthFirstIterator(e.get(i)), es -> productsBeforeIndices.contains(es))) {
                    domainArgsToRemove.add(i);
                }
            }
        }
    });
    // Remove arg positions that were not populated by a variable.
    for (int i = 0; i < summationIndexFunctionType.getArity(); i++) {
        if (!domainArgsHaveVar.contains(i)) {
            domainArgsToRemove.add(i);
        }
    }
    List<Expression> argTypes = new ArrayList<>();
    for (int i = 0; i < summationIndexFunctionType.getArity(); i++) {
        if (!domainArgsToRemove.contains(i)) {
            argTypes.add(parse(summationIndexFunctionType.getArgumentTypes().get(i).getName()));
        }
    }
    Expression codomainType = parse(summationIndexFunctionType.getCodomain().getName());
    Expression summationIndexReducedType;
    if (argTypes.size() == 0) {
        summationIndexReducedType = codomainType;
    } else {
        summationIndexReducedType = FunctionType.make(codomainType, argTypes);
    }
    Expression summationIndex = IndexExpressions.makeIndexExpression(summationIndexFunctionName, summationIndexReducedType);
    Expression phi = lastQuantifierHead.replaceAllOccurrences(e -> {
        Expression r = e;
        if (e.hasFunctor(summationIndexFunctionName)) {
            List<Expression> argsToKeep = new ArrayList<>();
            for (int i = 0; i < e.numberOfArguments(); i++) {
                if (!domainArgsToRemove.contains(i)) {
                    argsToKeep.add(e.get(i));
                }
            }
            if (argsToKeep.size() > 0) {
                r = Expressions.apply(summationIndexFunctionName, argsToKeep);
            } else {
                r = summationIndexFunctionName;
            }
        }
        return r;
    }, lastQuantifierHeadContext);
    Expression summationHead = phi;
    for (int i = indexOfSummationIndexedByFunction + 1; i < inversionQuantifierOrder.size(); i++) {
        Expression quantifier = inversionQuantifierOrder.get(i);
        Expression quantifierIntensionalSet = IntensionalSet.intensionalMultiSet(getIndexExpressions(quantifier), summationHead, getCondition(quantifier));
        summationHead = Expressions.apply(quantifier.getFunctor(), quantifierIntensionalSet);
    }
    Expression innerSummation = IntensionalSet.intensionalMultiSet(new ExtensionalIndexExpressionsSet(summationIndex), summationHead, getCondition(summationIndexedByFunction));
    result = Expressions.apply(FunctorConstants.SUM, innerSummation);
    for (int i = productsBefore.size() - 1; i >= 0; i--) {
        Expression product = productsBefore.get(i);
        product = IntensionalSet.intensionalMultiSet(getIndexExpressions(product), result, getCondition(product));
        result = Expressions.apply(FunctorConstants.PRODUCT, product);
    }
    return result;
}
Also used : Context(com.sri.ai.grinder.sgdpllt.api.Context) SubExpressionsDepthFirstIterator(com.sri.ai.expresso.helper.SubExpressionsDepthFirstIterator) ForAll(com.sri.ai.grinder.sgdpllt.library.boole.ForAll) Expressions(com.sri.ai.expresso.helper.Expressions) Expression(com.sri.ai.expresso.api.Expression) Disequality(com.sri.ai.grinder.sgdpllt.library.Disequality) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) GrinderUtil(com.sri.ai.grinder.helper.GrinderUtil) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) Expressions.parse(com.sri.ai.expresso.helper.Expressions.parse) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet) And(com.sri.ai.grinder.sgdpllt.library.boole.And) Pair(com.sri.ai.util.base.Pair) Equality(com.sri.ai.grinder.sgdpllt.library.Equality) Sets(com.sri.ai.grinder.sgdpllt.library.set.Sets) Type(com.sri.ai.expresso.api.Type) Implication(com.sri.ai.grinder.sgdpllt.library.boole.Implication) Simplifier(com.sri.ai.grinder.sgdpllt.rewriter.api.Simplifier) Set(java.util.Set) IntensionalSet(com.sri.ai.expresso.api.IntensionalSet) Context(com.sri.ai.grinder.sgdpllt.api.Context) FunctionType(com.sri.ai.expresso.type.FunctionType) List(java.util.List) IndexExpressions(com.sri.ai.grinder.sgdpllt.library.indexexpression.IndexExpressions) Util(com.sri.ai.util.Util) FunctorConstants(com.sri.ai.grinder.sgdpllt.library.FunctorConstants) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) Expression(com.sri.ai.expresso.api.Expression) ArrayList(java.util.ArrayList) SubExpressionsDepthFirstIterator(com.sri.ai.expresso.helper.SubExpressionsDepthFirstIterator) HashSet(java.util.HashSet)

Example 33 with FunctionType

use of com.sri.ai.expresso.type.FunctionType in project aic-expresso by aic-sri-international.

the class InversionSimplifier method getIndexAndFunctionType.

private static Pair<Expression, FunctionType> getIndexAndFunctionType(Expression functionOnIntensionalSet, Context context) {
    IndexExpressionsSet indexExpressionsSet = getIndexExpressions(functionOnIntensionalSet);
    List<Expression> indices = IndexExpressions.getIndices(indexExpressionsSet);
    if (indices.size() != 1) {
        throw new UnsupportedOperationException("Currently only support singular indices");
    }
    Expression index = indices.get(0);
    Context intensionalSetContext = context.extendWith(indexExpressionsSet);
    Type type = GrinderUtil.getType(index, intensionalSetContext);
    FunctionType functionType = null;
    if (type instanceof FunctionType) {
        functionType = (FunctionType) type;
    }
    Pair<Expression, FunctionType> result = new Pair<>(index, functionType);
    return result;
}
Also used : Context(com.sri.ai.grinder.sgdpllt.api.Context) Type(com.sri.ai.expresso.api.Type) FunctionType(com.sri.ai.expresso.type.FunctionType) Expression(com.sri.ai.expresso.api.Expression) FunctionType(com.sri.ai.expresso.type.FunctionType) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet) Pair(com.sri.ai.util.base.Pair)

Example 34 with FunctionType

use of com.sri.ai.expresso.type.FunctionType in project aic-expresso by aic-sri-international.

the class InversionSimplifier method simplify.

public static Expression simplify(Expression expression, Context context) {
    Expression result = expression;
    if (isSummationIndexedByFunctionOfQuantifiers(expression, context)) {
        // NOTE: at this point we know we have a summation indexed by a function
        Expression summationIndexedByFunction = expression;
        Pair<Expression, FunctionType> indexAndFunctionType = getIndexAndFunctionType(summationIndexedByFunction, context);
        Expression summationIndexFunctionName = indexAndFunctionType.first;
        FunctionType summationIndexFunctionType = indexAndFunctionType.second;
        List<Expression> originalQuantifierOrder = new ArrayList<>();
        collectQuantifiers(summationIndexedByFunction, originalQuantifierOrder);
        List<Expression> inversionQuantifierOrder = new ArrayList<>();
        if (isInversionPossible(summationIndexedByFunction, summationIndexFunctionName, summationIndexFunctionType, originalQuantifierOrder, inversionQuantifierOrder, context)) {
            result = applyInversion(summationIndexedByFunction, summationIndexFunctionName, summationIndexFunctionType, originalQuantifierOrder, inversionQuantifierOrder, context);
        }
    }
    return result;
}
Also used : Expression(com.sri.ai.expresso.api.Expression) FunctionType(com.sri.ai.expresso.type.FunctionType) ArrayList(java.util.ArrayList)

Example 35 with FunctionType

use of com.sri.ai.expresso.type.FunctionType in project aic-expresso by aic-sri-international.

the class SetOfArgumentTuplesForFunctionOccurringInExpression method computeUnionArgs.

private static void computeUnionArgs(List<Expression> unionArgs, Predicate<Expression> isF, FunctionType fType, Predicate<Expression> isFApplication, Expression e) {
    // if E does not contain &fnof;, oc<sub>&fnof;</sub>[E] is &empty;
    if (!containsF(e, isF)) {
        unionArgs.add(Sets.EMPTY_SET);
    } else // if E is &fnof;(t) for t a tuple, oc<sub>&fnof;</sub>[E] is {t}
    if (isFApplication.apply(e)) {
        Expression tupleT = Expressions.makeTuple(e.getArguments());
        Expression setT = ExtensionalSets.makeUniSet(tupleT);
        unionArgs.add(setT);
    } else // if E is &fnof;, oc<sub>&fnof;</sub>[E] is &Alpha;
    if (isF.apply(e)) {
        List<Expression> domainTypes = new ArrayList<>();
        for (Type domainType : fType.getArgumentTypes()) {
            domainTypes.add(Expressions.parse(domainType.getName()));
        }
        Expression tupleT = Expressions.makeTuple(domainTypes);
        Expression setT = ExtensionalSets.makeUniSet(tupleT);
        unionArgs.add(setT);
    } else // if E is g(E&prime;) for g a function symbol distinct from &fnof; and t a k-tuple of expressions
    if (Expressions.isFunctionApplicationWithArguments(e)) {
        // if g(E&prime;) is if C the E<sub>1</sub> else E<sub>2</sub> and C does not contain &fnof;
        if (IfThenElse.isIfThenElse(e) && !containsF(IfThenElse.condition(e), isF)) {
            // then oc<sub>&fnof;</sub>[E] is<br>
            // if C then oc<sub>&fnof;</sub>[E<sub>1</sub>] else oc<sub>&fnof;</sub>[E<sub>2</sub>]				
            Expression e1 = IfThenElse.thenBranch(e);
            List<Expression> thenUnionArgs = new ArrayList<>();
            computeUnionArgs(thenUnionArgs, isF, fType, isFApplication, e1);
            Expression thenBranch = makeUnion(thenUnionArgs);
            Expression e2 = IfThenElse.elseBranch(e);
            List<Expression> elseUnionArgs = new ArrayList<>();
            computeUnionArgs(elseUnionArgs, isF, fType, isFApplication, e2);
            Expression elseBranch = makeUnion(elseUnionArgs);
            Expression ifThenElse = IfThenElse.make(IfThenElse.condition(e), thenBranch, elseBranch);
            unionArgs.add(ifThenElse);
        } else {
            // oc<sub>&fnof;</sub>[t<sub>1</sub>] &cup; &hellip;	&cup; oc<sub>&fnof;</sub>[t<sub>k</sub>]
            for (Expression t : e.getArguments()) {
                computeUnionArgs(unionArgs, isF, fType, isFApplication, t);
            }
        }
    } else // quantified expression, 
    if (isArbitraryQuantifier(e) && !containsF(getQuantifierCondition(e), isF)) {
        // then oc<sub>&fnof;</sub>[E] is<br> 
        // &bigcup;<sub>x:C</sub>oc<sub>&fnof;</sub>[E&prime;]
        QuantifiedExpression q = (QuantifiedExpression) e;
        IndexExpressionsSet x = q.getIndexExpressions();
        Expression c = getQuantifierCondition(e);
        Expression ePrime = getQuantifiedExpression(q);
        List<Expression> ePrimeUnionArgs = new ArrayList<>();
        computeUnionArgs(ePrimeUnionArgs, isF, fType, isFApplication, ePrime);
        Expression ocfOfEPrime = makeUnion(ePrimeUnionArgs);
        Expression intensionalMultiSet = IntensionalSet.intensionalMultiSet(x, ocfOfEPrime, c);
        Expression intensionalUnion = Expressions.apply(FunctorConstants.INTENSIONAL_UNION, intensionalMultiSet);
        unionArgs.add(intensionalUnion);
    } else // quantified expression,
    if (isArbitraryQuantifier(e)) {
        // then oc<sub>&fnof;</sub>[E] is<br> 
        // &bigcup;<sub>x</sub>(oc<sub>&fnof;</sub>[C] &cup; oc<sub>&fnof;</sub>[E&prime;])
        QuantifiedExpression q = (QuantifiedExpression) e;
        IndexExpressionsSet x = q.getIndexExpressions();
        Expression c = getQuantifierCondition(e);
        Expression ePrime = getQuantifiedExpression(q);
        List<Expression> conditionUnionArgs = new ArrayList<>();
        computeUnionArgs(conditionUnionArgs, isF, fType, isFApplication, c);
        List<Expression> ePrimeUnionArgs = new ArrayList<>();
        computeUnionArgs(ePrimeUnionArgs, isF, fType, isFApplication, ePrime);
        List<Expression> combinedUnionArgs = new ArrayList<>();
        combinedUnionArgs.addAll(conditionUnionArgs);
        combinedUnionArgs.addAll(ePrimeUnionArgs);
        Expression combinedUnion = makeUnion(combinedUnionArgs);
        Expression intensionalMultiSet = IntensionalSet.intensionalMultiSet(x, combinedUnion, Expressions.TRUE);
        Expression intensionalUnion = Expressions.apply(FunctorConstants.INTENSIONAL_UNION, intensionalMultiSet);
        unionArgs.add(intensionalUnion);
    } else {
        throw new UnsupportedOperationException("Do not have logic for handling expression of the form: " + e);
    }
}
Also used : Type(com.sri.ai.expresso.api.Type) FunctionType(com.sri.ai.expresso.type.FunctionType) QuantifiedExpression(com.sri.ai.expresso.api.QuantifiedExpression) LambdaExpression(com.sri.ai.expresso.api.LambdaExpression) Expression(com.sri.ai.expresso.api.Expression) QuantifiedExpression(com.sri.ai.expresso.api.QuantifiedExpression) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet)

Aggregations

FunctionType (com.sri.ai.expresso.type.FunctionType)57 Test (org.junit.Test)28 Expression (com.sri.ai.expresso.api.Expression)23 Type (com.sri.ai.expresso.api.Type)22 IntegerInterval (com.sri.ai.expresso.type.IntegerInterval)17 Context (com.sri.ai.grinder.api.Context)15 Context (com.sri.ai.grinder.sgdpllt.api.Context)14 IndexExpressionsSet (com.sri.ai.expresso.api.IndexExpressionsSet)13 ArrayList (java.util.ArrayList)13 RealInterval (com.sri.ai.expresso.type.RealInterval)12 TheoryTestingSupport (com.sri.ai.grinder.sgdpllt.tester.TheoryTestingSupport)11 TheoryTestingSupport (com.sri.ai.grinder.tester.TheoryTestingSupport)11 TupleType (com.sri.ai.expresso.type.TupleType)10 StepSolver (com.sri.ai.grinder.api.StepSolver)10 StepSolver (com.sri.ai.grinder.sgdpllt.api.StepSolver)10 UnificationStepSolver (com.sri.ai.grinder.sgdpllt.theory.base.UnificationStepSolver)10 UnificationStepSolver (com.sri.ai.grinder.theory.base.UnificationStepSolver)10 Ignore (org.junit.Ignore)10 IntensionalSet (com.sri.ai.expresso.api.IntensionalSet)9 ExtensionalIndexExpressionsSet (com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet)9