Connect++ 0.6.0
A fast, readable connection prover for first-order logic.
Loading...
Searching...
No Matches
Unifier Class Reference

Wrap up various applications of unificiation into a single class: all the unification you need to do happens here. More...

#include <Unifier.hpp>

Collaboration diagram for Unifier:

Public Member Functions

 Unifier ()
 There isn't really much to initialize.
 
 Unifier (const Unifier &)=delete
 You really only need one Unifier!
 
 Unifier (const Unifier &&)=delete
 
Unifieroperator= (const Unifier &)=delete
 
Unifieroperator= (const Unifier &&)=delete
 
Substitution get_substitution () const
 Trivial get methods for the result.
 
UnificationOutcome operator() (Term *, Term *)
 Implementation of unification for a pair of Terms.
 
UnificationOutcome unify (Term *, Term *)
 Implementation of unification for a pair of Terms.
 
UnificationOutcome unify_terms (Term *, Term *)
 Main method implementing the traditional unification algorithm.
 
UnificationOutcome operator() (const vector< Term * > &, const vector< Term * > &)
 The same as the main operator(), but you've already extracted the arguments for the things of interest into lists.
 
UnificationOutcome operator() (Literal *, Literal *)
 Unification of Literals.
 
UnificationOutcome operator() (const Literal &l1, const Literal &l2)
 
void backtrack ()
 Apply the backtracking process to the substitution that has been constructed.
 
string to_string (bool subbed=false) const
 Make a nice string representation.
 

Private Member Functions

UnificationOutcome complete_unification ()
 Implementation of unification: for the polynomial-time approach. All the real work happens here.
 

Private Attributes

Substitution s
 Build the resulting substitution here.
 
vector< UPair > to_do
 Queue used by complete_unification method.
 

Friends

ostream & operator<< (ostream &, const Unifier &)
 

Detailed Description

Wrap up various applications of unificiation into a single class: all the unification you need to do happens here.

You may find yourself unifying Terms, Literals and so on. This puts it all in one place. The class is a function class with various overloaded operator() methods.

All the real work happens in the "complete_unification" and "unify_terms" methods, depending on whether you're using the traditional or polynomial time version.

For the polynomial time version, see the Wikipedia page. This is apparently due to Montelli and Montanari (1982). Looking at "An Efficient Unification Algorithm – yes, indeed it is. The algorithm as stated in the paper is nondeterministic, and apparently you get a bunch of different outcomes depending on the details of the implementation.

So: this one uses a vector, taking something from the end and placing any results on the end as well.

The traditional version is based on Figure 1, page 454, Handbook of Automated Reasoning Volume 1.

Note that some modifications have to be made compared with the original presentations, because the method used to make substitutions takes immediate effect. As a result, for example, substitutions get removed by the Delete rule, so you might as well remove them immediately. Also, when substituting x=? you don't need to check whether x appears in the other equations.

Definition at line 89 of file Unifier.hpp.

Constructor & Destructor Documentation

◆ Unifier() [1/2]

Unifier::Unifier ( )
inline

There isn't really much to initialize.

Definition at line 108 of file Unifier.hpp.

108: s(), to_do() {}
vector< UPair > to_do
Queue used by complete_unification method.
Definition Unifier.hpp:98
Substitution s
Build the resulting substitution here.
Definition Unifier.hpp:94

◆ Unifier() [2/2]

Unifier::Unifier ( const Unifier & )
delete

You really only need one Unifier!

As always, copying is a bad idea so let the compiler help you out.

Member Function Documentation

◆ backtrack()

void Unifier::backtrack ( )

Apply the backtracking process to the substitution that has been constructed.

Definition at line 195 of file Unifier.cpp.

195 {
196 s.backtrack();
197 s.clear();
198}
void backtrack() const
Remove a substitution everywhere.
void clear()
Clear a substitution.

◆ complete_unification()

UnificationOutcome Unifier::complete_unification ( )
private

Implementation of unification: for the polynomial-time approach. All the real work happens here.

Definition at line 127 of file Unifier.cpp.

