3 #include <utils/printer.h>
4 #include <state/statePattern.h>
5 #include <utils/messageException.h>
20 template <
typename NodeType>
23 std::shared_ptr<const MConfiguration<NodeType>>,
24 std::map<NodeType, std::shared_ptr<const MConfiguration<NodeType>>>
30 typedef std::map<NodeType, std::shared_ptr<const MConfiguration<NodeType>>>
Unification;
32 typedef std::shared_ptr<const MConfiguration<NodeType>> StateType_;
48 static_assert(std::is_same_v<StateType, StateType_>);
51 static_assert(std::is_same_v<MatcherType, Unification>);
132 constexpr std::shared_ptr<const MConfiguration<NodeType>>
getArg(
size_t)
const;
246 std::optional<MatcherType>
match(
const StateType& state)
const noexcept
override final;
270 template<
typename CharT =
char,
typename Traits = std::
char_traits<CharT>,
typename Alloc = std::allocator<CharT>>
271 std::basic_string<CharT, Traits, Alloc>
toString()
const;
321 template <
typename CharT =
char,
typename Traits = std::
char_traits<CharT>>
322 std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)>
debug()
const;
330 template <
typename CharT =
char,
typename Traits = std::
char_traits<CharT>>
331 static std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)>
debug(
const Unification& unification);
339 template <
typename CharT =
char,
typename Traits = std::
char_traits<CharT>>
340 static std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)>
debug(
const AlphaRewriting& rewriting);
348 template <
typename CharT =
char,
typename Traits = std::
char_traits<CharT>>
349 static std::function<std::basic_ostream<CharT, Traits>&(std::basic_ostream<CharT, Traits>&)>
debug(
const AlphaRelation& relation);
361 template <
typename U,
typename CharT,
typename Traits> constexpr
friend std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const MConfiguration<U>& m_conf) {
362 if(m_conf.
args.empty()) {
363 os << (m_conf.
isVar ?
"_" :
"") << m_conf.
node;
367 os << m_conf.
node <<
"(";
369 for(
size_t i = 0; i < m_conf.
args.size(); ++i) {
376 os << *m_conf.
args[i];
395 std::vector<std::shared_ptr<const MConfiguration<NodeType>>>
args;
406 template <
typename NodeType>
433 using Utils::Debug::operator<<;
434 std::ostringstream ss;
435 ss << this->
msg << std::endl;
436 ss <<
" pattern: " <<
pattern.debug() << std::endl;
437 ss <<
" state: " <<
state.debug() << std::endl;
459 template <
typename NodeType>
489 using Utils::Debug::operator<<;
490 std::ostringstream ss;
491 ss << this->
msg << std::endl;
492 ss <<
" lhs: " <<
lhs.debug() << std::endl;
493 ss <<
" rhs: " <<
rhs.debug() << std::endl;
520 template <
typename NodeType>
525 args(std::vector<std::shared_ptr<const
MConfiguration<NodeType>>>()),
529 template <
typename NodeType>
534 args(std::vector<std::shared_ptr<const
MConfiguration<NodeType>>>()),
535 is_pattern(isVariable)
538 template <
typename NodeType>
544 is_pattern(std::accumulate(subTrees.begin(), subTrees.end(), false, [](bool acc, const
MConfiguration<NodeType>& b) -> bool {
return acc || b.is_pattern; }))
551 template <
typename NodeType>
557 is_pattern(std::accumulate(subTrees.begin(), subTrees.end(), false, [](bool acc, const
MConfiguration<NodeType>& b) -> bool {
return acc || b.
is_pattern; }))
564 template <
typename NodeType>
570 is_pattern(std::accumulate(subTrees.begin(), subTrees.end(), false, [](bool acc, const std::shared_ptr<const
MConfiguration<NodeType>>& b) -> bool {
return acc || b->
is_pattern; }))
573 template <
typename NodeType>
578 args(std::move(subTrees)),
579 is_pattern(std::accumulate(subTrees.begin(), subTrees.end(), false, [](bool acc, const std::shared_ptr<const
MConfiguration<NodeType>>& b) -> bool {
return acc || b->
is_pattern; }))
582 template <
typename NodeType>
588 is_pattern(other.is_pattern)
591 template <
typename NodeType>
594 node(std::move(other.node)),
596 args(std::move(other.args)),
597 is_pattern(other.is_pattern)
600 template <
typename NodeType>
603 StatePattern_::operator=(other);
612 template <
typename NodeType>
615 StatePattern_::operator=(std::move(other));
616 node = std::move(other.node);
618 args = std::move(other.args);
619 is_pattern = other.is_pattern;
624 template <
typename NodeType>
629 template <
typename NodeType>
634 template <
typename NodeType>
639 template <
typename NodeType>
644 template <
typename NodeType>
649 template <
typename NodeType>
654 template <
typename NodeType>
659 template <
typename NodeType>
661 if(pattern->isLeaf() && pattern->isVariable()) {
662 if(subs.count(pattern->node))
663 return subs.at(pattern->node);
668 std::vector<std::shared_ptr<const MConfiguration<NodeType>>> outputArgs;
671 if(arg->is_pattern) {
672 outputArgs.push_back(applySubstitution(arg, subs));
675 outputArgs.push_back(arg);
679 return std::make_shared<const MConfiguration<NodeType>>(pattern->node, std::move(outputArgs));
682 template <
typename NodeType>
684 if(pattern->isLeaf() && pattern->isVariable()) {
685 if(subs.count(pattern->node))
686 return subs.at(pattern->node);
691 std::vector<std::shared_ptr<const MConfiguration<NodeType>>> outputArgs;
694 if(arg->is_pattern) {
695 outputArgs.push_back(applySubstitution(arg, subs, def));
698 outputArgs.push_back(arg);
702 return std::make_shared<const MConfiguration<NodeType>>(pattern->node, std::move(outputArgs));
705 template <
typename NodeType>
707 std::function<NoUnificationException<NodeType>(
const std::string&)> make_exception =
708 [&state, &pattern, &unification = std::as_const(unification)](
const std::string& message) {
712 if(pattern.isLeaf()) {
713 if(pattern.isVariable()) {
714 NodeType node = pattern.getNode();
715 typename std::map<NodeType, std::shared_ptr<const MConfiguration<NodeType>>>::const_iterator it = unification.find(node);
716 if(it == unification.end()) {
717 unification.insert({node, state});
719 else if(*it->second != *state) {
720 std::ostringstream ss;
721 ss <<
"Unable to unify: incompatible variables. At node " << node <<
"." << std::endl
722 <<
" Known unification: " << it->second;
723 throw make_exception(ss.str());
729 else if(pattern.getNode() == state->getNode())
732 std::ostringstream ss;
733 ss <<
"Unable to unify: incompatible leaves: " << state->getNode() <<
"(state) vs " << pattern.getNode() <<
"(pattern)";
734 throw make_exception(ss.str());
737 if(state->getArity() != pattern.getArity()) {
738 std::ostringstream ss;
739 ss <<
"Unable to unify: arities does not match: "
740 << state->getArity() <<
"(state) vs "
741 << pattern.getArity() <<
"(pattern)";
742 throw make_exception(ss.str());
744 if(state->getNode() != pattern.getNode()) {
745 std::ostringstream ss;
746 ss <<
"Unable to unify: m-function name does not match: " << state->getNode() <<
"(state) vs "
747 << pattern.getNode() <<
"(pattern)";
748 throw make_exception(ss.str());
750 size_t args_size = state->getArity();
751 for(
size_t i=0; i < args_size; ++i) {
752 unify_state(state->args[i], *pattern.args[i], unification);
757 template <
typename NodeType>
759 std::function<NoUnificationException<NodeType>(
const std::string&)> make_exception =
760 [&state, &pattern](
const std::string& message) {
761 using Utils::Debug::operator<<;
762 std::ostringstream ss;
763 ss << message << std::endl;
764 ss <<
" state: " << state->
debug() << std::endl;
765 ss <<
" pattern: " << pattern.
debug() << std::endl;
769 if(state->isPattern()) {
770 throw make_exception(
"first argument of unify_state must not be a pattern.");
772 std::map<NodeType, std::shared_ptr<const MConfiguration<NodeType>>> unification;
773 unify_state(state, pattern, unification);
777 template <
typename NodeType>
779 return unify_state(state, *
this);
782 template <
typename NodeType>
784 std::function<NoUnificationException<NodeType>(
const std::string&)> make_exception =
785 [
this, &other](
const std::string& message) {
790 if(other->isMFunction()) {
791 return unifyWithMConf(other);
793 throw make_exception(
"Two patterns in MConfiguration<T>::unify");
796 throw make_exception(
"'this' should be a pattern for MConfiguration<T>::unify");
800 template <
typename NodeType>
803 return std::make_optional(unify_state(m_conf, *
this));
810 template <
typename NodeType>
812 return unifyWithMConf_opt(state);
815 template <
typename NodeType>
817 std::function<NoUnificationException<NodeType>(
const std::string&)> make_exception =
818 [
this, &state](
const std::string& message) {
823 if(state->isMFunction()) {
824 return unifyWithMConf_opt(state);
826 throw make_exception(
"Two patterns in MConfiguration<T>::unify");
829 throw make_exception(
"'this' should be a pattern for MConfiguration<T>::unify_opt");
833 template <
typename NodeType>
834 template <
typename CharT,
typename Traits,
typename Alloc>
836 std::basic_ostringstream<CharT, Traits, Alloc> ss;
841 template <
typename NodeType>
843 if(node != other.
node) {
845 if(node < other.
node) {
851 if(isVar != other.
isVar) {
853 if(isVar < other.
isVar) {
859 if(args.size() != other.
args.size()) {
861 if(args.size() < other.
args.size()) {
867 const size_t args_size = args.size();
869 for(
size_t i = 0; i < args_size; ++i) {
881 template <
typename NodeType>
883 return compare(other) != 0;
886 template <
typename NodeType>
888 return compare(other) == 0;
891 template<
typename NodeType>
893 return compare(other) < 0;
896 template <
typename NodeType>
900 isAlphaEquivalent(other, direct, back);
905 return {{direct, back}};
908 template <
typename NodeType>
910 std::function<NoAlphaEquivalenceException<NodeType>(
const std::string&)> make_exception =
911 [
this, &other, &direct = std::as_const(direct), &back = std::as_const(back)](
const std::string& message) {
914 if(isVar != other->isVar) {
915 throw make_exception(
"One variable and one constant node");
918 if(node != other->node) {
919 throw make_exception(
"Two unequal nodes");
921 if(args.size() != other->args.size()) {
922 throw make_exception(
"Two nodes with unequal arity");
925 const size_t args_size = args.size();
926 for(
size_t i = 0; i < args_size; ++i) {
927 args[i]->isAlphaEquivalent(other->args[i], direct, back);
931 if(direct.count(node) > 0 && back.count(other->node) == 0) {
932 throw make_exception(
"Left node does not point to right node");
934 else if(direct.count(node) == 0 && back.count(other->node) > 0) {
935 throw make_exception(
"Right node does not point to left node");
937 else if(direct.count(node) == 0 && back.count(other->node) == 0) {
938 direct[node] = other->node;
939 back[other->node] = node;
941 else if(direct[node] != other->node || back[other->node] != node) {
942 throw make_exception(
"Incompatible relation");
951 template <
typename NodeType>
952 template <
typename CharT,
typename Traits>
954 return [
this](std::basic_ostream<CharT, Traits>& out) -> std::basic_ostream<CharT, Traits>& {
956 out << std::string(isVar ?
"_" :
"") << node;
960 out <<
"{" << node <<
"}(";
961 for (
size_t i = 0; i < args.size() - 1; ++i)
962 out <<
"{" << *args[i] <<
"}, ";
963 out <<
"{" << *args.back() <<
"})";
968 template<
typename NodeType>
969 template <
typename CharT,
typename Traits>
974 template<
typename NodeType>
975 template <
typename CharT,
typename Traits>
980 template<
typename NodeType>
981 template <
typename CharT,
typename Traits>