use of com.sri.ai.expresso.api.Expression in project aic-expresso by aic-sri-international.
the class Conjunction method addNTimes.
@Override
public Expression addNTimes(Expression value, Expression n, Context context) {
Expression result;
if (value.equals(TRUE) || n.equals(ZERO)) {
result = TRUE;
} else if (n.getValue() instanceof Number) {
// we already know value is not true and n is greater than zero from the previous condition having failed
result = FALSE;
} else // n is a symbolic value, so now it all depends on its being greater than zero
if (IfThenElse.isIfThenElse(n)) {
Expression condition = IfThenElse.condition(n);
Expression thenBranch = IfThenElse.thenBranch(n);
Expression elseBranch = IfThenElse.elseBranch(n);
Expression newThenBranch = addNTimes(value, thenBranch, context);
Expression newElseBranch = addNTimes(value, elseBranch, context);
// do not simplify to condition so it is a DPLL solution
result = IfThenElse.make(condition, newThenBranch, newElseBranch, false);
} else {
// it will only be true if n is zero
result = apply(EQUAL, n, Expressions.ZERO);
}
return result;
}
use of com.sri.ai.expresso.api.Expression in project aic-expresso by aic-sri-international.
the class CommutativeAssociative method make.
/**
* Similar to {@link Expressions#apply(Object, Object...)},
* but makes a simplified function application of an associative commutative operator,
* that is, its application but for the cases in which there are no arguments, or a single argument.
* When there are no arguments, a given neutral element value is returned.
* When a single argument is provided, it is returned itself.
* @param isIdempotent TODO
*/
public static Expression make(Object functor, List<Expression> arguments, Expression neutralElement, boolean isIdempotent) {
Predicate<Expression> notEqualToNeutralElement = Predicates.not(new Equals<Expression>(neutralElement));
arguments = Util.collectToList(arguments, notEqualToNeutralElement);
if (isIdempotent) {
Set<Expression> argumentsSet = new LinkedHashSet<Expression>(arguments);
arguments = new ArrayList<Expression>(argumentsSet);
}
if (arguments.isEmpty()) {
return Expressions.wrap(neutralElement);
}
if (arguments.size() == 1) {
return arguments.get(0);
}
Expression result = Expressions.makeExpressionOnSyntaxTreeWithLabelAndSubTrees(Expressions.wrap(functor), arguments);
result = Associative.associateWhenSureOperatorIsAssociative(result);
return result;
}
use of com.sri.ai.expresso.api.Expression in project aic-expresso by aic-sri-international.
the class CommutativeAssociative method apply.
@Override
public Expression apply(Expression expression, Context context) {
if (!expression.hasFunctor(getFunctor())) {
return expression;
}
if (!isExtensional(expression)) {
return expression;
}
List<Expression> arguments = expression.getArguments();
if (arguments.isEmpty()) {
return getNeutralElementExpression();
}
if (arguments.size() == 1) {
return expression.get(0);
}
LinkedList<Expression> operableArguments = new LinkedList<Expression>();
LinkedList<Expression> nonOperableArguments = new LinkedList<Expression>();
int indexOfFirstOperable = Util.collect(arguments, operableArguments, getIsOperableArgumentExpressionPredicate(), nonOperableArguments);
if (operableArguments.size() == 0) {
// everything is an non-operable argument, nothing that can be done.
return expression;
}
if (operableArguments.contains(getAbsorbingElement())) {
return getAbsorbingElement();
}
// get result on operable arguments
Expression resultOnOperableArgumentsExpression = operationOnOperableArguments(operableArguments);
// a distinct but equal instance that would keep being re-evaluated by the same manipulator.
if (operableArguments.size() == 1) {
if (operableArguments.getFirst().equals(getNeutralElementExpression())) {
// we don't need to include the neutral element, and are left with non-operable arguments only, done.
Expression result = makeExpressionWithSameFunctorAsThis(nonOperableArguments);
return result;
} else {
// the expression is formed by non-operable arguments and a single non-neutral operable argument, nothing else to do.
return expression;
}
}
// if there are no non-operable arguments, that's it.
if (nonOperableArguments.size() == 0) {
return resultOnOperableArgumentsExpression;
}
// if there are non-operable arguments, put them together with operables's result, unless this is the neutral element.
// changing semantics, and therefore, for clarity, the name. It's ok to modify it since it's been created locally.
LinkedList<Expression> argumentsOfResultingExpression = nonOperableArguments;
if (!resultOnOperableArgumentsExpression.equals(getNeutralElement())) {
argumentsOfResultingExpression.add(indexOfFirstOperable, resultOnOperableArgumentsExpression);
}
// return operation on result on operable and non-operable arguments.
Expression result = makeExpressionWithSameFunctorAsThis(argumentsOfResultingExpression);
return result;
}
use of com.sri.ai.expresso.api.Expression in project aic-expresso by aic-sri-international.
the class CommutativeAssociative method make.
/**
* Makes a commutative associative application from arguments in an iterator's range.
* This is potentially efficient in that it will stop as soon as the result is determined
* when it finds an absorbing element.
* If the arguments are being computed on the fly (for example, the iterator is a UnaryFunctionIterator),
* this can save a lot of time.
*/
public static Expression make(Object functor, Iterator<? extends Expression> argumentsIterator, Expression absorbingElement, Expression neutralElement, boolean isIdempotent) {
absorbingElement = Expressions.wrap(absorbingElement);
List<Expression> arguments = new LinkedList<Expression>();
while (argumentsIterator.hasNext()) {
Expression argument = argumentsIterator.next();
if (argument.equals(absorbingElement)) {
return absorbingElement;
}
if (!argument.equals(neutralElement)) {
arguments.add(argument);
}
}
Expression result = make(functor, arguments, neutralElement, isIdempotent);
return result;
}
use of com.sri.ai.expresso.api.Expression in project aic-expresso by aic-sri-international.
the class CommutativeAssociativeOnNumbers method dealWithInfinity.
/**
* If arguments of expression contain {@link Expressions#INFINITY} but not {@link Expressions#MINUS_INFINITY}, returns INFINITY;
* if they contain {@link Expressions#MINUS_INFINITY} but not {@link Expressions#INFINITY}, returns MINUS_INFINITY;
* if they contain both, throw an error
* if tye contain none, returns the result provided by provided fallback function
* @param expression
* @param context
* @param fallback
* @return
*/
public static Expression dealWithInfinity(Expression expression, Context context, BinaryFunction<Expression, Context, Expression> fallback) {
Expression result;
boolean containsInfinity = thereExists(expression.getArguments(), EQUALS_INFINITY);
boolean containsMinusInfinity = thereExists(expression.getArguments(), EQUALS_MINUS_INFINITY);
if (containsInfinity) {
if (containsMinusInfinity) {
throw new Error(expression.getFunctor() + " undefined for application to both positive and negative infinity: " + expression);
} else {
result = INFINITY;
}
} else {
if (containsMinusInfinity) {
result = MINUS_INFINITY;
} else {
result = fallback.apply(expression, context);
}
}
return result;
}
Aggregations