Connect++ 0.4.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::subbed_equal(Term* t) const {
73 Variable* tv = t->v;
74 // LHS is a variable.
75 if (v != nullptr) {
76 if (v->is_subbed()) {
77 return (v->get_subbed_term())->subbed_equal(t);
78 }
79 else if (t->subbed_is_variable()) {
80 return (t->subbed_variable() == v);
81 }
82 else return false;
83 }
84 // RHS is a variable.
85 else if (tv != nullptr) {
86 if (tv->is_subbed()) {
87 return subbed_equal(tv->get_subbed_term());
88 }
89 else return false;
90 }
91 // Both sides are functions.
92 else {
93 if (f != t->f)
94 return false;
95 if (f->get_arity() != t->f->get_arity())
96 return false;
97 for (size_t i = 0; i < f->get_arity(); i++) {
98 if (!(args[i]->subbed_equal(t->args[i])))
99 return false;
100 }
101 return true;
102 }
103}
104//----------------------------------------------------------------------
106 if (v == nullptr)
107 return true;
108 else
109 return v->subbed_is_function();
110}
111//----------------------------------------------------------------------
113 if (v == nullptr)
114 return false;
115 else
116 return v->subbed_is_variable();
117}
118//----------------------------------------------------------------------
120 if (f != nullptr) {
121 cerr << "You shouldn't be using this with a function term." << endl;
122 return nullptr;
123 }
124 else
125 return v->subbed_variable();
126}
127//----------------------------------------------------------------------
129 if (v != nullptr)
130 return v->contains_variable(v2);
131 if (f != nullptr)
132 for (size_t i = 0; i < args.size(); i++)
133 if (args[i]->contains_variable(v2))
134 return true;
135 return false;
136}
137//----------------------------------------------------------------------
139 if (f != nullptr)
140 return f;
141 else
142 return v->get_subbed_f();
143}
144//----------------------------------------------------------------------
146 if (f != nullptr)
147 return f->get_arity();
148 else
149 return v->get_subbed_arity();
150}
151//----------------------------------------------------------------------
152void Term::find_subbed_vars(set<Variable*>& vs) const {
153 if (v != nullptr) {
154 if (v->is_subbed())
156 else
157 vs.insert(v);
158 }
159 else {
160 for (size_t i = 0; i < args.size(); i++)
161 args[i]->find_subbed_vars(vs);
162 }
163}
164//----------------------------------------------------------------------
165string Term::to_string(bool subbed, bool show_addresses) const {
166 string result;
167 if (v != nullptr) {
168 result += v->to_string(subbed);
169 }
170 else if (f != nullptr) {
171 commas::comma com(args.size());
172 result += f->to_string();
173 result += "(";
174 for (size_t j = 0; j < args.size(); j++) {
175 result += args[j]->to_string(subbed, show_addresses);
176 result += com();
177 }
178 result += ")";
179 }
180 else
181 result += "You're trying to print a badly-formed term.";
182 if (show_addresses) {
183 result += ":";
184 ostringstream oss;
185 oss << this;
186 result += oss.str();
187 }
188 return result;
189}
190//----------------------------------------------------------------------
192 string result;
193 if (v != nullptr) {
194 result += v->get_name();
195 }
196 else if (f != nullptr) {
197 commas::comma com(args.size());
198 result += f->get_name();
199 if (args.size() > 0) {
200 result += "(";
201 for (size_t j = 0; j < args.size(); j++) {
202 result += args[j]->to_prolog_string();
203 result += com();
204 }
205 result += ")";
206 }
207 }
208 return result;
209}
210//----------------------------------------------------------------------
211string Term::make_LaTeX(bool subbed) const {
212 if (v != nullptr) {
213 return v->make_LaTeX(subbed);
214 }
215 string s = f->make_LaTeX();
216 if (args.size() > 0) {
217 s += "(";
218 commas::comma com(args.size());
219 for (size_t j = 0; j < args.size(); j++) {
220 s += args[j]->make_LaTeX(subbed);
221 s += com();
222 }
223 s += ")";
224 }
225 return s;
226}
227//----------------------------------------------------------------------
229 if (v == nullptr)
230 return false;
231 return !(v->is_subbed());
232}
233//----------------------------------------------------------------------
235 if (f == nullptr) {
236 if (v->is_subbed()) {
237 return v->skip_leading_variables();
238 }
239 }
240 Term* p = const_cast<Term*>(this);
241 return p;
242}
243//----------------------------------------------------------------------
244set<Term*> Term::all_variables() const {
245 set<Term*> result;
246 if (v != nullptr) {
247 if (v->is_subbed())
248 cerr << "STOP IT!!! You shouldn't be using this with substituted variables!" << endl;
249 Term* p = const_cast<Term*>(this);
250 result.insert(p);
251 }
252 else {
253 for (Term* p : args) {
254 set<Term*> some_vars = p->all_variables();
255 result.insert(some_vars.begin(), some_vars.end());
256 }
257 }
258 return result;
259}
260//----------------------------------------------------------------------
261ostream& operator<<(ostream& out, const Term& t) {
262 out << t.to_string(params::output_terms_with_substitution, true);
263 return out;
264}
265
266
267/*
268* Everything from here on is implementatin of methods for
269* Variable.hpp
270*
271* These need to be here to make the dependencies work.
272*/
273
274
275//----------------------------------------------------------------------
276string Variable::to_string(bool subbed) const {
277 colour_string::ColourString cs(params::use_colours);
278 if (!subbed || substitution == nullptr)
279 return cs(name).lblue();
280 else
281 return substitution->to_string(subbed);
282}
283//----------------------------------------------------------------------
284string Variable::make_LaTeX(bool subbed) const {
285 if (subbed && substitution != nullptr)
286 return substitution->make_LaTeX(subbed);
287 else {
288 string s ("\\text{");
289 s += latex_escape_characters(name);
290 s += "}";
291 return s;
292 }
293}
294//----------------------------------------------------------------------
296 if (substitution == nullptr)
297 return false;
298 else
299 return substitution->subbed_is_function();
300}
301//----------------------------------------------------------------------
303 if (substitution == nullptr)
304 return true;
305 else
306 return substitution->subbed_is_variable();
307}
308//----------------------------------------------------------------------
310 if (substitution == nullptr) {
311 Variable* p = const_cast<Variable*>(this);
312 return p;
313 }
314 else
315 return substitution->subbed_variable();
316}
317//----------------------------------------------------------------------
319 if (substitution == nullptr)
320 return this==v2;
321 else
322 return substitution->contains_variable(v2);
323}
324//----------------------------------------------------------------------
326 if (substitution == nullptr) {
327 cerr << "There is no function name to be found..." << endl;
328 return nullptr;
329 }
330 else
331 return substitution->get_subbed_f();
332}
333//----------------------------------------------------------------------
335 if (substitution == nullptr) {
336 cerr << "There is no arity to be found..." << endl;
337 return 0;
338 }
339 else
340 return substitution->get_subbed_arity();
341}
342//----------------------------------------------------------------------
344 if (substitution != nullptr) {
345 return substitution->skip_leading_variables();
346 }
347 cerr << "Stop it! You're trying to skip something inappropriate!" << endl;
348 return nullptr;
349}
350
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:89
string get_name() const
Most basic access function.
Definition Function.hpp:85
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:138
bool is_unsubbed_variable() const
Is this a variable that hasn't been substituted?
Definition Term.cpp:228
string make_LaTeX(bool=false) const
Make a useable LaTeX representation.
Definition Term.cpp:211
bool subbed_equal(Term *) const
Equality test, taking substitution into account.
Definition Term.cpp:72
Term * skip_leading_variables() const
It may be that there is a chain of substitutions attached to a variable.
Definition Term.cpp:234
void find_subbed_vars(set< Variable * > &) const
Taking substitution into account, find all the variables in a term.
Definition Term.cpp:152
bool subbed_is_variable() const
Is this term a variable, taking substitution into accoumt?
Definition Term.cpp:112
set< Term * > all_variables() const
Assuming nothing has been substituted, find all the variables in this term.
Definition Term.cpp:244
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:165
Term()
Constructors - these are private as Terms should only ever be constructed by the TermIndex,...
Definition Term.hpp:72
Variable * subbed_variable() const
Taking substitution into account, what variable do we actually have?
Definition Term.cpp:119
Arity get_subbed_arity() const
Taking substitution into account, what arity do we actually have?
Definition Term.cpp:145
bool contains_variable(Variable *) const
Taking substitution into account, does the term include the variable passed?
Definition Term.cpp:128
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:191
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:105
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:309
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:343
bool contains_variable(Variable *) const
Does the substitution turn the variable into something that includes the variable passed?
Definition Term.cpp:318
bool subbed_is_variable() const
Is the variable still in fact a variable, taking substitution into account?
Definition Term.cpp:302
bool is_subbed() const
Self-explanatory.
Definition Variable.hpp:111
Arity get_subbed_arity() const
If there is a chain of substitutions ending in a function, find that function's arity.
Definition Term.cpp:334
Function * get_subbed_f() const
If there is a chain of substitutions ending in a function, find that function.
Definition Term.cpp:325
string to_string(bool=false) const
Convert to a (coloured) string.
Definition Term.cpp:276
bool subbed_is_function() const
Is the variable now a function, taking substitution into account?
Definition Term.cpp:295
string get_name() const
Self-explanatory access function.
Definition Variable.hpp:99
string make_LaTeX(bool=false) const
Convert the Variable to a useable LaTeX representation.
Definition Term.cpp:284
Term * get_subbed_term() const
Self-explanatory.
Definition Variable.hpp:116
Simple addition of colour to strings and ostreams.
Simple function object for putting commas in lists.