![JAR search and dependency download from the Maven repository](/logo.png)
com.sri.ai.grinder.sgdpllt.library.SyntacticSubstitute Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aic-expresso Show documentation
Show all versions of aic-expresso Show documentation
SRI International's AIC Symbolic Manipulation and Evaluation Library (for Java 1.8+)
The newest version!
/*
* Copyright (c) 2013, SRI International
* All rights reserved.
* Licensed under the The BSD 3-Clause License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://opensource.org/licenses/BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the aic-expresso nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.sri.ai.grinder.sgdpllt.library;
import static com.sri.ai.util.Util.mapIntoList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.sri.ai.expresso.api.Expression;
import com.sri.ai.expresso.helper.Expressions;
import com.sri.ai.expresso.helper.GetFunctorOrSymbol;
import com.sri.ai.expresso.helper.MapReplacementFunction;
import com.sri.ai.grinder.api.Registry;
import com.sri.ai.grinder.core.PruningPredicate;
import com.sri.ai.grinder.sgdpllt.api.Context;
import com.sri.ai.util.Util;
import com.sri.ai.util.base.ReplaceByIfEqualTo;
/**
* A class providing a static method for substituting symbols or function applications in an expression
* by another expression (not subject itself to the same substitution, which would either not occur or lead to an infinite recursion).
*
* This is a simpler, less exhaustive version of {@link SemanticSubstitute} that takes into account only syntactic information,
* that is, it only replaces an expression by a value if the expression is represented with the same symbols
* as the originally searched ones. Here are a few examples to make this more clear:
*
* Replacing a symbol works as one would expect:
*
* Replacing X
by 99 in foo
returns foo
* Replacing X
by 99 in X
returns 99
*
* However, quantifications need to be taken into account:
* replacing X
by 99 in X + if there exists X : X = 9 then X else 0
returns 99 + if there exists X : X = 9 then 99 else 0
* because the quantified X works as a distinct variable. Its scope is limited to the if's condition,
* so the X in the then branch corresponds to the original X.
*
* When replacing a function substitution, the function's corresponding "cell" has its value replaced.
* Here are some examples:
*
* Replacing f(10)
by 99 in f(9)
returns f(9)
* Replacing f(Y)
by 99 in f(Y)
returns 99
* Replacing f(10)
by 99 in f(X)
returns f(X)
* even though, semantically speaking, X
could be equal to 10
.
* Semantic substitution would have returned if X = 10 then 99 else f(X)
* Replacing f(Y)
by 99 in f(X)
returns if X = Y then 99 else f(X)
*
* When replacing a function application, quantification of either the function symbol or the arguments will prevent
* further replacement down the expression:
*
* Replacing f(X)
by 99 in f(X) + (for all g : g(f(X))) + (for all f : f(X)) + (for all X : f(X))
* returns 99 + (for all g : g(99)) + (for all f : f(X)) + (for all X : f(X))
*
* @author braz
*
*/
@Beta
public class SyntacticSubstitute {
public static Expression replace(Expression expression, Expression replaced, Expression replacement, Context context) {
Expression result =
expression.replaceAllOccurrences(
new ReplaceByIfEqualTo(replacement, replaced), null,
new SubstitutePruningPredicate(replaced, replacement, context), null,
context);
return result;
}
public static Expression replaceAll(Expression expression, Map fromReplacedToReplacements, Context context) {
Expression result = expression.replaceAllOccurrences(new MapReplacementFunction(fromReplacedToReplacements), context);
return result;
// // Used to be as below but that is incorrect as one of the new variables may be replaced by another new variable coming later.
// for (Map.Entry entry : fromReplacedToReplacements.entrySet()) {
// expression = replace(expression, entry.getKey(), entry.getValue(), context);
// }
// return expression;
}
private static class SubstitutePruningPredicate implements PruningPredicate {
List allSymbolsInReplacedAndReplacement;
public SubstitutePruningPredicate(Expression replaced, Expression replacement, Registry registry) {
Set freeSymbolsInReplaced = Expressions.freeSymbols(replaced, registry);
Set freeSymbolsInReplacement = Expressions.freeSymbols(replacement, registry);
this.allSymbolsInReplacedAndReplacement =
Util.union(
freeSymbolsInReplacement,
freeSymbolsInReplaced);
}
@Override
public boolean apply(Expression expression, Function replacementFunctionFunction, Registry registry) {
List locallyScopedSymbols = mapIntoList(expression.getScopedExpressions(registry), new GetFunctorOrSymbol());
boolean result = Util.intersect(allSymbolsInReplacedAndReplacement, locallyScopedSymbols);
return result;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy