Search in sources :

Example 16 with TupleType

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

the class TupleRewriterTest method testTupleValuedFreeVariablesSimplifier.

@Test
public void testTupleValuedFreeVariablesSimplifier() {
    Context tupleTheoryContext = new TrueContext(new CompoundTheory(new DifferenceArithmeticTheory(false, false), new TupleTheory()));
    TupleType nTupleType = new TupleType(new IntegerInterval(1, 10), new IntegerInterval(1, 10));
    tupleTheoryContext = (Context) GrinderUtil.extendRegistryWith(map("N", nTupleType.toString()), Arrays.asList(nTupleType), tupleTheoryContext);
    TupleValuedFreeVariablesSimplifier simplifier = new TupleValuedFreeVariablesSimplifier();
    Expression expression = parse("sum( {{ (on X in 1..10) if N = (2, X) then 2 else 3 }} )");
    Expression simplified = simplifier.apply(expression, tupleTheoryContext);
    Assert.assertEquals(parse("if get(N, 1) = 2 then 29 else 30"), simplified);
}
Also used : TrueContext(com.sri.ai.grinder.core.TrueContext) Context(com.sri.ai.grinder.api.Context) Expression(com.sri.ai.expresso.api.Expression) DifferenceArithmeticTheory(com.sri.ai.grinder.theory.differencearithmetic.DifferenceArithmeticTheory) IntegerInterval(com.sri.ai.expresso.type.IntegerInterval) TupleType(com.sri.ai.expresso.type.TupleType) TupleValuedFreeVariablesSimplifier(com.sri.ai.grinder.theory.tuple.rewriter.TupleValuedFreeVariablesSimplifier) CompoundTheory(com.sri.ai.grinder.theory.compound.CompoundTheory) TrueContext(com.sri.ai.grinder.core.TrueContext) TupleTheory(com.sri.ai.grinder.theory.tuple.TupleTheory) Test(org.junit.Test)

Example 17 with TupleType

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

the class TupleValuedFreeVariablesSimplifier method simplify.

public static Expression simplify(Expression expression, Context context) {
    Expression result = expression;
    // First see if we have any free variables.
    Map<Expression, Expression> freeVariablesAndTypes = Expressions.freeVariablesAndTypes(expression, context);
    if (freeVariablesAndTypes.size() > 0) {
        // Retrieve those that are tuples
        Map<Expression, TupleType> freeVariablesOfTupleType = freeVariablesAndTypes.entrySet().stream().filter(entry -> entry.getValue() != null && TupleType.isTupleType(entry.getValue())).collect(Collectors.toMap(e -> e.getKey(), e -> (TupleType) GrinderUtil.fromTypeExpressionToItsIntrinsicMeaning(e.getValue(), context)));
        if (freeVariablesOfTupleType.size() > 0) {
            final Map<Expression, List<Pair<Expression, Integer>>> freeVariableComponentsMap = constructComponentMap(freeVariablesOfTupleType, expression, context);
            // Replace the free tuple variables with their componentised forms
            // e.g. N --> (N1, N2)
            Expression componentisedExpression = expression.replaceAllOccurrences(expr -> {
                Expression replacement = expr;
                List<Pair<Expression, Integer>> replacementComponents = freeVariableComponentsMap.get(expr);
                if (replacementComponents != null) {
                    replacement = constructComponentTuple(replacementComponents);
                }
                return replacement;
            }, context);
            // Evaluate the expression with the un-componentized free tuple variables, within an extended
            // context that knows about the newly componentized variables
            Context contextExtendedWithComponentVariables = extendContextWithComponentVariables(context, freeVariablesOfTupleType, freeVariableComponentsMap);
            Expression evaluatedResult = context.getTheory().evaluate(componentisedExpression, contextExtendedWithComponentVariables);
            // Translate back the free variable components
            // e.g:
            // if N1 = 2 then 29 else 30
            // ---->
            // if get(N, 1) = 2 then 29 else 30
            final Map<Expression, Pair<Expression, Integer>> componentToFreeVariableMap = createReverseLookupMap(freeVariableComponentsMap);
            result = evaluatedResult.replaceAllOccurrences(expr -> {
                Expression replacement = expr;
                Pair<Expression, Integer> correspondingFreeVariableWithIndex = componentToFreeVariableMap.get(expr);
                if (correspondingFreeVariableWithIndex != null) {
                    replacement = Expressions.apply(FunctorConstants.GET, correspondingFreeVariableWithIndex.first, correspondingFreeVariableWithIndex.second);
                }
                return replacement;
            }, contextExtendedWithComponentVariables);
        }
    }
    return result;
}
Also used : Type(com.sri.ai.expresso.api.Type) Expressions(com.sri.ai.expresso.helper.Expressions) Set(java.util.Set) Expression(com.sri.ai.expresso.api.Expression) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) GrinderUtil(com.sri.ai.grinder.helper.GrinderUtil) List(java.util.List) TupleType(com.sri.ai.expresso.type.TupleType) Map(java.util.Map) Simplifier(com.sri.ai.grinder.rewriter.api.Simplifier) Context(com.sri.ai.grinder.api.Context) FunctorConstants(com.sri.ai.grinder.library.FunctorConstants) LinkedHashSet(java.util.LinkedHashSet) Pair(com.sri.ai.util.base.Pair) Context(com.sri.ai.grinder.api.Context) Expression(com.sri.ai.expresso.api.Expression) TupleType(com.sri.ai.expresso.type.TupleType) ArrayList(java.util.ArrayList) List(java.util.List) Pair(com.sri.ai.util.base.Pair)

Example 18 with TupleType

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

the class TupleValuedFreeVariablesSimplifier method constructComponentMap.

private static Map<Expression, List<Pair<Expression, Integer>>> constructComponentMap(Map<Expression, TupleType> freeVariablesOfTupleType, Expression expression, Context context) {
    Map<Expression, List<Pair<Expression, Integer>>> result = new LinkedHashMap<>();
    for (Map.Entry<Expression, TupleType> freeVariableOfTupleType : freeVariablesOfTupleType.entrySet()) {
        Expression freeVariable = freeVariableOfTupleType.getKey();
        TupleType freeVariableTupleType = freeVariableOfTupleType.getValue();
        List<Pair<Expression, Integer>> components = new ArrayList<>();
        int tupleArity = freeVariableTupleType.getArity();
        for (int i = 1; i <= tupleArity; i++) {
            String proposedComponentVariableName = freeVariable.toString() + i;
            Expression componentVariable = Expressions.makeUniqueVariable(proposedComponentVariableName, expression, context);
            components.add(new Pair<>(componentVariable, i));
        }
        result.put(freeVariable, components);
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Expression(com.sri.ai.expresso.api.Expression) TupleType(com.sri.ai.expresso.type.TupleType) ArrayList(java.util.ArrayList) List(java.util.List) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) Pair(com.sri.ai.util.base.Pair)

Example 19 with TupleType

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

the class GrinderUtil method fromTypeExpressionToItsIntrinsicMeaning.

/**
 * A method mapping type expressions to their intrinsic {@link Type} objects,
 * where "intrinsic" means there is only one possible {@link Type} object
 * for them in the registry of grinder
 * (therefore, it cannot be used for, say, categorical types defined
 * by the user and registered in the registry by name only).
 * Current recognized type expressions are
 * <code>Boolean</code>, <code>Integer</code>, and function applications
 * of the type <code>model..n</code>.
 * If there is no such meaning, the method returns <code>null</code>.
 * @param typeExpression
 * @param registry TODO
 * @return
 */
public static Type fromTypeExpressionToItsIntrinsicMeaning(Expression typeExpression, Registry registry) throws Error {
    Type type;
    if (typeExpression.equals("Boolean")) {
        type = BOOLEAN_TYPE;
    } else if (typeExpression.equals("Integer")) {
        type = INTEGER_TYPE;
    } else if (typeExpression.equals("Real")) {
        type = REAL_TYPE;
    } else if (typeExpression.hasFunctor(INTEGER_INTERVAL) && typeExpression.numberOfArguments() == 2) {
        type = new IntegerInterval(typeExpression.get(0), typeExpression.get(1));
    } else if ((typeExpression.hasFunctor(FunctorConstants.REAL_INTERVAL_CLOSED_CLOSED) || typeExpression.hasFunctor(FunctorConstants.REAL_INTERVAL_OPEN_CLOSED) || typeExpression.hasFunctor(FunctorConstants.REAL_INTERVAL_CLOSED_OPEN) || typeExpression.hasFunctor(FunctorConstants.REAL_INTERVAL_OPEN_OPEN)) && typeExpression.numberOfArguments() == 2) {
        type = new RealInterval(typeExpression.toString());
    } else if (FunctionType.isFunctionType(typeExpression)) {
        Function<Expression, Type> getType = e -> registry.getTypeFromTypeExpression(e);
        Type codomain = getType.apply(FunctionType.getCodomain(typeExpression));
        List<Expression> argumentTypeExpressions = FunctionType.getArgumentList(typeExpression);
        ArrayList<Type> argumentTypes = mapIntoArrayList(argumentTypeExpressions, getType);
        Type[] argumentTypesArray = new Type[argumentTypes.size()];
        type = new FunctionType(codomain, argumentTypes.toArray(argumentTypesArray));
    } else if (TupleType.isTupleType(typeExpression)) {
        List<Type> elementTypes = typeExpression.getArguments().stream().map(elementTypeExpression -> registry.getTypeFromTypeExpression(elementTypeExpression)).collect(Collectors.toList());
        type = new TupleType(elementTypes);
    } else {
        type = null;
    }
    return type;
}
Also used : CountingFormula(com.sri.ai.expresso.api.CountingFormula) FALSE(com.sri.ai.expresso.helper.Expressions.FALSE) INTEGER_INTERVAL(com.sri.ai.grinder.library.FunctorConstants.INTEGER_INTERVAL) Expressions(com.sri.ai.expresso.helper.Expressions) Rational(com.sri.ai.util.math.Rational) SUM(com.sri.ai.grinder.library.FunctorConstants.SUM) Expression(com.sri.ai.expresso.api.Expression) FUNCTION_TYPE(com.sri.ai.grinder.library.FunctorConstants.FUNCTION_TYPE) Util.getFirstSatisfyingPredicateOrNull(com.sri.ai.util.Util.getFirstSatisfyingPredicateOrNull) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) Symbol(com.sri.ai.expresso.api.Symbol) Equality(com.sri.ai.grinder.library.Equality) TrueContext(com.sri.ai.grinder.core.TrueContext) IndexExpressions(com.sri.ai.grinder.library.indexexpression.IndexExpressions) Map(java.util.Map) Context(com.sri.ai.grinder.api.Context) Util.thereExists(com.sri.ai.util.Util.thereExists) MAX(com.sri.ai.grinder.library.FunctorConstants.MAX) 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) IfThenElse(com.sri.ai.grinder.library.controlflow.IfThenElse) Collectors(java.util.stream.Collectors) DefaultPolynomial(com.sri.ai.grinder.polynomial.core.DefaultPolynomial) 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) Predicate(com.google.common.base.Predicate) LESS_THAN(com.sri.ai.grinder.library.FunctorConstants.LESS_THAN) FunctorConstants(com.sri.ai.grinder.library.FunctorConstants) TRUE(com.sri.ai.expresso.helper.Expressions.TRUE) TIMES(com.sri.ai.grinder.library.FunctorConstants.TIMES) 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) CARDINALITY(com.sri.ai.grinder.library.FunctorConstants.CARDINALITY) Util.mapIntoArrayList(com.sri.ai.util.Util.mapIntoArrayList) IntegerInterval(com.sri.ai.expresso.type.IntegerInterval) Sets(com.sri.ai.grinder.library.set.Sets) ArrayList(java.util.ArrayList) ExtensionalSets(com.sri.ai.grinder.library.set.extensional.ExtensionalSets) EXPONENTIATION(com.sri.ai.grinder.library.FunctorConstants.EXPONENTIATION) TupleType(com.sri.ai.expresso.type.TupleType) Expressions.apply(com.sri.ai.expresso.helper.Expressions.apply) LessThan(com.sri.ai.grinder.library.number.LessThan) Expressions.parse(com.sri.ai.expresso.helper.Expressions.parse) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet) Registry(com.sri.ai.grinder.api.Registry) LinkedList(java.util.LinkedList) Util.arrayList(com.sri.ai.util.Util.arrayList) Util.ifAllTheSameOrNull(com.sri.ai.util.Util.ifAllTheSameOrNull) LambdaExpression(com.sri.ai.expresso.api.LambdaExpression) LESS_THAN_OR_EQUAL_TO(com.sri.ai.grinder.library.FunctorConstants.LESS_THAN_OR_EQUAL_TO) Type(com.sri.ai.expresso.api.Type) FormulaUtil(com.sri.ai.grinder.library.FormulaUtil) Disequality(com.sri.ai.grinder.library.Disequality) MINUS(com.sri.ai.grinder.library.FunctorConstants.MINUS) RealExpressoType(com.sri.ai.expresso.type.RealExpressoType) MINUS_INFINITY(com.sri.ai.expresso.helper.Expressions.MINUS_INFINITY) PLUS(com.sri.ai.grinder.library.FunctorConstants.PLUS) DefaultUniversallyQuantifiedFormula(com.sri.ai.expresso.core.DefaultUniversallyQuantifiedFormula) GREATER_THAN(com.sri.ai.grinder.library.FunctorConstants.GREATER_THAN) 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) GREATER_THAN_OR_EQUAL_TO(com.sri.ai.grinder.library.FunctorConstants.GREATER_THAN_OR_EQUAL_TO) Theory(com.sri.ai.grinder.api.Theory) 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) DIVISION(com.sri.ai.grinder.library.FunctorConstants.DIVISION) EMPTY_TUPLE(com.sri.ai.expresso.api.Tuple.EMPTY_TUPLE) Util(com.sri.ai.util.Util) GreaterThan(com.sri.ai.grinder.library.number.GreaterThan) PRODUCT(com.sri.ai.grinder.library.FunctorConstants.PRODUCT) Function(com.google.common.base.Function) 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) IntegerInterval(com.sri.ai.expresso.type.IntegerInterval) FunctionType(com.sri.ai.expresso.type.FunctionType) Util.mapIntoArrayList(com.sri.ai.util.Util.mapIntoArrayList) ArrayList(java.util.ArrayList) 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) RealInterval(com.sri.ai.expresso.type.RealInterval)

