summaryrefslogtreecommitdiff
path: root/ts_cpp/ts_lib.h
blob: 68fe7be6d4693dce10cee30e74a4abc37bd86ee7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#ifndef TS_LIB_H_
#define TS_LIB_H_

#include <array>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <stack>
#include <vector>
#include <cassert>

// Nodes are > 0. Variables are <= 0. Where Nodes are expected, an 'empty' node
// is represented by 0.

#define Node int
#define Variable int
#define NodeOrVariable int

class Triplet : public std::array<Node, 3> {
 public:
  Triplet(Node i, Node j, Node k) : std::array<Node, 3>({i, j, k}) {}
};

// https://en.cppreference.com/w/cpp/utility/hash
namespace std {
template<> struct hash<Triplet> {
  std::size_t operator()(Triplet const& triplet) const noexcept {
    std::size_t h1 = std::hash<int>{}(triplet[0]);
    std::size_t h2 = std::hash<int>{}(triplet[1]);
    std::size_t h3 = std::hash<int>{}(triplet[2]);
    // TODO(masotoud): maybe profile with other combinations.
    return h1 ^ (h2 << 1) ^ (h3 >> 1);
  }
};
}  // namespace std

class Structure {
 public:
  void AddFact(const Triplet &fact);
  void RemoveFact(const Triplet &fact);
  void AddFactPy(Node i, Node j, Node k);
  void RemoveFactPy(Node i, Node j, Node k);
  const std::vector<Triplet> &Lookup(const Triplet &fact) const;
  bool AllTrue(const std::vector<Triplet> &facts) const;
  bool IsTrue(const Triplet &fact) const;

 private:
  std::unordered_map<Triplet, std::vector<Triplet>> facts_;
  // TODO(masotoud)
  std::vector<Triplet> empty_;
};

class Solver {
 public:
  Solver(const Structure &structure,
         const size_t n_variables,
         const std::vector<Triplet> &constraints,
         const std::vector<std::set<size_t>> &maybe_equal);

  bool IsValid() { return valid_; }
  std::vector<Node> NextAssignment();
  void Assign(const Node to);
  void UnAssign();
  void GetOptions();

 private:
  int CurrentVariable() const;
  bool IsVariable(int node) const;

  struct State {
    State() : options(), options_it(options.begin()) { }
    std::set<Node> options;
    std::set<Node>::iterator options_it;
  };

  const Structure &structure_;
  const size_t n_variables_;
  bool valid_;
  std::vector<Triplet> constraints_;
  std::vector<Triplet> working_constraints_;
  // Size: n_variables
  std::vector<std::vector<size_t>> var_to_constraints_;
  // Size: n_variables
  std::vector<std::set<size_t>> may_equal_;
  // Size: n_variables
  std::vector<Node> assignment_;
  // Size: n_variables
  std::vector<State> states_;
  // Range: [0, infty)
  // NOTE: This is actually -current_variable_. Makes it more convenient for
  // indexing into assignment_, states_, etc.
  int current_index_ = 0;
};

#endif  // TS_LIB_H_
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback