Completed implementing simplification with deep variable replacement.
This commit is contained in:
parent
42e0217409
commit
cae0948763
@ -107,6 +107,75 @@ struct RecursiveFormulaVisitor
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct RecursiveTermVisitor
|
||||||
|
{
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::BinaryOperation &binaryOperation, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
binaryOperation.left.accept(*this, binaryOperation.left, std::forward<Arguments>(arguments)...);
|
||||||
|
binaryOperation.right.accept(*this, binaryOperation.left, std::forward<Arguments>(arguments)...);
|
||||||
|
|
||||||
|
return T::accept(binaryOperation, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::Boolean &boolean, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
return T::accept(boolean, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::Constant &constant, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
return T::accept(constant, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::Function &function, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
for (auto &argument : function.arguments)
|
||||||
|
argument.accept(*this, argument, std::forward<Arguments>(arguments)...);
|
||||||
|
|
||||||
|
return T::accept(function, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::Integer &integer, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
return T::accept(integer, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::Interval &interval, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
interval.from.accept(*this, interval.from, std::forward<Arguments>(arguments)...);
|
||||||
|
interval.to.accept(*this, interval.to, std::forward<Arguments>(arguments)...);
|
||||||
|
|
||||||
|
return T::accept(interval, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::SpecialInteger &specialInteger, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
return T::accept(specialInteger, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::String &string, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
return T::accept(string, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Arguments>
|
||||||
|
void visit(ast::Variable &variable, ast::Term &term, Arguments &&... arguments)
|
||||||
|
{
|
||||||
|
return T::accept(variable, term, std::forward<Arguments>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,42 +57,48 @@ std::experimental::optional<ast::Term> extractAssignedTerm(ast::Formula &formula
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Replaces all occurrences of a variable with a term in a given formula
|
// Replaces all occurrences of a variable in a given term with another term
|
||||||
struct ReplaceVariableWithTermVisitor : public ast::RecursiveFormulaVisitor<ReplaceVariableWithTermVisitor>
|
struct ReplaceVariableInTermVisitor : public ast::RecursiveTermVisitor<ReplaceVariableInTermVisitor>
|
||||||
{
|
{
|
||||||
static void accept(ast::Comparison &comparison, ast::Formula &, const ast::Variable &variable, ast::Term &term)
|
static void accept(ast::Variable &variable, ast::Term &term, const ast::Variable &variableToReplace, const ast::Term &replacementTerm)
|
||||||
{
|
{
|
||||||
if (matchesVariable(comparison.left, variable))
|
if (variable.name == variableToReplace.name)
|
||||||
comparison.left = ast::deepCopy(term);
|
term = ast::deepCopy(replacementTerm);
|
||||||
|
|
||||||
if (matchesVariable(comparison.right, variable))
|
|
||||||
comparison.right = ast::deepCopy(term);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accept(ast::In &in, ast::Formula &, const ast::Variable &variable, ast::Term &term)
|
|
||||||
{
|
|
||||||
if (matchesVariable(in.element, variable))
|
|
||||||
in.element = ast::deepCopy(term);
|
|
||||||
|
|
||||||
if (matchesVariable(in.set, variable))
|
|
||||||
in.set = ast::deepCopy(term);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accept(ast::Predicate &predicate, ast::Formula &, const ast::Variable &variable, ast::Term &term)
|
|
||||||
{
|
|
||||||
for (auto &argument : predicate.arguments)
|
|
||||||
{
|
|
||||||
if (!matchesVariable(argument, variable))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// TODO: optimize (one less deep copy possible)
|
|
||||||
argument = ast::deepCopy(term);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore all other types of expressions
|
// Ignore all other types of expressions
|
||||||
template<class T>
|
template<class T>
|
||||||
static void accept(T &, ast::Formula &, const ast::Variable &, ast::Term &)
|
static void accept(T &, ast::Term &, const ast::Variable &, const ast::Term &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Replaces all occurrences of a variable in a given formula with a term
|
||||||
|
struct ReplaceVariableInFormulaVisitor : public ast::RecursiveFormulaVisitor<ReplaceVariableInFormulaVisitor>
|
||||||
|
{
|
||||||
|
static void accept(ast::Comparison &comparison, ast::Formula &, const ast::Variable &variable, const ast::Term &term)
|
||||||
|
{
|
||||||
|
comparison.left.accept(ReplaceVariableInTermVisitor(), comparison.left, variable, term);
|
||||||
|
comparison.right.accept(ReplaceVariableInTermVisitor(), comparison.left, variable, term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accept(ast::In &in, ast::Formula &, const ast::Variable &variable, const ast::Term &term)
|
||||||
|
{
|
||||||
|
in.element.accept(ReplaceVariableInTermVisitor(), in.element, variable, term);
|
||||||
|
in.set.accept(ReplaceVariableInTermVisitor(), in.set, variable, term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accept(ast::Predicate &predicate, ast::Formula &, const ast::Variable &variable, const ast::Term &term)
|
||||||
|
{
|
||||||
|
for (auto &argument : predicate.arguments)
|
||||||
|
argument.accept(ReplaceVariableInTermVisitor(), argument, variable, term);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore all other types of expressions
|
||||||
|
template<class T>
|
||||||
|
static void accept(T &, ast::Formula &, const ast::Variable &, const ast::Term &)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -116,6 +122,7 @@ void simplify(ast::Exists &exists, ast::Formula &formula)
|
|||||||
|
|
||||||
bool wasVariableReplaced = false;
|
bool wasVariableReplaced = false;
|
||||||
|
|
||||||
|
// TODO: refactor
|
||||||
for (auto j = arguments.begin(); j != arguments.end(); j++)
|
for (auto j = arguments.begin(); j != arguments.end(); j++)
|
||||||
{
|
{
|
||||||
auto &argument = *j;
|
auto &argument = *j;
|
||||||
@ -126,8 +133,14 @@ void simplify(ast::Exists &exists, ast::Formula &formula)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Replace all occurrences of the variable with the equivalent term
|
// Replace all occurrences of the variable with the equivalent term
|
||||||
for (auto &otherArgument : arguments)
|
for (auto k = arguments.begin(); k != arguments.end(); k++)
|
||||||
otherArgument.accept(ReplaceVariableWithTermVisitor(), otherArgument, variable, assignedTerm.value());
|
{
|
||||||
|
if (k == j)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto &otherArgument = *k;
|
||||||
|
otherArgument.accept(ReplaceVariableInFormulaVisitor(), otherArgument, variable, assignedTerm.value());
|
||||||
|
}
|
||||||
|
|
||||||
arguments.erase(j);
|
arguments.erase(j);
|
||||||
wasVariableReplaced = true;
|
wasVariableReplaced = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user