Example 20 with TupleType

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

the class GrinderUtil method getTypeExpressionOfExpression.

/**
 * Returns the type of given expression according to registry.
 */
public static Expression getTypeExpressionOfExpression(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 = getTypeExpressionOfExpression(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 = getTypeExpressionOfExpression(IfThenElse.thenBranch(expression), registry);
        Expression elseType = getTypeExpressionOfExpression(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 -> getTypeExpressionOfExpression(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 = getTypeExpressionOfExpression(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.getTypeExpressionOfRegisteredSymbol(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 = getTypeExpressionOfExpression(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 = getTypeExpressionOfExpression(expression.getFunctor(), registry);
        if (functionType == null) {
            throw new Error("Type of '" + expression.getFunctor() + "' required but unknown.");
        }
        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.getTypeFromTypeExpression(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 -> getTypeExpressionOfExpression(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 = getTypeExpressionOfExpression(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 = getTypeExpressionOfExpression(lambdaExpression.getBody(), lambdaExpressionWithABodyRegistry);
        result = Expressions.apply(FUNCTION_TYPE, domain, coDomain);
    } else if (expression instanceof AbstractExpressionWrapper) {
        Expression innerExpression = ((AbstractExpressionWrapper) expression).getInnerExpression();
        result = getTypeExpressionOfExpression(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 : CountingFormula(com.sri.ai.expresso.api.CountingFormula) FALSE(com.sri.ai.expresso.helper.Expressions.FALSE) INTEGER_INTERVAL(com.sri.ai.grinder.library.FunctorConstants.INTEGER_INTERVAL) Expressions(com.sri.ai.expresso.helper.Expressions) Rational(com.sri.ai.util.math.Rational) SUM(com.sri.ai.grinder.library.FunctorConstants.SUM) Expression(com.sri.ai.expresso.api.Expression) FUNCTION_TYPE(com.sri.ai.grinder.library.FunctorConstants.FUNCTION_TYPE) Util.getFirstSatisfyingPredicateOrNull(com.sri.ai.util.Util.getFirstSatisfyingPredicateOrNull) ExtensionalIndexExpressionsSet(com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet) Symbol(com.sri.ai.expresso.api.Symbol) Equality(com.sri.ai.grinder.library.Equality) TrueContext(com.sri.ai.grinder.core.TrueContext) IndexExpressions(com.sri.ai.grinder.library.indexexpression.IndexExpressions) Map(java.util.Map) Context(com.sri.ai.grinder.api.Context) Util.thereExists(com.sri.ai.util.Util.thereExists) MAX(com.sri.ai.grinder.library.FunctorConstants.MAX) 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) IfThenElse(com.sri.ai.grinder.library.controlflow.IfThenElse) Collectors(java.util.stream.Collectors) DefaultPolynomial(com.sri.ai.grinder.polynomial.core.DefaultPolynomial) 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) Predicate(com.google.common.base.Predicate) LESS_THAN(com.sri.ai.grinder.library.FunctorConstants.LESS_THAN) FunctorConstants(com.sri.ai.grinder.library.FunctorConstants) TRUE(com.sri.ai.expresso.helper.Expressions.TRUE) TIMES(com.sri.ai.grinder.library.FunctorConstants.TIMES) 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) CARDINALITY(com.sri.ai.grinder.library.FunctorConstants.CARDINALITY) Util.mapIntoArrayList(com.sri.ai.util.Util.mapIntoArrayList) IntegerInterval(com.sri.ai.expresso.type.IntegerInterval) Sets(com.sri.ai.grinder.library.set.Sets) ArrayList(java.util.ArrayList) ExtensionalSets(com.sri.ai.grinder.library.set.extensional.ExtensionalSets) EXPONENTIATION(com.sri.ai.grinder.library.FunctorConstants.EXPONENTIATION) TupleType(com.sri.ai.expresso.type.TupleType) Expressions.apply(com.sri.ai.expresso.helper.Expressions.apply) LessThan(com.sri.ai.grinder.library.number.LessThan) Expressions.parse(com.sri.ai.expresso.helper.Expressions.parse) IndexExpressionsSet(com.sri.ai.expresso.api.IndexExpressionsSet) Registry(com.sri.ai.grinder.api.Registry) LinkedList(java.util.LinkedList) Util.arrayList(com.sri.ai.util.Util.arrayList) Util.ifAllTheSameOrNull(com.sri.ai.util.Util.ifAllTheSameOrNull) LambdaExpression(com.sri.ai.expresso.api.LambdaExpression) LESS_THAN_OR_EQUAL_TO(com.sri.ai.grinder.library.FunctorConstants.LESS_THAN_OR_EQUAL_TO) Type(com.sri.ai.expresso.api.Type) FormulaUtil(com.sri.ai.grinder.library.FormulaUtil) Disequality(com.sri.ai.grinder.library.Disequality) MINUS(com.sri.ai.grinder.library.FunctorConstants.MINUS) RealExpressoType(com.sri.ai.expresso.type.RealExpressoType) MINUS_INFINITY(com.sri.ai.expresso.helper.Expressions.MINUS_INFINITY) PLUS(com.sri.ai.grinder.library.FunctorConstants.PLUS) DefaultUniversallyQuantifiedFormula(com.sri.ai.expresso.core.DefaultUniversallyQuantifiedFormula) GREATER_THAN(com.sri.ai.grinder.library.FunctorConstants.GREATER_THAN) 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) GREATER_THAN_OR_EQUAL_TO(com.sri.ai.grinder.library.FunctorConstants.GREATER_THAN_OR_EQUAL_TO) Theory(com.sri.ai.grinder.api.Theory) 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) DIVISION(com.sri.ai.grinder.library.FunctorConstants.DIVISION) EMPTY_TUPLE(com.sri.ai.expresso.api.Tuple.EMPTY_TUPLE) Util(com.sri.ai.util.Util) GreaterThan(com.sri.ai.grinder.library.number.GreaterThan) PRODUCT(com.sri.ai.grinder.library.FunctorConstants.PRODUCT) 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)

Aggregations

TupleType (com.sri.ai.expresso.type.TupleType)23 Expression (com.sri.ai.expresso.api.Expression)17 Type (com.sri.ai.expresso.api.Type)13 IntegerInterval (com.sri.ai.expresso.type.IntegerInterval)11 FunctionType (com.sri.ai.expresso.type.FunctionType)10 ArrayList (java.util.ArrayList)9 Map (java.util.Map)9 RealExpressoType (com.sri.ai.expresso.type.RealExpressoType)8 RealInterval (com.sri.ai.expresso.type.RealInterval)8 List (java.util.List)7 Categorical (com.sri.ai.expresso.type.Categorical)6 IntegerExpressoType (com.sri.ai.expresso.type.IntegerExpressoType)6 Context (com.sri.ai.grinder.api.Context)6 Pair (com.sri.ai.util.base.Pair)6 LinkedHashMap (java.util.LinkedHashMap)6 IndexExpressionsSet (com.sri.ai.expresso.api.IndexExpressionsSet)5 IntensionalSet (com.sri.ai.expresso.api.IntensionalSet)5 ExtensionalIndexExpressionsSet (com.sri.ai.expresso.core.ExtensionalIndexExpressionsSet)5 Expressions (com.sri.ai.expresso.helper.Expressions)5 Rational (com.sri.ai.util.math.Rational)5