souffle  2.0.2-371-g6315b36
ConstraintSystem.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file ConstraintSystem.h
12  *
13  * A basic set of utilities for solving systems of constraints.
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
20 #include <iostream>
21 #include <map>
22 #include <memory>
23 #include <set>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 namespace souffle::ast::analysis {
29 
30 //----------------------------------------------------------------------
31 // forward declarations
32 //----------------------------------------------------------------------
33 
34 template <typename Id, typename PropertySpace>
35 struct Variable;
36 
37 template <typename Var>
38 class Constraint;
39 
40 template <typename Var>
41 class Assignment;
42 
43 template <typename Var>
44 class Problem;
45 
46 //----------------------------------------------------------------------
47 // property space constructors
48 //----------------------------------------------------------------------
49 
50 namespace detail {
51 
52 template <typename T>
53 struct default_bottom_factory {
54  T operator()() const {
55  return T();
56  }
57 };
58 
59 template <typename T, typename meet_assign_op>
61  T operator()(const T& a, const T& b) {
62  T res = a;
63  meet_assign_op()(res, b);
64  return res;
65  }
66 };
67 } // namespace detail
68 
69 /**
70  * A MPL type for defining a property space. A property space consists of
71  * a value type T (the domain of the property space), a meet operator and
72  * a factory for computing the bottom value of the property space.
73  *
74  * For performance reasons the meet operator is defined by a meet-assign
75  * operator mutating the first operator to become the actual result of the
76  * meet operation.
77  *
78  * @tparam T the value domain of the defined property space
79  * @tparam meet_assign_op the meet-assign operator defining the lattice over the
80  * values of T forming the foundation for the resulting property space
81  * @tparam bottom_factory a functor producing the bottom element of the property space
82  * by default the default constructor of T will be utilized
83  * @tparam meet_op a non destructive meet operator, by default derived from the
84  * meet-assign operator
85  */
86 template <typename T, typename meet_assign_op,
87  typename bottom_factory = typename detail::default_bottom_factory<T>,
88  typename meet_op = typename detail::default_meet_op<T, meet_assign_op>>
89 struct property_space {
90  using value_type = T;
91  using meet_assign_op_type = meet_assign_op;
92  using meet_op_type = meet_op;
93  using bottom_factory_type = bottom_factory;
94 };
95 
96 namespace detail {
97 
98 /**
99  * A meet operator for set-based property spaces based on the sub-set lattices.
100  */
101 template <typename T>
102 struct set_meet_assign_op {
103  bool operator()(std::set<T>& a, const std::set<T>& b) {
104  bool changed = false;
105  for (const auto& cur : b) {
106  changed |= a.insert(cur).second;
107  }
108  return changed;
109  }
110 };
111 } // namespace detail
112 
113 /**
114  * A property space for set-based properties based on sub-set lattices.
115  */
116 template <typename T>
117 struct set_property_space : public property_space<std::set<T>, detail::set_meet_assign_op<T>> {};
118 
119 //----------------------------------------------------------------------
120 // variables
121 //----------------------------------------------------------------------
122 
123 /**
124  * A variable to be utilized within constraints to be handled by the
125  * constraint solver.
126  *
127  * @tparam Id the type of object this variable shall be bound to
128  * @tparam PropertySpace the property space this variable is associated to
129  */
130 template <typename Id, typename PropertySpace>
131 struct Variable {
132  /** exports the property space */
133  using property_space = PropertySpace;
134 
135  Variable(Id id) : id(std::move(id)) {}
136  virtual ~Variable() = default;
137 
138  Variable(const Variable&) = default;
139  Variable(Variable&&) = default;
140 
141  Variable& operator=(const Variable&) = default;
142  Variable& operator=(Variable&&) = default;
143 
144  /** Adds support for equality comparison */
145  bool operator==(const Variable& other) const {
146  return id == other.id;
147  }
148 
149  /** Adds support for inequality comparison */
150  bool operator!=(const Variable& other) const {
151  return !(*this == other);
152  }
153 
154  /** Adds support for less-than comparison */
155  bool operator<(const Variable& other) const {
156  return id < other.id;
157  }
158 
159  /** Adds print support */
160  virtual void print(std::ostream& out) const {
161  out << id;
162  }
163 
164  /** Adds print support */
165  friend std::ostream& operator<<(std::ostream& out, const Variable& var) {
166  var.print(out);
167  return out;
168  }
169 
170 protected:
171  /** the underlying value giving this variable its identity */
172  Id id;
173 };
174 
175 //----------------------------------------------------------------------
176 // constraints
177 //----------------------------------------------------------------------
178 
179 /**
180  * A generic base class for constraints on variables.
181  *
182  * @tparam Var the type of variables constraint.
183  */
184 template <typename Var>
185 class Constraint {
186 public:
187  /** A virtual destructor */
188  virtual ~Constraint() = default;
189 
190  /**
191  * Requests the given assignment to be updated according to
192  * this constraint.
193  *
194  * @param ass the assignment to be updated
195  * @return true if the assignment was altered, false otherwise
196  */
197  virtual bool update(Assignment<Var>& ass) const = 0;
198 
199  /** Adds print support for constraints (debugging) */
200  virtual void print(std::ostream& out) const = 0;
201 
202  /** Adds print support for constraints (debugging) */
203  friend std::ostream& operator<<(std::ostream& out, const Constraint& c) {
204  c.print(out);
205  return out;
206  }
207 };
208 
209 //----------------------------------------------------------------------
210 // generic constraint factories
211 //----------------------------------------------------------------------
212 
213 /**
214  * A generic factory for constraints of the form
215  *
216  * a ⊑ b
217  *
218  * where a and b are variables and ⊑ is the order relation induced by
219  * their associated property space.
220  */
221 template <typename Var>
222 std::shared_ptr<Constraint<Var>> sub(const Var& a, const Var& b, const std::string& symbol = "⊑") {
223  struct Sub : public Constraint<Var> {
224  Var a, b;
225  std::string symbol;
226 
227  Sub(Var a, Var b, std::string symbol) : a(std::move(a)), b(std::move(b)), symbol(std::move(symbol)) {}
228 
229  bool update(Assignment<Var>& ass) const override {
230  typename Var::property_space::meet_assign_op_type meet_assign;
231  return meet_assign(ass[b], ass[a]);
232  }
233 
234  void print(std::ostream& out) const override {
235  out << a << " " << symbol << " " << b;
236  }
237  };
238 
239  return std::make_shared<Sub>(a, b, symbol);
240 }
241 
242 /**
243  * A generic factory for constraints of the form
244  *
245  * a ⊑ b
246  *
247  * where b is a variables, a is a value of b's property space, and ⊑ is
248  * the order relation induced by b's property space.
249  */
250 template <typename Var, typename Val = typename Var::property_space::value_type>
251 std::shared_ptr<Constraint<Var>> sub(const Val& a, const Var& b, const std::string& symbol = "⊑") {
252  struct Sub : public Constraint<Var> {
253  Val a;
254  Var b;
255  std::string symbol;
256 
257  Sub(Val a, Var b, std::string symbol) : a(std::move(a)), b(std::move(b)), symbol(std::move(symbol)) {}
258 
259  bool update(Assignment<Var>& ass) const override {
260  typename Var::property_space::meet_assign_op_type meet_assign;
261  return meet_assign(ass[b], a);
262  }
263 
264  void print(std::ostream& out) const override {
265  out << a << " " << symbol << " " << b;
266  }
267  };
268 
269  return std::make_shared<Sub>(a, b, symbol);
270 }
271 
272 //----------------------------------------------------------------------
273 // assignment
274 //----------------------------------------------------------------------
275 
276 /**
277  * An assignment maps a list of variables to values of their respective
278  * property space.
279  *
280  * @tparam Var the kind of variable forming the domain of this assignment
281  */
282 template <typename Var>
283 class Assignment {
284  // a few type definitions
285  using property_space = typename Var::property_space;
286  using value_type = typename property_space::value_type;
288 
289  using data_type = typename std::map<Var, value_type>;
290 
291  /** a copy of the value assigned to all unmapped variables */
293 
294  /** the actual mapping of variables to values */
296 
297 public:
298  using iterator = typename data_type::const_iterator;
299 
300  /** Creates a new, empty assignment */
302 
303  /**
304  * Looks up the value associated to the given variable. Every
305  * Assignment is a total mapping assigning each variable in
306  * the domain of type {Var} a value of its property space. If
307  * not defined earlier, it will be the bottom value.
308  *
309  * @param var the variable whose value is required
310  * @return a const reference to the associated value
311  */
312  const value_type& operator[](const Var& var) const {
313  auto pos = data.find(var);
314  return (pos != data.end()) ? pos->second : bottom;
315  }
316 
317  /**
318  * Looks up the value associated to the given variable. Every
319  * Assignment is a total mapping assigning each variable in
320  * the domain of type {Var} a value of its property space. If
321  * not defined earlier, it will be bound to the bottom value.
322  *
323  * @param var the variable whose value is required
324  * @return a mutable reference to the associated value
325  */
326  value_type& operator[](const Var& var) {
327  auto pos = data.find(var);
328  if (pos == data.end()) {
329  return data[var] = bottom;
330  }
331  return pos->second;
332  }
333 
334  /** Adds print support */
335  void print(std::ostream& out) const {
336  out << data;
337  }
338 
339  /** Adds print support */
340  friend std::ostream& operator<<(std::ostream& out, const Assignment& ass) {
341  ass.print(out);
342  return out;
343  }
344 
345  /** Allows to iterate over the maplets defining this assignment. */
346  iterator begin() const {
347  return data.begin();
348  }
349 
350  /** Allows to iterate over the maplets defining this assignment. */
351  iterator end() const {
352  return data.end();
353  }
354 };
355 
356 //----------------------------------------------------------------------
357 // problem & solver
358 //----------------------------------------------------------------------
359 
360 /**
361  * A problem is a list of constraints for which a solution is desired.
362  *
363  * @tparam Var the domain of variables handled by this problem
364  */
365 template <typename Var>
366 class Problem {
367  // a few type definitions
368  using constraint = Constraint<Var>;
369  using constraint_ptr = std::shared_ptr<constraint>;
370 
371  /** The list of covered constraints */
372  std::vector<constraint_ptr> constraints;
373 
374 public:
375  /**
376  * Adds another constraint to the internally maintained list of constraints.
377  */
379  constraints.push_back(constraint);
380  }
381 
382  /**
383  * Computes a solution (minimum fixpoint) for the contained list of
384  * constraints.
385  *
386  * @return an assignment representing a solution for this problem
387  */
388  Assignment<Var> solve() const {
389  Assignment<Var> res;
390  return solve(res);
391  }
392 
393  /**
394  * Computes a solution (minimum fixpoint) for the contained list of
395  * constraints based on an initial assignment.
396  *
397  * @return an assignment representing a solution for this problem
398  */
399  Assignment<Var>& solve(Assignment<Var>& assignment) const {
400  // this is the most naive version of a solver, but sound and complete
401  bool change = true;
402  while (change) {
403  change = false;
404  for (const auto& constraint : constraints) {
405  change |= constraint->update(assignment);
406  }
407  }
408  // already done
409  return assignment;
410  }
411 
412  /** Enables a problem to be printed (debugging) */
413  void print(std::ostream& out) const {
414  if (constraints.empty()) {
415  out << "{}";
416  } else {
417  out << "{\n\t" << join(constraints, ",\n\t", print_deref<constraint_ptr>()) << "\n}";
418  }
419  }
420 
421  friend std::ostream& operator<<(std::ostream& out, const Problem& p) {
422  p.print(out);
423  return out;
424  }
425 };
426 
427 } // namespace souffle::ast::analysis
souffle::ast::analysis::Assignment::operator<<
friend std::ostream & operator<<(std::ostream &out, const Assignment &ass)
Adds print support.
Definition: ConstraintSystem.h:346
souffle::ast::analysis::Variable::print
virtual void print(std::ostream &out) const
Adds print support.
Definition: ConstraintSystem.h:166
souffle::ast::analysis::Assignment::bottom
value_type bottom
a copy of the value assigned to all unmapped variables
Definition: ConstraintSystem.h:298
souffle::ast::analysis::property_space::value_type
T value_type
Definition: ConstraintSystem.h:96
souffle::ast::analysis::sub
std::shared_ptr< Constraint< Var > > sub(const Var &a, const Var &b, const std::string &symbol="⊑")
A generic factory for constraints of the form.
Definition: ConstraintSystem.h:228
souffle::ast::analysis::Variable::operator<
bool operator<(const Variable &other) const
Adds support for less-than comparison.
Definition: ConstraintSystem.h:161
souffle::ast::analysis::Problem::constraint
Constraint< Var > constraint
Definition: ConstraintSystem.h:374
souffle::ast::analysis::property_space::bottom_factory_type
bottom_factory bottom_factory_type
Definition: ConstraintSystem.h:99
souffle::ast::analysis::Assignment::bottom_factory_type
typename property_space::bottom_factory_type bottom_factory_type
Definition: ConstraintSystem.h:293
souffle::ast::analysis::Constraint::print
virtual void print(std::ostream &out) const =0
Adds print support for constraints (debugging)
souffle::ast::analysis::Problem
A problem is a list of constraints for which a solution is desired.
Definition: ConstraintSystem.h:50
souffle::ast::analysis::Variable
A variable to be utilized within constraints to be handled by the constraint solver.
Definition: ConstraintSystem.h:41
souffle::ast::analysis::Variable::operator=
Variable & operator=(const Variable &)=default
souffle::ast::analysis::Problem::constraint_ptr
std::shared_ptr< constraint > constraint_ptr
Definition: ConstraintSystem.h:375
souffle::ast::analysis::Constraint
A generic base class for constraints on variables.
Definition: ConstraintSystem.h:44
souffle::ast::analysis::Variable::~Variable
virtual ~Variable()=default
souffle::ast::analysis::Variable::id
Id id
the underlying value giving this variable its identity
Definition: ConstraintSystem.h:178
souffle::ast::analysis::Assignment< TypeVar >::iterator
typename data_type::const_iterator iterator
Definition: ConstraintSystem.h:304
souffle::ast::analysis::Assignment::property_space
typename Var::property_space property_space
Definition: ConstraintSystem.h:291
souffle::ast::analysis::Assignment::operator[]
const value_type & operator[](const Var &var) const
Looks up the value associated to the given variable.
Definition: ConstraintSystem.h:318
souffle::join
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
Definition: StreamUtil.h:175
souffle::ast::analysis::Assignment
An assignment maps a list of variables to values of their respective property space.
Definition: ConstraintSystem.h:47
souffle::ast::analysis::detail::default_bottom_factory::operator()
T operator()() const
Definition: ConstraintSystem.h:60
souffle::ast::analysis::detail::default_bottom_factory
Definition: ConstraintSystem.h:59
souffle::ast::analysis::set_property_space
A property space for set-based properties based on sub-set lattices.
Definition: ConstraintSystem.h:123
souffle::ast::analysis::Variable::Variable
Variable(Id id)
Definition: ConstraintSystem.h:141
souffle::ast::analysis::Assignment::end
iterator end() const
Allows to iterate over the maplets defining this assignment.
Definition: ConstraintSystem.h:357
souffle::ast::analysis::property_space
A MPL type for defining a property space.
Definition: ConstraintSystem.h:95
souffle::ast::analysis::detail::default_meet_op
Definition: ConstraintSystem.h:66
souffle::ast::analysis::Constraint::~Constraint
virtual ~Constraint()=default
A virtual destructor.
souffle::ast::analysis::property_space::meet_assign_op_type
meet_assign_op meet_assign_op_type
Definition: ConstraintSystem.h:97
souffle::ast::analysis::Variable::operator<<
friend std::ostream & operator<<(std::ostream &out, const Variable &var)
Adds print support.
Definition: ConstraintSystem.h:171
souffle::ast::analysis::detail::set_meet_assign_op::operator()
bool operator()(std::set< T > &a, const std::set< T > &b)
Definition: ConstraintSystem.h:109
souffle::ast::analysis::Assignment::Assignment
Assignment()
Creates a new, empty assignment.
Definition: ConstraintSystem.h:307
souffle::ast::analysis::Assignment::data_type
typename std::map< Var, value_type > data_type
Definition: ConstraintSystem.h:295
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
std
Definition: Brie.h:3053
StreamUtil.h
souffle::ast::analysis::detail::default_meet_op::operator()
T operator()(const T &a, const T &b)
Definition: ConstraintSystem.h:67
souffle::ast::analysis
Definition: Aggregate.cpp:39
souffle::ast::analysis::property_space::meet_op_type
meet_op meet_op_type
Definition: ConstraintSystem.h:98
souffle::ast::analysis::Variable::operator!=
bool operator!=(const Variable &other) const
Adds support for inequality comparison.
Definition: ConstraintSystem.h:156
souffle::ast::analysis::Assignment::begin
iterator begin() const
Allows to iterate over the maplets defining this assignment.
Definition: ConstraintSystem.h:352
souffle::ast::analysis::Assignment::value_type
typename property_space::value_type value_type
Definition: ConstraintSystem.h:292
souffle::ast::analysis::Constraint::operator<<
friend std::ostream & operator<<(std::ostream &out, const Constraint &c)
Adds print support for constraints (debugging)
Definition: ConstraintSystem.h:209
souffle::ast::analysis::Problem::print
void print(std::ostream &out) const
Enables a problem to be printed (debugging)
Definition: ConstraintSystem.h:419
souffle::ast::analysis::Variable::operator==
bool operator==(const Variable &other) const
Adds support for equality comparison.
Definition: ConstraintSystem.h:151
souffle::ast::analysis::Constraint::update
virtual bool update(Assignment< Var > &ass) const =0
Requests the given assignment to be updated according to this constraint.
souffle::ast::analysis::Problem::constraints
std::vector< constraint_ptr > constraints
The list of covered constraints.
Definition: ConstraintSystem.h:378
souffle::ast::analysis::Problem::add
void add(const constraint_ptr &constraint)
Adds another constraint to the internally maintained list of constraints.
Definition: ConstraintSystem.h:384
souffle::ast::analysis::Assignment::print
void print(std::ostream &out) const
Adds print support.
Definition: ConstraintSystem.h:341
souffle::ast::analysis::Problem::operator<<
friend std::ostream & operator<<(std::ostream &out, const Problem &p)
Definition: ConstraintSystem.h:427
souffle::ast::analysis::Problem::solve
Assignment< Var > solve() const
Computes a solution (minimum fixpoint) for the contained list of constraints.
Definition: ConstraintSystem.h:394
souffle::ast::analysis::Assignment::data
data_type data
the actual mapping of variables to values
Definition: ConstraintSystem.h:301
p
a horizontalBars(j=m=void 0===a.axisX.type?new c.AutoScaleAxis(c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})):a.axisX.type.call(c, c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})), l=n=void 0===a.axisY.type?new c.StepAxis(c.Axis.units.y, b.normalized.series, o,{ticks:k}):a.axisY.type.call(c, c.Axis.units.y, b.normalized.series, o, a.axisY)) var p
Definition: htmlJsChartistMin.h:15