Define empty and check for it in apply variants

release/4.3a0
Frank Dellaert 2022-01-02 09:47:15 -05:00
parent 7f3f332d09
commit 78f8cc948d
3 changed files with 24 additions and 0 deletions

View File

@ -642,6 +642,11 @@ namespace gtsam {
template<typename L, typename Y> template<typename L, typename Y>
DecisionTree<L, Y> DecisionTree<L, Y>::apply(const Unary& op) const { DecisionTree<L, Y> DecisionTree<L, Y>::apply(const Unary& op) const {
// It is unclear what should happen if tree is empty:
if (empty()) {
throw std::runtime_error(
"DecisionTree::apply(unary op) undefined for empty tree.");
}
return DecisionTree(root_->apply(op)); return DecisionTree(root_->apply(op));
} }
@ -649,6 +654,11 @@ namespace gtsam {
template<typename L, typename Y> template<typename L, typename Y>
DecisionTree<L, Y> DecisionTree<L, Y>::apply(const DecisionTree& g, DecisionTree<L, Y> DecisionTree<L, Y>::apply(const DecisionTree& g,
const Binary& op) const { const Binary& op) const {
// It is unclear what should happen if either tree is empty:
if (empty() or g.empty()) {
throw std::runtime_error(
"DecisionTree::apply(binary op) undefined for empty trees.");
}
// apply the operaton on the root of both diagrams // apply the operaton on the root of both diagrams
NodePtr h = root_->apply_f_op_g(*g.root_, op); NodePtr h = root_->apply_f_op_g(*g.root_, op);
// create a new class with the resulting root "h" // create a new class with the resulting root "h"

View File

@ -194,6 +194,9 @@ namespace gtsam {
virtual ~DecisionTree() { virtual ~DecisionTree() {
} }
/** empty tree? */
bool empty() const { return !root_; }
/** equality */ /** equality */
bool operator==(const DecisionTree& q) const; bool operator==(const DecisionTree& q) const;

View File

@ -78,6 +78,9 @@ struct Ring {
static inline int one() { static inline int one() {
return 1; return 1;
} }
static inline int id(const int& a) {
return a;
}
static inline int add(const int& a, const int& b) { static inline int add(const int& a, const int& b) {
return a + b; return a + b;
} }
@ -100,6 +103,9 @@ TEST(DT, example)
x10[A] = 1, x10[B] = 0; x10[A] = 1, x10[B] = 0;
x11[A] = 1, x11[B] = 1; x11[A] = 1, x11[B] = 1;
// empty
DT empty;
// A // A
DT a(A, 0, 5); DT a(A, 0, 5);
LONGS_EQUAL(0,a(x00)) LONGS_EQUAL(0,a(x00))
@ -118,6 +124,11 @@ TEST(DT, example)
LONGS_EQUAL(5,notb(x10)) LONGS_EQUAL(5,notb(x10))
DOT(notb); DOT(notb);
// Check supplying empty trees yields an exception
CHECK_EXCEPTION(apply(empty, &Ring::id), std::runtime_error);
CHECK_EXCEPTION(apply(empty, a, &Ring::mul), std::runtime_error);
CHECK_EXCEPTION(apply(a, empty, &Ring::mul), std::runtime_error);
// apply, two nodes, in natural order // apply, two nodes, in natural order
DT anotb = apply(a, notb, &Ring::mul); DT anotb = apply(a, notb, &Ring::mul);
LONGS_EQUAL(0,anotb(x00)) LONGS_EQUAL(0,anotb(x00))