1/*
2 * Domain.h
3 * @brief Domain restriction constraint
4 * @date Feb 13, 2012
5 * @author Frank Dellaert
6 */
7
8#pragma once
9
10#include <gtsam/discrete/DiscreteKey.h>
11#include <gtsam_unstable/discrete/Constraint.h>
12#include <optional>
13
14namespace gtsam {
15
16/**
17 * The Domain class represents a constraint that restricts the possible values a
18 * particular variable, with given key, can take on.
19 */
20class GTSAM_UNSTABLE_EXPORT Domain : public Constraint {
21 size_t cardinality_; /// Cardinality
22 std::set<size_t> values_; /// allowed values
23
24 public:
25 typedef std::shared_ptr<Domain> shared_ptr;
26
27 // Constructor on Discrete Key initializes an "all-allowed" domain
28 Domain(const DiscreteKey& dkey)
29 : Constraint(dkey.first), cardinality_(dkey.second) {
30 for (size_t v = 0; v < cardinality_; v++) values_.insert(x: v);
31 }
32
33 // Constructor on Discrete Key with single allowed value
34 // Consider SingleValue constraint
35 Domain(const DiscreteKey& dkey, size_t v)
36 : Constraint(dkey.first), cardinality_(dkey.second) {
37 values_.insert(x: v);
38 }
39
40 /// The one key
41 Key key() const { return keys_[0]; }
42
43 // The associated discrete key
44 DiscreteKey discreteKey() const { return DiscreteKey(key(), cardinality_); }
45
46 /// Insert a value, non const :-(
47 void insert(size_t value) { values_.insert(x: value); }
48
49 /// Erase a value, non const :-(
50 void erase(size_t value) { values_.erase(x: value); }
51
52 uint64_t nrValues() const override { return values_.size(); }
53
54 bool isSingleton() const { return nrValues() == 1; }
55
56 size_t firstValue() const { return *values_.begin(); }
57
58 // print
59 void print(const std::string& s = "", const KeyFormatter& formatter =
60 DefaultKeyFormatter) const override;
61
62 /// equals
63 bool equals(const DiscreteFactor& other, double tol) const override {
64 if (!dynamic_cast<const Domain*>(&other))
65 return false;
66 else {
67 const Domain& f(static_cast<const Domain&>(other));
68 return (cardinality_ == f.cardinality_) && (values_ == f.values_);
69 }
70 }
71
72 // Return concise string representation, mostly to debug arc consistency.
73 // Converts from base 0 to base1.
74 std::string base1Str() const;
75
76 // Check whether domain cotains a specific value.
77 bool contains(size_t value) const { return values_.count(x: value) > 0; }
78
79 /// Calculate value
80 double evaluate(const Assignment<Key>& values) const override;
81
82 /// Convert into a decisiontree
83 DecisionTreeFactor toDecisionTreeFactor() const override;
84
85 /// Multiply into a decisiontree
86 DecisionTreeFactor operator*(const DecisionTreeFactor& f) const override;
87
88 /*
89 * Ensure Arc-consistency by checking every possible value of domain j.
90 * @param j domain to be checked
91 * @param (in/out) domains all domains, but only domains->at(j) will be
92 * checked.
93 * @return true if domains->at(j) was changed, false otherwise.
94 */
95 bool ensureArcConsistency(Key j, Domains* domains) const override;
96
97 /**
98 * Check for a value in domain that does not occur in any other connected
99 * domain. If found, return a a new singleton domain...
100 * Called in AllDiff::ensureArcConsistency
101 * @param keys connected domains through alldiff
102 * @param keys other domains
103 */
104 std::optional<Domain> checkAllDiff(const KeyVector keys,
105 const Domains& domains) const;
106
107 /// Partially apply known values
108 Constraint::shared_ptr partiallyApply(const DiscreteValues& values) const override;
109
110 /// Partially apply known values, domain version
111 Constraint::shared_ptr partiallyApply(const Domains& domains) const override;
112};
113
114} // namespace gtsam
115