carl  24.04
Computer ARithmetic Library
Variable.h
Go to the documentation of this file.
1 /**
2  * @file Variable.h
3  * @author Sebastian Junges
4  */
5 
6 #pragma once
7 
8 #include <cassert>
9 #include <climits>
10 #include <iosfwd>
11 #include <string>
12 #include <type_traits>
13 
15 #include <carl-common/config.h>
17 
18 namespace carl {
19 
20 /**
21  * Several types of variables are supported.
22  * BOOL: the Booleans
23  * REAL: the reals
24  * INT: the integers
25  * UNINTERPRETED: all uninterpreted types
26  * BITVECTOR: bitvectors of any length
27  */
28 enum class VariableType { VT_BOOL = 0,
29  VT_REAL = 1,
30  VT_INT = 2,
31  VT_UNINTERPRETED = 3,
32  VT_BITVECTOR = 4,
33  MIN_TYPE = VT_BOOL,
35  TYPE_SIZE = MAX_TYPE - MIN_TYPE + 1 };
36 
37 /**
38  * Streaming operator for VariableType.
39  * @param os Output Stream.
40  * @param t VariableType.
41  * @return os.
42  */
43 inline std::ostream& operator<<(std::ostream& os, const VariableType& t) {
44  switch (t) {
46  return os << "Bool";
48  return os << "Real";
50  return os << "Int";
52  return os << "Uninterpreted";
54  return os << "Bitvector";
55  default:
56  assert(false && "Invalid enum value for VariableType");
57  return os << "VariableType(" << underlying_enum_value(t) << ")";
58  }
59 }
60 
61 class VariablePool;
62 
63 /**
64  * A Variable represents an algebraic variable that can be used throughout carl.
65  *
66  * Variables are basically bitvectors that contain `[rank | id | type]`, called *content*.
67  * - The `id` is the identifier of this variable.
68  * - The `type` is the variable type.
69  * - The `rank` is zero be default, but can be used to create a custom variable ordering, as the comparison operators compare the whole content.
70  * The `id` and the `type` together form a unique identifier for a variable.
71  * If the VariablePool is used to construct variables (and we advise to do so), the id's will be consecutive starting with one for each variable type.
72  * The `rank` is meant to change the variable order when passing a set of variables to another context, for example a function.
73  * A single variable (identified by `id` and `type`) should not occur with two different `rank` values in the same context and hence such a comparison should never take place.
74  *
75  * A variable with id zero is considered invalid. It can be used as a default argument and can be compared to Variable::NO_VARIABLE.
76  * Such a variable can only be constructed using the default constructor and its content will always be zero.
77  *
78  * Although not templated, we keep the whole class inlined for efficiency purposes.
79  * Note that this way, any decent compiler removes the overhead introduced, while
80  * having gained strong type-definitions and thus the ability to provide operator overloading.
81  *
82  * Moreover, notice that for small classes like this, pass-by-value could be faster than pass-by-ref.
83  * However, this depends much on the capabilities of the compiler.
84  */
85 class Variable {
86  friend VariablePool;
87 public:
88  /// Argument type for variables being function arguments.
89  using Arg = const Variable&;
90 
91 private:
92  /**
93  * The content of the variable.
94  * In order to keep a variable object small, this is the only data member.
95  * All other data (like names or alike) are stored in the VariablePool.
96  */
97  std::size_t mContent = 0;
98 
99  /**
100  * Private constructor to be used by the VariablePool.
101  * @param id The identifier of the variable.
102  * @param type The type.
103  * @param rank The rank.
104  */
105  explicit Variable(std::size_t id, VariableType type = VariableType::VT_REAL, std::size_t rank = 0) noexcept
106  : mContent((rank << (AVAILABLE + RESERVED_FOR_TYPE)) | (id << RESERVED_FOR_TYPE) | static_cast<std::size_t>(type)) {
107  assert(rank < (1UL << RESERVED_FOR_RANK));
108  assert(0 < id && id < (1UL << AVAILABLE));
110  }
111 
112 public:
113  /**
114  * Default constructor, constructing a variable, which is considered as not an actual variable.
115  * Such an invalid variable is stored in NO_VARIABLE, so use this if you need a default value for a variable.
116  */
117  constexpr Variable() = default;
118 
119  /**
120  * Retrieves the id of the variable.
121  * @return Variable id.
122  */
123  constexpr std::size_t id() const noexcept {
124  return (mContent >> RESERVED_FOR_TYPE) % (static_cast<std::size_t>(1) << AVAILABLE);
125  }
126 
127  /**
128  * Retrieves the type of the variable.
129  * @return Variable type.
130  */
131  constexpr VariableType type() const noexcept {
132  return static_cast<VariableType>(mContent % (static_cast<std::size_t>(1) << RESERVED_FOR_TYPE));
133  }
134 
135  /**
136  * Retrieves the name of the variable.
137  * @return Variable name.
138  */
139  std::string name() const;
140 
141  /**
142  * Retrieves a unique name of the variable of the form `<type><id>`.
143  * While `<type>` consists of lowercase letters, `<id>` is a decimal number.
144  * This unique name is meant to be used wherever a unique but notationally simple identifier is required, for example when interfacing with other systems.
145  * @return Variable name.
146  */
147  std::string safe_name() const;
148 
149  /**
150  * Retrieves the rank of the variable.
151  * @return Variable rank.
152  */
153  constexpr std::size_t rank() const noexcept {
154  return mContent >> (AVAILABLE + RESERVED_FOR_TYPE);
155  }
156 
157  /// @name Comparison operators
158  /// @{
159  /**
160  * Compares two variables.
161  *
162  * Note that for performance reasons, we compare the whole content of the variable (including the rank).
163  *
164  * Note that the variable order is not the order of the variable id. We consider variables greater, if they are defined earlier, i.e. if they have a smaller id.
165  * Hence, the variables order and the order of the variable ids are reversed.
166  * @param lhs First variable.
167  * @param rhs Second variable.
168  * @return `lhs ~ rhs`, `~` being the relation that is checked.
169  */
170  friend bool operator==(Variable lhs, Variable rhs) noexcept {
171  return lhs.mContent == rhs.mContent;
172  }
173  friend bool operator!=(Variable lhs, Variable rhs) noexcept {
174  return lhs.mContent != rhs.mContent;
175  }
176  friend bool operator<(Variable lhs, Variable rhs) noexcept {
177  return lhs.mContent < rhs.mContent;
178  }
179  friend bool operator<=(Variable lhs, Variable rhs) noexcept {
180  return lhs.mContent <= rhs.mContent;
181  }
182  friend bool operator>(Variable lhs, Variable rhs) noexcept {
183  return lhs.mContent > rhs.mContent;
184  }
185  friend bool operator>=(Variable lhs, Variable rhs) noexcept {
186  return lhs.mContent >= rhs.mContent;
187  }
188  /// @}
189 
190  /// Number of bits available for the content.
191  static constexpr std::size_t BITSIZE = CHAR_BIT * sizeof(std::size_t); //mContent has type size_t
192  /// Number of bits reserved for the type.
193  static constexpr std::size_t RESERVED_FOR_TYPE = 3;
194  /// Number of bits reserved for the rank.
195  static constexpr std::size_t RESERVED_FOR_RANK = 4;
196  /// Overall number of bits reserved.
197  static constexpr std::size_t RESERVED = RESERVED_FOR_RANK + RESERVED_FOR_TYPE;
198  static_assert(RESERVED < BITSIZE, "Too many bits reserved for special use.");
199  /// Number of bits available for the id.
200  static constexpr std::size_t AVAILABLE = BITSIZE - RESERVED;
201 
202  /// Instance of an invalid variable.
203  static const Variable NO_VARIABLE;
204 };
205 static_assert(std::is_trivially_copyable<Variable>::value, "Variable should be trivially copyable.");
206 
207 /**
208  * Streaming operator for Variable.
209  * @param os Output stream.
210  * @param rhs Variable.
211  * @return `os`
212  */
213 inline std::ostream& operator<<(std::ostream& os, Variable rhs) {
214  return os << rhs.name();
215 }
216 
217 } // namespace carl
218 
219 namespace std {
220 /**
221  * Specialization of `std::hash` for Variable.
222  */
223 template<>
224 struct hash<carl::Variable> {
225  /**
226  * Calculates the hash of a Variable.
227  * @param variable Variable.
228  * @return Hash of variable
229  */
230  std::size_t operator()(const carl::Variable variable) const noexcept {
231  return variable.id();
232  }
233 };
234 } // namespace std
A small wrapper that configures logging for carl.
carl is the main namespace for the library.
std::ostream & operator<<(std::ostream &os, const BasicConstraint< Poly > &c)
Prints the given constraint on the given stream.
VariableType
Several types of variables are supported.
Definition: Variable.h:28
constexpr auto underlying_enum_value(Enum e)
Casts an enum value to a value of the underlying number type.
Definition: enum_util.h:21
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
std::string safe_name() const
Retrieves a unique name of the variable of the form <type><id>.
Definition: Variable.cpp:11
friend bool operator>=(Variable lhs, Variable rhs) noexcept
Compares two variables.
Definition: Variable.h:185
friend bool operator<=(Variable lhs, Variable rhs) noexcept
Compares two variables.
Definition: Variable.h:179
constexpr std::size_t rank() const noexcept
Retrieves the rank of the variable.
Definition: Variable.h:153
friend bool operator<(Variable lhs, Variable rhs) noexcept
Compares two variables.
Definition: Variable.h:176
static constexpr std::size_t RESERVED_FOR_RANK
Number of bits reserved for the rank.
Definition: Variable.h:195
Variable(std::size_t id, VariableType type=VariableType::VT_REAL, std::size_t rank=0) noexcept
Private constructor to be used by the VariablePool.
Definition: Variable.h:105
friend bool operator!=(Variable lhs, Variable rhs) noexcept
Compares two variables.
Definition: Variable.h:173
friend bool operator==(Variable lhs, Variable rhs) noexcept
Compares two variables.
Definition: Variable.h:170
friend VariablePool
Definition: Variable.h:86
static constexpr std::size_t BITSIZE
Number of bits available for the content.
Definition: Variable.h:191
static constexpr std::size_t RESERVED_FOR_TYPE
Number of bits reserved for the type.
Definition: Variable.h:193
friend bool operator>(Variable lhs, Variable rhs) noexcept
Compares two variables.
Definition: Variable.h:182
std::string name() const
Retrieves the name of the variable.
Definition: Variable.cpp:8
constexpr Variable()=default
Default constructor, constructing a variable, which is considered as not an actual variable.
static const Variable NO_VARIABLE
Instance of an invalid variable.
Definition: Variable.h:203
constexpr std::size_t id() const noexcept
Retrieves the id of the variable.
Definition: Variable.h:123
static constexpr std::size_t RESERVED
Overall number of bits reserved.
Definition: Variable.h:197
std::size_t mContent
The content of the variable.
Definition: Variable.h:97
constexpr VariableType type() const noexcept
Retrieves the type of the variable.
Definition: Variable.h:131
static constexpr std::size_t AVAILABLE
Number of bits available for the id.
Definition: Variable.h:200
std::size_t operator()(const carl::Variable variable) const noexcept
Calculates the hash of a Variable.
Definition: Variable.h:230