Connect++ 0.6.0
A fast, readable connection prover for first-order logic.
Loading...
Searching...
No Matches
Term.cpp
1/*
2
3Copyright © 2023-24 Sean Holden. All rights reserved.
4
5*/
6/*
7
8This file is part of Connect++.
9
10Connect++ is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License as published by the
12Free Software Foundation, either version 3 of the License, or (at your
13option) any later version.
14
15Connect++ is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18more details.
19
20You should have received a copy of the GNU General Public License along
21with Connect++. If not, see <https://www.gnu.org/licenses/>.
22
23*/
24
25#include "Term.hpp"
26
27/*
28* Some methods are in TermIndex.cpp to make the dependencies work:
29*
30* make_copy_with_new_vars_helper
31* make_copy_with_new_vars
32*/
33
34//----------------------------------------------------------------------
35Term::Term(Function* new_f, const vector<Term*>& new_args)
36: v(nullptr), f(new_f), args(new_args)
37{
38 if (new_f->get_arity() != new_args.size()) {
39 cerr << "Number of arguments doesn't match function arity" << endl;
40 cerr << "Perhaps your function names are mixed up?" << endl;
41 }
42}
43//----------------------------------------------------------------------
44bool Term::operator==(const Term& t) const {
45 return (v == t.v &&
46 f == t.f &&
47 args == t.args);
48}
49//----------------------------------------------------------------------
50Term* Term::operator[](size_t i) const {
51 if (args.size() == 0) {
52 cerr << "You shouldn't be accessing a term's arguments here." << endl;
53 return nullptr;
54 }
55 return args[i];
56}
57//----------------------------------------------------------------------
58bool Term::is_subbed() const {
59 if (v != nullptr) {
60 return v->is_subbed();
61 }
62 else {
63 for (size_t i = 0; i < args.size(); i++) {
64 if (args[i]->is_subbed()) {
65 return true;
66 }
67 }
68 }
69 return false;
70}
71//----------------------------------------------------------------------
72bool Term::is_ground() const {
73 if (v != nullptr) {
74 return false;
75 }
76 for (Term* t : args) {
77 if (!t->is_ground()) {
78 return false;
79 }
80 }
81 return true;
82}
83//----------------------------------------------------------------------
84bool Term::subbed_equal(Term* t) const {
85 if (this == t) {
86 return true;
87 }
88 Variable* tv = t->v;
89 // LHS is a variable.
90 if (v != nullptr) {
91 if (v->is_subbed()) {
92 return (v->get_subbed_term())->subbed_equal(t);
93 }
94 else if (t->subbed_is_variable()) {
95 return (t->subbed_variable() == v);
96 }
97 else return false;
98 }
99 // RHS is a variable.
100 else if (tv != nullptr) {
101 if (tv->is_subbed()) {
102 return subbed_equal(tv->get_subbed_term());
103 }
104 else return false;
105 }
106 // Both sides are functions.
107 else {
108 if (f != t->f)
109 return false;
110 if (f->get_arity() != t->f->get_arity())
111 return false;
112 for (size_t i = 0; i < f->get_arity(); i++) {
113 if (!(args[i]->subbed_equal(t->args[i])))
114 return false;
115 }
116 return true;
117 }
118}
119//----------------------------------------------------------------------
121 if (v == nullptr)
122 return true;
123 else
124 return v->subbed_is_function();
125}
126//----------------------------------------------------------------------
128 if (v == nullptr)
129 return false;
130 else
131 return v->subbed_is_variable();
132}
133//----------------------------------------------------------------------
135 if (f != nullptr) {
136 cerr << "You shouldn't be using this with a function term." << endl;
137 return nullptr;
138 }
139 else
140 return v->subbed_variable();
141}
142//----------------------------------------------------------------------
144 if (v != nullptr)
145 return v->contains_variable(v2);
146 if (f != nullptr)
147 for (size_t i = 0; i < args.size(); i++)
148 if (args[i]->contains_variable(v2))
149 return true;
150 return false;
151}
152//----------------------------------------------------------------------
154 if (f != nullptr)
155 return f;
156 else
157 return v->get_subbed_f();
158}
159//----------------------------------------------------------------------
161 if (f != nullptr)
162 return f->get_arity();
163 else
164 return v->get_subbed_arity();
165}
166//----------------------------------------------------------------------
167void Term::find_subbed_vars(set<Variable*>& vs) const {
168 if (v != nullptr) {
169 if (v->is_subbed())
171 else
172 vs.insert(v);
173 }
174 else {
175 for (size_t i = 0; i < args.size(); i++)
176 args[i]->find_subbed_vars(vs);
177 }
178}
179//----------------------------------------------------------------------
180string Term::to_string(bool subbed, bool show_addresses) const {
181 string result;
182 if (v != nullptr) {
183 result += v->to_string(subbed);
184 }
185 else if (f != nullptr) {
186 result += f->to_string();
187 if (f->get_arity() > 0) {
188 result += vector_to_string(args, subbed, show_addresses);
189 }
190 }
191 else
192 result += "You're trying to print a badly-formed term.";
193 if (show_addresses) {
194 result += ":";
195 ostringstream oss;
196 oss << this;
197 result += oss.str();
198 }
199 return result;
200}
201//----------------------------------------------------------------------
203 string result;
204 if (v != nullptr) {
205 result += v->get_name();
206 }
207 else if (f != nullptr) {
208 commas::comma com(args.size());
209 result += f->get_name();
210 if (args.size() > 0) {
211 result += "(";
212 for (size_t j = 0; j < args.size(); j++) {
213 result += args[j]->to_prolog_string();
214 result += com();
215 }
216 result += ")";
217 }
218 }
219 return result;
220}
221//----------------------------------------------------------------------
222string Term::make_LaTeX(bool subbed) const {
223 if (v != nullptr) {
224 return v->make_LaTeX(subbed);
225 }
226 string s = f->make_LaTeX();
227 if (args.size() > 0) {
228 s += "(";
229 commas::comma com(args.size());
230 for (size_t j = 0; j < args.size(); j++) {
231 s += args[j]->make_LaTeX(subbed);
232 s += com();
233 }
234 s += ")";
235 }
236 return s;
237}
238//----------------------------------------------------------------------
240 if (v == nullptr)
241 return false;
242 return !(v->is_subbed());
243}
244//----------------------------------------------------------------------
246 if (f == nullptr) {
247 if (v->is_subbed()) {
248 return v->skip_leading_variables();
249 }
250 }
251 Term* p = const_cast<Term*>(this);
252 return p;
253}
254//----------------------------------------------------------------------
256 bool& _subbed_is_var,
257 Variable*& _subbed_v,
258 Function*& _subbed_f,
259 size_t& _subbed_arity) const {
260
261 if (f == nullptr && v == nullptr) {
262 }
263 Term* p = const_cast<Term*>(this);
264 while (p->f == nullptr) {
265 if (p->v->is_subbed()) {
266 p = p->v->get_subbed_term();
267 }
268 else {
269 break;
270 }
271 }
272 if (p->f == nullptr) {
273 _subbed_v = p->v;
274 _subbed_f = nullptr;
275 _subbed_arity = 0;
276 _subbed_is_var = true;
277 }
278 else {
279 _subbed_v = nullptr;
280 _subbed_f = p->f;
281 _subbed_arity = p->f->get_arity();
282 _subbed_is_var = false;
283 }
284 return p;
285}
286//----------------------------------------------------------------------
287set<Term*> Term::all_variables() const {
288 set<Term*> result;
289 if (v != nullptr) {
290 if (v->is_subbed())
291 cerr << "STOP IT!!! You shouldn't be using this with substituted variables!" << endl;
292 Term* p = const_cast<Term*>(this);
293 result.insert(p);
294 }
295 else {
296 for (Term* p : args) {
297 set<Term*> some_vars = p->all_variables();
298 result.insert(some_vars.begin(), some_vars.end());
299 }
300 }
301 return result;
302}
303//----------------------------------------------------------------------
304ostream& operator<<(ostream& out, const Term& t) {
305 out << t.to_string(params::output_terms_with_substitution, true);
306 return out;
307}
308
309
310/*
311* Everything from here on is implementation of methods for
312* Variable.hpp
313*
314* These need to be here to make the dependencies work.
315*/
316
317
318//----------------------------------------------------------------------
319string Variable::to_string(bool subbed) const {
320 colour_string::ColourString cs(params::use_colours);
321 string s = cs(name).lblue();
322 if (subbed && substitution != nullptr) {
323 s += unicode_symbols::LogSym::subbed;
324 s += substitution->to_string(subbed);
325 }
326 return s;
327}
328//----------------------------------------------------------------------
329string Variable::make_LaTeX(bool subbed) const {
330 if (subbed && substitution != nullptr)
331 return substitution->make_LaTeX(subbed);
332 else {
333 string s ("\\text{");
334 s += latex_escape_characters(name);
335 s += "}";
336 return s;
337 }
338}
339//----------------------------------------------------------------------
341 if (substitution == nullptr)
342 return false;
343 else
344 return substitution->subbed_is_function();
345}
346//----------------------------------------------------------------------
348 if (substitution == nullptr)
349 return true;
350 else
351 return substitution->subbed_is_variable();
352}
353//----------------------------------------------------------------------
355 if (substitution == nullptr) {
356 Variable* p = const_cast<Variable*>(this);
357 return p;
358 }
359 else
360 return substitution->subbed_variable();
361}
362//----------------------------------------------------------------------
364 if (substitution == nullptr)
365 return this==v2;
366 else
367 return substitution->contains_variable(v2);
368}
369//----------------------------------------------------------------------
371 if (substitution == nullptr) {
372 cerr << "There is no function name to be found..." << endl;
373 return nullptr;
374 }
375 else
376 return substitution->get_subbed_f();
377}
378//----------------------------------------------------------------------
380 if (substitution == nullptr) {
381 cerr << "There is no arity to be found..." << endl;
382 return 0;
383 }
384 else
385 return substitution->get_subbed_arity();
386}
387//----------------------------------------------------------------------
389 if (substitution != nullptr) {
390 return substitution->skip_leading_variables();
391 }
392 cerr << "Stop it! You're trying to skip something inappropriate!" << endl;
393 return nullptr;
394}
395
Basic representation of functions.
Definition Function.hpp:54
string make_LaTeX() const
Make a useable LaTeX version.
Definition Function.cpp:33
string to_string() const
Make a useable string representation.
Definition Function.cpp:28
Arity get_arity() const
Most basic access function.
Definition Function.hpp:88
string get_name() const
Most basic access function.
Definition Function.hpp:84
General representation of terms.
Definition Term.hpp:62
Function * get_subbed_f() const
Taking substitution into account, what function do we actually have?
Definition Term.cpp:153
bool is_unsubbed_variable() const
Is this a variable that hasn't been substituted?
Definition Term.cpp:239
string make_LaTeX(bool=false) const
Make a useable LaTeX representation.
Definition Term.cpp:222
bool subbed_equal(Term *) const
Equality test, taking substitution into account.
Definition Term.cpp:84
Term * skip_leading_variables() const
It may be that there is a chain of substitutions attached to a variable.
Definition Term.cpp:245
void find_subbed_vars(set< Variable * > &) const
Taking substitution into account, find all the variables in a term.
Definition Term.cpp:167
bool subbed_is_variable() const
Is this term a variable, taking substitution into accoumt?
Definition Term.cpp:127
set< Term * > all_variables() const
Assuming nothing has been substituted, find all the variables in this term.
Definition Term.cpp:287
string to_string(bool=false, bool=false) const
Make a string representation of the Term, taking into account any substitutions that have been made.
Definition Term.cpp:180
Term()
Constructors - these are private as Terms should only ever be constructed by the TermIndex,...
Definition Term.hpp:72
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 is_ground() const
Is the term ground?
Definition Term.cpp:72
Variable * subbed_variable() const
Taking substitution into account, what variable do we actually have?
Definition Term.cpp:134
Arity get_subbed_arity() const
Taking substitution into account, what arity do we actually have?
Definition Term.cpp:160
bool contains_variable(Variable *) const
Taking substitution into account, does the term include the variable passed?
Definition Term.cpp:143
bool operator==(const Term &) const
For the TermIndex you want strict equaliity of the data members.
Definition Term.cpp:44
string to_prolog_string() const
Convert to a string that can be read by Prolog.
Definition Term.cpp:202
bool is_subbed() const
Test whether any variable has been substituted.
Definition Term.cpp:58
Term * operator[](size_t) const
Access to args, but don't mess with them!
Definition Term.cpp:50
bool subbed_is_function() const
Is this term a function, taking substitution into accoumt?
Definition Term.cpp:120
Basic representation of variables.
Definition Variable.hpp:58
Variable * subbed_variable() const
If the variable is unsubbed then return "this"; otherwise a pointer to the variable at the end of a c...
Definition Term.cpp:354
Term * skip_leading_variables() const
It may be that there is a chain of substitutions attached to this variable: skip the leading ones.
Definition Term.cpp:388
bool contains_variable(Variable *) const
Does the substitution turn the variable into something that includes the variable passed?
Definition Term.cpp:363
bool subbed_is_variable() const
Is the variable still in fact a variable, taking substitution into account?
Definition Term.cpp:347
bool is_subbed() const
Is this variable currently substituted?
Definition Variable.hpp:106
Arity get_subbed_arity() const
If there is a chain of substitutions ending in a function, find that function's arity.
Definition Term.cpp:379
Function * get_subbed_f() const
If there is a chain of substitutions ending in a function, find that function.
Definition Term.cpp:370
string to_string(bool=false) const
Convert to a (coloured) string.
Definition Term.cpp:319
bool subbed_is_function() const
Is the variable now a function, taking substitution into account?
Definition Term.cpp:340
string get_name() const
Self-explanatory access function.
Definition Variable.hpp:96
string make_LaTeX(bool=false) const
Convert the Variable to a useable LaTeX representation.
Definition Term.cpp:329
Term * get_subbed_term() const
Get the current substitution, or nullptr.
Definition Variable.hpp:110
Simple addition of colour to strings and ostreams.
Simple function object for putting commas in lists.