127 {
128 s.clear();
129 while (to_do.size() > 0) {
130 // Get the next thing from the queue and split it up.
131 UPair upair(to_do.back());
132 Term* t1(upair.first);
133 Term* t2(upair.second);
134 to_do.pop_back();
135
136 bool t1_is_var;
137 Variable* t1v;
138 Function* t1f;
139 size_t t1a;
140 t1 = t1->skip_leading_variables_for_unification(t1_is_var, t1v, t1f, t1a);
141
142 bool t2_is_var;
143 Variable* t2v;
144 Function* t2f;
145 size_t t2a;
146 t2 = t2->skip_leading_variables_for_unification(t2_is_var, t2v, t2f, t2a);
147
148 // Swap
149 if (!t1_is_var && t2_is_var) {
150 to_do.push_back(UPair(t2, t1));
151 continue;
152 }
153
154 // Delete
155 if (t1->subbed_equal(t2)) {
156 continue;
157 }
158
159 // Decompose/Conflict
160 if (!t1_is_var && !t2_is_var) {
161 // Conflict
162 if ((t1f != t2f) ||
163 (t1a != t2a)) {
164 backtrack();
165 return UnificationOutcome::ConflictFail;
166 }
167 // Decompose
168 else {
169 size_t n_args = t1->arity();
170 for (size_t i = 0; i < n_args; i++) {
171 to_do.push_back(UPair((*t1)[i], (*t2)[i]));
172 }
173 continue;
174 }
175 }
176
177 bool contains = t2->contains_variable(t1v);
178
179 // Eliminate
180 if (t1_is_var && !contains) {
181 s.push_back(t1v, t2);
182 t1v->substitute(t2);
183 continue;
184 }
185
186 // Occurs
187 if (t1_is_var && !t2_is_var && contains) {
188 backtrack();
189 return UnificationOutcome::OccursFail;
190 }
191 }
192 return UnificationOutcome::Succeed;
193}
Basic representation of functions.
Definition Function.hpp:54
void push_back(Variable *, Term *)
Add a pair to a substitution.
General representation of terms.
Definition Term.hpp:62
void backtrack()
Apply the backtracking process to the substitution that has been constructed.
Definition Unifier.cpp:195
Basic representation of variables.
Definition Variable.hpp:58
void substitute(Term *t)
Self-explanatory, but be careful!
Definition Variable.hpp:129

◆ get_substitution()

Substitution Unifier::get_substitution ( ) const
inline

Trivial get methods for the result.

Definition at line 122 of file Unifier.hpp.

122{ return s; }

◆ operator()() [1/4]

UnificationOutcome Unifier::operator() ( const Literal & l1,
const Literal & l2 )
inline

Unification of Literals.

This is the version that is used most of the time, so there is an attempt here to optimize it.

Parameters
l1Reference to first Literal
l2Reference to second Literal

Definition at line 168 of file Unifier.hpp.

168 {
169 if (params::poly_unification) {
170 to_do.clear();
171 size_t s = l1.get_arity();
172 for (size_t i = 0; i < s; i++) {
173 to_do.push_back(UPair(l1[i], l2[i]));
174 }
175 return complete_unification();
176 }
177 else {
178 auto i = l1.get_args().begin();
179 for (Term* term1 : l2.get_args()) {
180 UnificationOutcome outcome = unify_terms(term1, *i);
181 if (outcome != UnificationOutcome::Succeed) {
182 backtrack();
183 return outcome;
184 }
185 i++;
186 }
187 return UnificationOutcome::Succeed;
188 }
189 }
const vector< Term * > & get_args() const
Basic get method.
Definition Literal.hpp:83
Arity get_arity() const
Basic get method.
Definition Literal.hpp:75
UnificationOutcome unify_terms(Term *, Term *)
Main method implementing the traditional unification algorithm.
Definition Unifier.cpp:48
UnificationOutcome complete_unification()
Implementation of unification: for the polynomial-time approach. All the real work happens here.
Definition Unifier.cpp:127

◆ operator()() [2/4]

UnificationOutcome Unifier::operator() ( const vector< Term * > & t1s,
const vector< Term * > & t2s )

The same as the main operator(), but you've already extracted the arguments for the things of interest into lists.

Parameters
t1sReference to vector of pointers to Terms
t2sReference to vector of pointers to Terms

Definition at line 88 of file Unifier.cpp.

89 {
90 if (t1s.size() != t2s.size())
91 return UnificationOutcome::ConflictFail;
92 if (params::poly_unification) {
93 to_do.clear();
94 auto i = t2s.begin();
95 for (Term* term1 : t1s) {
96 to_do.push_back(UPair(term1, *i));
97 i++;
98 }
99 return complete_unification();
100 }
101 else {
102 auto i = t2s.begin();
103 for (Term* term1 : t1s) {
104 UnificationOutcome outcome = unify_terms(term1, *i);
105 if (outcome != UnificationOutcome::Succeed) {
106 backtrack();
107 return outcome;
108 }
109 i++;
110 }
111 return UnificationOutcome::Succeed;
112 }
113}

◆ operator()() [3/4]

UnificationOutcome Unifier::operator() ( Literal * l1,
Literal * l2 )

Unification of Literals.

