use of com.sri.ai.expresso.api.Type in project aic-expresso by aic-sri-international.
the class BPTest method generateProbability.
private static Expression generateProbability(Context context, int i, Expression... listOfVariables) {
if (listOfVariables.length == 0) {
return null;
}
// randomNumberGenerator();
Expression result = makeSymbol(0);
Expression variable = listOfVariables[i];
// listOfVariables.remove(0);
Type type = context.getTypeOfRegisteredSymbol(variable);
Iterator<Expression> iteratorToValuesInType = type.iterator();
if (listOfVariables.length == i + 1) {
for (Expression value : in(iteratorToValuesInType)) {
Expression varEqualsValue = apply(EQUAL, variable, value);
Expression randProbability = randomNumberGenerator();
result = apply(IF_THEN_ELSE, varEqualsValue, randProbability, result);
}
} else {
for (Expression value : in(iteratorToValuesInType)) {
Expression varEqualsValue = apply(EQUAL, variable, value);
Expression randProbability = generateProbability(context, i + 1, listOfVariables);
result = apply(IF_THEN_ELSE, varEqualsValue, randProbability, result);
}
}
return result;
}
use of com.sri.ai.expresso.api.Type in project aic-expresso by aic-sri-international.
the class Context method extendWith.
/**
* Extends context with index expressions, taking into account that new contextual variables may collide with existing ones.
* In this case, it renames the incoming variables to unique identifiers and replaces them in the types of remaining
* index expressions. It also renames these indices if they occur in a given expression --
* this is useful because the client code (invoking this method)
* often knows that these renamed indices may occur in a known set of expressions that need to be updated accordingly.
* Returns the new context, the index expressions and expression in scope after the renaming.
* @param indexExpressions
* @param expressionInScope
* @return the new context and the index expressions and expression in scope after the renaming
*/
default Triple<Context, ExtensionalIndexExpressionsSet, Expression> extendWith(ExtensionalIndexExpressionsSet indexExpressions, Expression expressionInScope) {
Triple<Context, ExtensionalIndexExpressionsSet, Expression> result;
if (thereExists(getIndices(indexExpressions), index -> this.containsSymbol(index))) {
// OPTIMIZATION: only kick in this entire procedure when extending with symbol in the context (previous ones could have been dealt with normally).
// the objects to be returned in the triple:
Context newContext = this;
ArrayList<Expression> newIndexExpressionsList = new ArrayList<>(indexExpressions.getList());
Expression newExpressionInScope = expressionInScope;
// Collects all existing symbols to be able to create unique symbols
Set<Expression> alreadyDefined = Util.set();
alreadyDefined.addAll(this.getSymbols());
alreadyDefined.addAll(Expressions.freeSymbols(new DefaultTuple(newIndexExpressionsList), this));
alreadyDefined.addAll(Expressions.freeSymbols(expressionInScope, this));
Predicate<Expression> isAlreadyDefined = e -> alreadyDefined.contains(e);
for (int i = 0; i != newIndexExpressionsList.size(); i++) {
Expression indexExpression = newIndexExpressionsList.get(i);
Symbol index = (Symbol) indexExpression.get(0);
Expression type = indexExpression.get(1);
PairOf<Expression> newIndexAndNewExpressionInScope = Expressions.standardizeApart(index, isAlreadyDefined, newExpressionInScope);
Expression newIndex = newIndexAndNewExpressionInScope.first;
newExpressionInScope = newIndexAndNewExpressionInScope.second;
// type should not contain the index
Expression newIndexExpression = apply(IN, newIndex, type);
newIndexExpressionsList.set(i, newIndexExpression);
alreadyDefined.add(newIndex);
for (int j = i + 1; j != newIndexExpressionsList.size(); j++) {
Expression anotherIndexExpression = newIndexExpressionsList.get(j);
Expression anotherIndex = anotherIndexExpression.get(0);
Expression anotherType = anotherIndexExpression.get(1);
Expression newAnotherType = anotherType.replaceSymbol(index, newIndex, this);
// anotherIndex is a symbols and does not contain index
Expression newAnotherIndexExpression = apply(IN, anotherIndex, newAnotherType);
newIndexExpressionsList.set(j, newAnotherIndexExpression);
}
}
ExtensionalIndexExpressionsSet newIndexExpressions = new ExtensionalIndexExpressionsSet(newIndexExpressionsList);
newContext = newContext.extendWith(newIndexExpressions);
result = triple(newContext, newIndexExpressions, newExpressionInScope);
} else {
// no collision; usual extension and the expressions do not change.
result = triple(extendWith(indexExpressions), indexExpressions, expressionInScope);
}
return result;
}
use of com.sri.ai.expresso.api.Type in project aic-expresso by aic-sri-international.
the class Theory method makeSingleVariableConstraint.
/**
* Make a new single-variable constraint for this theory.
* Default implementation checks suitability of type and invokes {@link #makeSingleVariableConstraint(Expression, Context)}.
* @param variable
* @param context
* @return the constraint, or null if there is no theory for the variable.
*/
default SingleVariableConstraint makeSingleVariableConstraint(Expression variable, Context context) {
Type variableType = context.getTypeOfRegisteredSymbol(variable);
myAssert(context.getTheory().isSuitableFor(variableType), () -> this + " does not know how to make constraints for variable " + variable + " of type " + variableType);
SingleVariableConstraint result = makeSingleVariableConstraintAfterBookkeeping(variable, context);
return result;
}
use of com.sri.ai.expresso.api.Type in project aic-expresso by aic-sri-international.
the class Compilation method compile.
/**
* Compiles an expression to a normalized (decision-tree-like) expression.
* @param inputExpression
* @param mapFromVariableNameToTypeName
* @param mapFromCategoricalTypeNameToSizeString
* @param additionalTypes
* @param solverListener if not null, invoked on solver used for compilation, before and after compilation starts; returned solver on 'before' invocation is used (it may be the same one used as argument, of course).
* @return
*/
public static Expression compile(Expression inputExpression, Theory theory, Map<String, String> mapFromVariableNameToTypeName, Map<String, String> mapFromUniquelyNamedConstantToTypeName, Map<String, String> mapFromCategoricalTypeNameToSizeString, Collection<Type> additionalTypes, Function<MultiQuantifierEliminator, MultiQuantifierEliminator> solverListener) {
// the group actually does not matter, because we are not going to have any indices.
AssociativeCommutativeGroup group = new Max();
// The solver for the parameters above.
MultiQuantifierEliminator solver = new DefaultMultiQuantifierEliminator();
if (solverListener != null) {
solver = solverListener.apply(solver);
}
// We use the Prolog convention of small-letter initials for constants, but we need an exception for the random variables.
Predicate<Expression> isPrologConstant = new PrologConstantPredicate();
Predicate<Expression> isUniquelyNamedConstantPredicate = e -> isPrologConstant.apply(e) && !mapFromVariableNameToTypeName.containsKey(e);
Map<String, String> mapFromSymbolNameToTypeName = new LinkedHashMap<>(mapFromVariableNameToTypeName);
mapFromSymbolNameToTypeName.putAll(mapFromUniquelyNamedConstantToTypeName);
// Solve the problem.
// no indices; we want to keep all variables
List<Expression> indices = Util.list();
Expression result = solver.solve(group, inputExpression, indices, mapFromSymbolNameToTypeName, mapFromCategoricalTypeNameToSizeString, additionalTypes, isUniquelyNamedConstantPredicate, theory);
if (solverListener != null) {
solverListener.apply(null);
}
return result;
}
use of com.sri.ai.expresso.api.Type in project aic-expresso by aic-sri-international.
the class Measure method get.
public static Rational get(Expression intensionalSetExpression, Context context) {
Rational result;
if (Sets.isIntensionalSet(intensionalSetExpression)) {
IntensionalSet intensionalSet = (IntensionalSet) intensionalSetExpression;
IndexExpressionsSet indexExpressionsSet = intensionalSet.getIndexExpressions();
List<Expression> indices = IndexExpressions.getIndices(indexExpressionsSet);
if (indices.size() == 1) {
Expression evaluatedResult;
Expression intensionalSetIndex = indices.get(0);
Expression intensionalSetHead = intensionalSet.getHead();
if (!intensionalSetHead.equals(intensionalSetIndex)) {
throw new UnsupportedOperationException("Index and Head must be the same to calculate the meaure of an Intensional : " + intensionalSet);
}
Expression intensionalSetCondition = intensionalSet.getCondition();
Context intensionalSetContext = context.extendWith(indexExpressionsSet);
Type indexType = GrinderUtil.getTypeOfExpression(intensionalSetIndex, intensionalSetContext);
if (intensionalSetCondition.equals(false)) {
// short circuit known empty sets up front.
evaluatedResult = Expressions.ZERO;
} else if (indexType instanceof RealExpressoType || indexType instanceof RealInterval) {
// NOTE : For Reals can always assume the condition is of this type.
SingleVariableLinearRealArithmeticConstraint svConstraint = (SingleVariableLinearRealArithmeticConstraint) intensionalSetCondition;
MeasureOfSingleVariableLinearRealArithmeticConstraintStepSolver realSolver = new MeasureOfSingleVariableLinearRealArithmeticConstraintStepSolver(svConstraint);
evaluatedResult = realSolver.solve(intensionalSetContext);
} else if (indexType instanceof FunctionType) {
if (!intensionalSetCondition.equals(true)) {
throw new UnsupportedOperationException("Measure of intensional set with a function type domain currently do not support conditions: " + intensionalSet);
}
// measure(co-domain)^measure(domain)
FunctionType indexFunctionType = (FunctionType) indexType;
Expression condomainIntensionalSet = constructComponentIntensionalSet(indexFunctionType.getCodomain(), intensionalSet, ZERO, intensionalSetContext);
Rational codomainMeasure = get(condomainIntensionalSet, intensionalSetContext);
Rational domainMeasure = Rational.ONE;
for (Type argDomainType : indexFunctionType.getArgumentTypes()) {
Expression argDomainIntensionalSet = constructComponentIntensionalSet(argDomainType, intensionalSet, ZERO, intensionalSetContext);
Rational argMeasure = get(argDomainIntensionalSet, intensionalSetContext);
domainMeasure = domainMeasure.multiply(argMeasure);
}
evaluatedResult = Expressions.makeSymbol(codomainMeasure.pow(domainMeasure.intValueExact()));
} else if (indexType instanceof TupleType) {
if (!intensionalSetCondition.equals(true)) {
throw new UnsupportedOperationException("Measure of intensional set with a tuple type domain currently do not support conditions: " + intensionalSet);
}
// (element_1, ..., element_n) = measure(element_1) * ... * measure(element_n)
TupleType indexTupleType = (TupleType) indexType;
Rational elementMeasuresProduct = Rational.ONE;
for (Type elementType : indexTupleType.getElementTypes()) {
Expression elementDomainIntensionalSet = constructComponentIntensionalSet(elementType, intensionalSet, ZERO, intensionalSetContext);
Rational elementMeasure = get(elementDomainIntensionalSet, intensionalSetContext);
elementMeasuresProduct = elementMeasuresProduct.multiply(elementMeasure);
}
evaluatedResult = Expressions.makeSymbol(elementMeasuresProduct);
} else {
Expression countingFormula = new DefaultCountingFormula(indexExpressionsSet, intensionalSet.getCondition());
evaluatedResult = context.getTheory().evaluate(countingFormula, context);
}
if (Expressions.isNumber(evaluatedResult)) {
result = evaluatedResult.rationalValue();
} else {
throw new UnsupportedOperationException("Unable to compute a finite measure for: " + intensionalSet + ", got : " + evaluatedResult);
}
} else {
throw new UnsupportedOperationException("Currently only support the measure of single indexed intensional sets: " + intensionalSet);
}
} else {
throw new IllegalArgumentException("Not an intensional set: " + intensionalSetExpression);
}
return result;
}
Aggregations