Parameters
l1Pointer to first Literal
l2Pointer to second Literal

Definition at line 115 of file Unifier.cpp.

115 {
116 if (!l1->is_compatible_with(l2)) {
117 cerr << "ERROR" << ": ";
118 cerr << "You're trying to unify non-compatible literals." << endl;
119 cerr << "ERROR" << ": " << *l1 << endl;
120 cerr << "ERROR" << ": " << *l2 << endl;
121 }
122 const vector<Term*>& args1 = l1->get_args();
123 const vector<Term*>& args2 = l2->get_args();
124 return operator()(args1, args2);
125}
bool is_compatible_with(const Literal *) const
Literals can only be unified if the polarity and actual predicate are the same.
Definition Literal.cpp:74
UnificationOutcome operator()(Term *, Term *)
Implementation of unification for a pair of Terms.
Definition Unifier.cpp:27

◆ operator()() [4/4]

UnificationOutcome Unifier::operator() ( Term * term1,
Term * term2 )

Implementation of unification for a pair of Terms.

Parameters
term1Pointer to first term
term2Pointer to second term

Definition at line 27 of file Unifier.cpp.

27 {
28 if (params::poly_unification) {
29 to_do.clear();
30 to_do.push_back(UPair(term1, term2));
31 return complete_unification();
32 }
33 else {
34 return unify_terms(term1, term2);
35 }
36}

◆ to_string()

string Unifier::to_string ( bool subbed = false) const
inline

Make a nice string representation.

Parameters
subbedUse substitutions if true.

Definition at line 200 of file Unifier.hpp.

200 {
201 return s.to_string(subbed);
202 }
string to_string(bool=false) const
Make a string representation.

◆ unify()

UnificationOutcome Unifier::unify ( Term * t1,
Term * t2 )

Implementation of unification for a pair of Terms.

Parameters
term1Pointer to first term
term2Pointer to second term

Definition at line 38 of file Unifier.cpp.

38 {
39 UnificationOutcome outcome = unify_terms(t1, t2);
40 if (outcome != UnificationOutcome::Succeed) {
41 backtrack();
42 }
43 return outcome;
44}

◆ unify_terms()

UnificationOutcome Unifier::unify_terms ( Term * t1,
Term * t2 )

Main method implementing the traditional unification algorithm.

Definition at line 48 of file Unifier.cpp.

48 {
49 bool t1_is_var;
50 Variable* t1v;
51 Function* t1f;
52 size_t t1a;
53 t1 = t1->skip_leading_variables_for_unification(t1_is_var, t1v, t1f, t1a);
54
55 bool t2_is_var;
56 Variable* t2v;
57 Function* t2f;
58 size_t t2a;
59 t2 = t2->skip_leading_variables_for_unification(t2_is_var, t2v, t2f, t2a);
60
61 if (t1_is_var && t1v == t2v) {}
62 else if (!t1_is_var && !t2_is_var) {
63 if (t1f == t2f && t1a == t2a) {
64 for (size_t i = 0; i < t1a; i++) {
65 UnificationOutcome outcome = unify_terms((*t1)[i], (*t2)[i]);
66 if (outcome != UnificationOutcome::Succeed) {
67 return outcome;
68 }
69 }
70 }
71 else {
72 return UnificationOutcome::ConflictFail;
73 }
74 }
75 else if (!t1_is_var) {
76 return unify_terms(t2, t1);
77 }
78 else if (t2->contains_variable(t1v)) {
79 return UnificationOutcome::OccursFail;
80 }
81 else {
82 s.push_back(t1v, t2);
83 t1v->substitute(t2);
84 }
85 return UnificationOutcome::Succeed;
86}
Term * skip_leading_variables_for_unification(bool &, Variable *&, Function *&, size_t &) const
It may be that there is a chain of substitutions attached to a variable.
Definition Term.cpp:255
bool contains_variable(Variable *) const
Taking substitution into account, does the term include the variable passed?
Definition Term.cpp:143

Friends And Related Symbol Documentation

◆ operator<<

ostream & operator<< ( ostream & out,
const Unifier & u )
friend

Definition at line 218 of file Unifier.cpp.

218 {
219 out << u.to_string();
220 return out;
221}
string to_string(bool subbed=false) const
Make a nice string representation.
Definition Unifier.hpp:200

Member Data Documentation

◆ s

Substitution Unifier::s
private

Build the resulting substitution here.

Definition at line 94 of file Unifier.hpp.

◆ to_do

vector<UPair> Unifier::to_do
private

Queue used by complete_unification method.

Definition at line 98 of file Unifier.hpp.


The documentation for this class was generated from the following files: