36#include <TargetConditionals.h>
45 template<
typename L,
typename Y>
52 template <
typename L,
typename Y>
75 return (q.isLeaf() && q.sameLeaf(*
this));
79 bool equals(
const Node& q,
const CompareFunc& compare)
const override {
80 if (!q.isLeaf())
return false;
81 const Leaf* other =
static_cast<const Leaf*
>(&q);
82 return compare(this->constant_, other->
constant_);
86 void print(
const std::string& s,
const LabelFormatter& labelFormatter,
87 const ValueFormatter& valueFormatter)
const override {
88 std::cout << s <<
" Leaf " << valueFormatter(
constant_) << std::endl;
92 void dot(std::ostream& os,
const LabelFormatter& labelFormatter,
93 const ValueFormatter& valueFormatter,
94 bool showZero)
const override {
95 const std::string value = valueFormatter(
constant_);
96 if (showZero || value.compare(
"0"))
97 os <<
"\"" << this->id() <<
"\" [label=\"" << value
98 <<
"\", shape=box, rank=sink, height=0.35, fixedsize=true]\n";
124 NodePtr apply_f_op_g(
const Node& g,
const Binary& op)
const override {
125 return g.apply_g_op_fL(*
this, op);
129 NodePtr apply_g_op_fL(
const Leaf& fL,
const Binary& op)
const override {
131 NodePtr h(
new Leaf(op(fL.constant_, constant_)));
136 NodePtr apply_g_op_fC(
const Choice& fC,
const Binary& op)
const override {
137 return fC.apply_fC_op_gL(*
this, op);
145 bool isLeaf()
const override {
return true; }
150#if GTSAM_ENABLE_BOOST_SERIALIZATION
152 friend class boost::serialization::access;
153 template <
class ARCHIVE>
154 void serialize(ARCHIVE& ar,
const unsigned int ) {
155 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
156 ar& BOOST_SERIALIZATION_NVP(constant_);
164 template<
typename L,
typename Y>
179 using ChoicePtr = std::shared_ptr<const Choice>;
186#ifdef DT_DEBUG_MEMORY
187 std::cout << Node::nrNodes <<
" destructing (Choice) " << this->id()
208 #ifdef GTSAM_DT_MERGING
211 if (node->isLeaf())
return node;
213 auto choice = std::static_pointer_cast<const Choice>(node);
216 auto f = std::make_shared<Choice>(choice->label(), choice->nrChoices());
219 for (
const auto& branch : choice->branches_) {
220 f->push_back(Unique(branch));
225 assert(f->branches().size() > 0);
226 auto f0 = std::static_pointer_cast<const Leaf>(f->branches_[0]);
227 return std::make_shared<Leaf>(f0->constant());
241 bool isLeaf()
const override {
return false; }
256 size_t count = f.nrChoices();
257 branches_.reserve(count);
258 for (size_t i = 0; i < count; i++) {
259 NodePtr newBranch = f.branches_[i]->apply_f_op_g(g, op);
260 push_back(std::move(newBranch));
262 }
else if (g.label() > f.label()) {
265 size_t count = g.nrChoices();
266 branches_.reserve(count);
267 for (size_t i = 0; i < count; i++) {
268 NodePtr newBranch = g.branches_[i]->apply_g_op_fC(f, op);
269 push_back(std::move(newBranch));
274 size_t count = f.nrChoices();
275 branches_.reserve(count);
276 for (
size_t i = 0; i < count; i++) {
277 NodePtr newBranch = f.branches_[i]->apply_f_op_g(*g.branches_[i], op);
278 push_back(std::move(newBranch));
288 size_t nrChoices()
const {
289 return branches_.size();
292 const std::vector<NodePtr>& branches()
const {
296 std::vector<NodePtr>& branches() {
304 allSame_ = node->sameLeaf(*
branches_.back());
310 void print(
const std::string& s,
const LabelFormatter& labelFormatter,
311 const ValueFormatter& valueFormatter)
const override {
312 std::cout << s <<
" Choice(";
313 std::cout << labelFormatter(
label_) <<
") " << std::endl;
314 for (
size_t i = 0; i <
branches_.size(); i++) {
315 branches_[i]->print(s +
" " + std::to_string(i), labelFormatter, valueFormatter);
320 void dot(std::ostream& os,
const LabelFormatter& labelFormatter,
321 const ValueFormatter& valueFormatter,
322 bool showZero)
const override {
324 os <<
"\"" << this->id() <<
"\" [shape=circle, label=\"" <<
label
327 for (
size_t i = 0; i < B; i++) {
331 if (!showZero && branch->isLeaf()) {
332 auto leaf = std::static_pointer_cast<const Leaf>(branch);
333 if (valueFormatter(leaf->constant()).compare(
"0"))
continue;
336 os <<
"\"" << this->id() <<
"\" -> \"" << branch->id() <<
"\"";
337 if (B == 2 && i == 0) os <<
" [style=dashed]";
339 branch->dot(os, labelFormatter, valueFormatter, showZero);
350 return (q.isLeaf() && q.sameLeaf(*
this));
354 bool equals(
const Node& q,
const CompareFunc& compare)
const override {
355 if (q.isLeaf())
return false;
357 if (this->label_ != other->
label_)
return false;
360 for (
size_t i = 0; i <
branches_.size(); i++)
369 typename Assignment<L>::const_iterator it = x.find(
label_);
371 std::cout <<
"Trying to find value for " <<
label_ << std::endl;
372 throw std::invalid_argument(
373 "DecisionTree::operator(): value undefined for a label");
376 size_t index = x.at(
label_);
386 push_back(branch->apply(op));
407 for (
size_t i = 0; i < f.
branches_.size(); i++) {
411 push_back(branch->apply(op, assignment_));
414 auto assignment_it = assignment_.find(
label_);
415 assignment_.erase(assignment_it);
421 auto r = std::make_shared<Choice>(
label_, *
this, op);
428 auto r = std::make_shared<Choice>(
label_, *
this, op, assignment);
437 NodePtr apply_f_op_g(
const Node& g,
const Binary& op)
const override {
438 return g.apply_g_op_fC(*
this, op);
442 NodePtr apply_g_op_fL(
const Leaf& fL,
const Binary& op)
const override {
443 auto h = std::make_shared<Choice>(label(), nrChoices());
444 for (
auto&& branch : branches_)
445 h->push_back(fL.apply_f_op_g(*branch, op));
450 NodePtr apply_g_op_fC(
const Choice& fC,
const Binary& op)
const override {
451 auto h = std::make_shared<Choice>(fC, *
this, op);
456 template<
typename OP>
457 NodePtr apply_fC_op_gL(
const Leaf& gL, OP op)
const {
458 auto h = std::make_shared<Choice>(label(), nrChoices());
459 for (
auto&& branch : branches_)
460 h->push_back(branch->apply_f_op_g(gL, op));
471 r->push_back(branch->choose(
label, index));
480#if GTSAM_ENABLE_BOOST_SERIALIZATION
482 friend class boost::serialization::access;
483 template <
class ARCHIVE>
484 void serialize(ARCHIVE& ar,
const unsigned int ) {
485 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
486 ar& BOOST_SERIALIZATION_NVP(label_);
487 ar& BOOST_SERIALIZATION_NVP(branches_);
488 ar& BOOST_SERIALIZATION_NVP(allSame_);
496 template <
typename L,
typename Y>
499 template<
typename L,
typename Y>
504 template<
typename L,
typename Y>
510 template <
typename L,
typename Y>
512 auto a = std::make_shared<Choice>(label, 2);
514 a->push_back(std::move(l1));
515 a->push_back(std::move(l2));
520 template <
typename L,
typename Y>
523 if (labelC.second != 2)
throw std::invalid_argument(
524 "DecisionTree: binary constructor called with non-binary label");
525 auto a = std::make_shared<Choice>(labelC.first, 2);
527 a->push_back(std::move(l1));
528 a->push_back(std::move(l2));
532 template<
typename L,
typename Y>
534 const std::vector<Y>& ys) {
536 root_ =
create(labelCs.begin(), labelCs.end(), ys.begin(), ys.end());
540 template<
typename L,
typename Y>
542 const std::string& table) {
545 std::istringstream iss(table);
546 copy(std::istream_iterator<Y>(iss), std::istream_iterator<Y>(),
550 root_ =
create(labelCs.begin(), labelCs.end(), ys.begin(), ys.end());
554 template<
typename L,
typename Y>
556 Iterator begin, Iterator end,
const L& label) {
557 root_ = compose(begin, end, label);
561 template<
typename L,
typename Y>
564 const std::vector<DecisionTree> functions{f0, f1};
565 root_ = compose(functions.begin(), functions.end(), label);
569 template <
typename L,
typename Y>
572 :
root_(std::move(other.root_)) {
579 if (node->isLeaf()) {
581 auto leaf = std::static_pointer_cast<Leaf>(node);
582 leaf->constant_ = op(leaf->constant_);
585 auto choice = std::static_pointer_cast<Choice>(node);
586 for (
NodePtr& branch : choice->branches()) {
593 ApplyUnary applyUnary{op};
597 other.root_ =
nullptr;
601 template <
typename L,
typename Y>
602 template <
typename X,
typename Func>
609 template <
typename L,
typename Y>
610 template <
typename M,
typename X,
typename Func>
612 const std::map<M, L>& map, Func Y_of_X) {
613 auto L_of_M = [&map](
const M& label) -> L {
return map.at(label); };
623 template <
typename L,
typename Y>
624 template <
typename Iterator>
626 Iterator begin, Iterator end,
const L& label) {
628 std::optional<L> highestLabel;
629 size_t nrChoices = 0;
630 for (Iterator it = begin; it != end; it++) {
631 if (it->root_->isLeaf())
633 auto c = std::static_pointer_cast<const Choice>(it->root_);
634 if (!highestLabel || c->label() > *highestLabel) {
635 highestLabel = c->label();
636 nrChoices = c->nrChoices();
641 if (!nrChoices || !highestLabel || label > *highestLabel) {
642 auto choiceOnLabel = std::make_shared<Choice>(label, end - begin);
643 for (Iterator it = begin; it != end; it++) {
644 NodePtr root = it->root_;
645 choiceOnLabel->push_back(std::move(root));
648 return choiceOnLabel;
651 auto choiceOnHighestLabel =
652 std::make_shared<Choice>(*highestLabel, nrChoices);
654 for (
size_t index = 0; index < nrChoices; index++) {
657 std::vector<DecisionTree> functions;
658 for (Iterator it = begin; it != end; it++) {
661 functions.push_back(chosen);
664 NodePtr fi = compose(functions.begin(), functions.end(), label);
665 choiceOnHighestLabel->push_back(std::move(fi));
667 return choiceOnHighestLabel;
692 template<
typename L,
typename Y>
693 template<
typename It,
typename ValueIt>
695 It begin, It end, ValueIt beginY, ValueIt endY) {
697 size_t nrChoices = begin->second;
698 size_t size = endY - beginY;
701 It labelC = begin + 1;
705 if (size != nrChoices) {
706 std::cout <<
"Trying to create DD on " << begin->first << std::endl;
707 std::cout <<
"DecisionTree::create: expected " << nrChoices
708 <<
" values but got " << size <<
" instead" << std::endl;
709 throw std::invalid_argument(
"DecisionTree::create invalid argument");
711 auto choice = std::make_shared<Choice>(begin->first, endY - beginY);
712 for (ValueIt y = beginY; y != endY; y++) {
721 std::vector<DecisionTree> functions;
722 functions.reserve(nrChoices);
723 size_t split = size / nrChoices;
724 for (
size_t i = 0; i < nrChoices; i++, beginY +=
split) {
726 functions.emplace_back(f);
728 return compose(functions.begin(), functions.end(), begin->first);
734 template<
typename L,
typename Y>
735 template<
typename It,
typename ValueIt>
737 It begin, It end, ValueIt beginY, ValueIt endY) {
738 auto node =
build(begin, end, beginY, endY);
743 template <
typename L,
typename Y>
744 template <
typename X>
747 std::function<Y(
const X&)> Y_of_X) {
753 auto leaf = std::static_pointer_cast<LXLeaf>(f);
754 return NodePtr(
new Leaf(Y_of_X(leaf->constant())));
758 auto choice = std::static_pointer_cast<const LXChoice>(f);
761 auto newChoice = std::make_shared<Choice>(choice->label(), choice->nrChoices());
764 for (
auto&& branch : choice->branches()) {
772 template <
typename L,
typename Y>
773 template <
typename M,
typename X>
776 std::function<L(
const M&)> L_of_M, std::function<Y(
const X&)> Y_of_X) {
783 auto leaf = std::static_pointer_cast<const MXLeaf>(f);
784 return NodePtr(
new Leaf(Y_of_X(leaf->constant())));
788 auto choice = std::static_pointer_cast<const MXChoice>(f);
791 const M oldLabel = choice->label();
792 const L newLabel = L_of_M(oldLabel);
802 std::vector<LY> functions;
803 for (
auto&& branch : choice->branches()) {
807 LY::compose(functions.begin(), functions.end(), newLabel));
821 template <
typename L,
typename Y>
823 using F = std::function<void(
const Y&)>;
832 if (node->isLeaf()) {
833 auto leaf = std::static_pointer_cast<const Leaf>(node);
834 return f(leaf->constant());
837 auto choice = std::static_pointer_cast<const Choice>(node);
838 for (
auto&& branch : choice->branches()) (*this)(branch);
842 template <
typename L,
typename Y>
843 template <
typename Func>
859 template <
typename L,
typename Y>
870 if (node->isLeaf()) {
871 auto leaf = std::static_pointer_cast<const Leaf>(node);
875 auto choice = std::static_pointer_cast<const Choice>(node);
876 for (
auto&& branch : choice->branches()) (*this)(branch);
880 template <
typename L,
typename Y>
881 template <
typename Func>
894 template <
typename L,
typename Y>
896 using F = std::function<void(
const Assignment<L>&,
const Y&)>;
906 if (node->isLeaf()) {
907 auto leaf = std::static_pointer_cast<const Leaf>(node);
913 auto choice = std::static_pointer_cast<const Choice>(node);
914 for (
size_t i = 0; i < choice->nrChoices(); i++) {
917 (*this)(choice->branches()[i]);
920 auto choice_it =
assignment.find(choice->label());
926 template <
typename L,
typename Y>
927 template <
typename Func>
934 template <
typename L,
typename Y>
937 visit([&total](
const Y& node) { total += 1; });
943 template <
typename L,
typename Y>
944 template <
typename Func,
typename X>
946 visit([&](
const Y& y) { x0 = f(y, x0); });
964 template <
typename L,
typename Y>
968 for (
auto&& kv : assignment) {
969 unique.insert(kv.first);
977 template <
typename L,
typename Y>
978 bool DecisionTree<L, Y>::equals(
const DecisionTree& other,
979 const CompareFunc& compare)
const {
980 return root_->equals(*other.
root_, compare);
983 template <
typename L,
typename Y>
985 const LabelFormatter& labelFormatter,
986 const ValueFormatter& valueFormatter)
const {
987 root_->print(s, labelFormatter, valueFormatter);
990 template<
typename L,
typename Y>
996 template<
typename L,
typename Y>
998 if (
root_ ==
nullptr)
999 throw std::invalid_argument(
1000 "DecisionTree::operator() called on empty tree");
1001 return root_->operator ()(x);
1005 template<
typename L,
typename Y>
1009 throw std::runtime_error(
1010 "DecisionTree::apply(unary op) undefined for empty tree.");
1017 template <
typename L,
typename Y>
1019 const UnaryAssignment& op)
const {
1022 throw std::runtime_error(
1023 "DecisionTree::apply(unary op) undefined for empty tree.");
1030 template<
typename L,
typename Y>
1032 const Binary& op)
const {
1035 throw std::runtime_error(
1036 "DecisionTree::apply(binary op) undefined for empty trees.");
1054 template<
typename L,
typename Y>
1056 size_t cardinality,
const Binary& op)
const {
1058 for (
size_t index = 1; index < cardinality; index++) {
1060 result = result.
apply(chosen, op);
1066 template <
typename L,
typename Y>
1068 const LabelFormatter& labelFormatter,
1069 const ValueFormatter& valueFormatter,
1070 bool showZero)
const {
1071 os <<
"digraph G {\n";
1072 root_->dot(os, labelFormatter, valueFormatter, showZero);
1073 os <<
" [ordering=out]}" << std::endl;
1076 template <
typename L,
typename Y>
1078 const LabelFormatter& labelFormatter,
1079 const ValueFormatter& valueFormatter,
1080 bool showZero)
const {
1081 std::ofstream os((name +
".dot").c_str());
1082 dot(os, labelFormatter, valueFormatter, showZero);
1083#if defined(__APPLE__) && TARGET_OS_IPHONE
1090 system((
"dot -Tpdf " + name +
".dot -o " + name +
".pdf >& /dev/null")
1093 throw std::runtime_error(
"DecisionTree::dot system call failed");
1097 template <
typename L,
typename Y>
1099 const ValueFormatter& valueFormatter,
1100 bool showZero)
const {
1101 std::stringstream ss;
1102 dot(ss, labelFormatter, valueFormatter, showZero);
1107 template <
typename L,
typename Y>
1108 template <
typename A,
typename B>
1110 std::function<std::pair<A, B>(
const Y&)> AB_of_Y)
const {
1111 using AB = std::pair<A, B>;
Decision Tree for use in DiscreteFactors.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
double dot(const V1 &a, const V2 &b)
Dot product.
Definition Vector.h:191
An assignment from labels to value index (size_t).
Definition Assignment.h:37
Definition DecisionTree-inl.h:53
NodePtr choose(const L &label, size_t index) const override
choose a branch, create new memory !
Definition DecisionTree-inl.h:141
const Y & operator()(const Assignment< L > &x) const override
evaluate
Definition DecisionTree-inl.h:102
NodePtr apply(const UnaryAssignment &op, const Assignment< L > &assignment) const override
Apply unary operator with assignment.
Definition DecisionTree-inl.h:113
bool equals(const Node &q, const CompareFunc &compare) const override
equality up to tolerance
Definition DecisionTree-inl.h:79
Y constant_
constant stored in this leaf
Definition DecisionTree-inl.h:55
void print(const std::string &s, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter) const override
print
Definition DecisionTree-inl.h:86
NodePtr apply(const Unary &op) const override
apply unary operator
Definition DecisionTree-inl.h:107
Leaf(const Y &constant)
Constructor from constant.
Definition DecisionTree-inl.h:61
bool sameLeaf(const Leaf &q) const override
Leaf-Leaf equality.
Definition DecisionTree-inl.h:69
void dot(std::ostream &os, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter, bool showZero) const override
Write graphviz format to stream os.
Definition DecisionTree-inl.h:92
Leaf()
Default constructor for serialization.
Definition DecisionTree-inl.h:58
bool sameLeaf(const Node &q) const override
polymorphic equality: is q a leaf and is it the same as this leaf?
Definition DecisionTree-inl.h:74
const Y & constant() const
Return the constant.
Definition DecisionTree-inl.h:64
Definition DecisionTree-inl.h:165
NodePtr apply(const Unary &op) const override
apply unary operator.
Definition DecisionTree-inl.h:420
void push_back(NodePtr &&node)
add a branch: TODO merge into constructor
Definition DecisionTree-inl.h:301
Choice(const L &label, const Choice &f, const UnaryAssignment &op, const Assignment< L > &assignment)
Constructor which accepts a UnaryAssignment op and the corresponding assignment.
Definition DecisionTree-inl.h:400
const L & label() const
Return the label of this choice node.
Definition DecisionTree-inl.h:284
void print(const std::string &s, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter) const override
print (as a tree).
Definition DecisionTree-inl.h:310
static NodePtr Unique(const NodePtr &node)
Merge branches with equal leaf values for every choice node in a decision tree.
Definition DecisionTree-inl.h:235
NodePtr apply(const UnaryAssignment &op, const Assignment< L > &assignment) const override
Apply unary operator with assignment.
Definition DecisionTree-inl.h:426
L label_
the label of the variable on which we split
Definition DecisionTree-inl.h:167
bool sameLeaf(const Node &q) const override
polymorphic equality: if q is a leaf, could be...
Definition DecisionTree-inl.h:349
Choice(const Choice &f, const Choice &g, const Binary &op)
Construct from applying binary op to two Choice nodes.
Definition DecisionTree-inl.h:250
std::vector< NodePtr > branches_
The children of this Choice node.
Definition DecisionTree-inl.h:170
Choice()
Default constructor for serialization.
Definition DecisionTree-inl.h:183
const Y & operator()(const Assignment< L > &x) const override
evaluate
Definition DecisionTree-inl.h:367
Choice(const L &label, size_t count)
Constructor, given choice label and mandatory expected branch count.
Definition DecisionTree-inl.h:244
NodePtr choose(const L &label, size_t index) const override
choose a branch, recursively
Definition DecisionTree-inl.h:465
Choice(const L &label, const Choice &f, const Unary &op)
Construct from applying unary op to a Choice node.
Definition DecisionTree-inl.h:382
void dot(std::ostream &os, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter, bool showZero) const override
output to graphviz (as a a graph)
Definition DecisionTree-inl.h:320
bool sameLeaf(const Leaf &q) const override
Choice-Leaf equality: always false.
Definition DecisionTree-inl.h:344
bool equals(const Node &q, const CompareFunc &compare) const override
equality
Definition DecisionTree-inl.h:354
Functor performing depth-first visit to each leaf with the leaf value as the argument.
Definition DecisionTree-inl.h:822
F f
folding function object.
Definition DecisionTree-inl.h:825
void operator()(const typename DecisionTree< L, Y >::NodePtr &node) const
Do a depth-first visit on the tree rooted at node.
Definition DecisionTree-inl.h:828
Visit(F f)
Construct from folding function.
Definition DecisionTree-inl.h:824
Functor performing depth-first visit to each leaf with the Leaf object passed as an argument.
Definition DecisionTree-inl.h:860
VisitLeaf(F f)
Construct from folding function.
Definition DecisionTree-inl.h:862
void operator()(const typename DecisionTree< L, Y >::NodePtr &node) const
Do a depth-first visit on the tree rooted at node.
Definition DecisionTree-inl.h:866
F f
folding function object.
Definition DecisionTree-inl.h:863
Functor performing depth-first visit to each leaf with the leaf's Assignment<L> and value passed as a...
Definition DecisionTree-inl.h:895
VisitWith(F f)
Construct from folding function.
Definition DecisionTree-inl.h:897
Assignment< L > assignment
Assignment, mutating through recursion.
Definition DecisionTree-inl.h:898
void operator()(const typename DecisionTree< L, Y >::NodePtr &node)
Do a depth-first visit on the tree rooted at node.
Definition DecisionTree-inl.h:902
F f
folding function object.
Definition DecisionTree-inl.h:899
a decision tree is a function from assignments to values.
Definition DecisionTree.h:62
DecisionTree apply(const Unary &op) const
apply Unary operation "op" to f
Definition DecisionTree-inl.h:1006
DecisionTree choose(const L &label, size_t index) const
create a new function where value(label)==index It's like "restrict" in Darwiche09book pg329,...
Definition DecisionTree.h:391
typename Node::Ptr NodePtr
---------------------— Node base class ------------------------—
Definition DecisionTree.h:146
static NodePtr build(It begin, It end, ValueIt beginY, ValueIt endY)
Internal recursive function to create from keys, cardinalities, and Y values.
Definition DecisionTree-inl.h:694
std::set< L > labels() const
Retrieve all unique labels as a set.
Definition DecisionTree-inl.h:965
bool empty() const
Check if tree is empty.
Definition DecisionTree.h:290
void visit(Func f) const
Visit all leaves in depth-first fashion.
Definition DecisionTree-inl.h:844
void visitLeaf(Func f) const
Visit all leaves in depth-first fashion.
Definition DecisionTree-inl.h:882
std::function< Y(const Y &)> Unary
Handy typedefs for unary and binary function types.
Definition DecisionTree.h:75
X fold(Func f, X x0) const
Fold a binary function over the tree, returning accumulator.
Definition DecisionTree-inl.h:945
NodePtr root_
A DecisionTree just contains the root. TODO(dellaert): make protected.
Definition DecisionTree.h:149
void print(const std::string &s, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter) const
GTSAM-style print.
Definition DecisionTree-inl.h:984
DecisionTree combine(const L &label, size_t cardinality, const Binary &op) const
combine subtrees on key with binary operation "op"
Definition DecisionTree-inl.h:1055
void visitWith(Func f) const
Visit all leaves in depth-first fashion.
Definition DecisionTree-inl.h:928
const Y & operator()(const Assignment< L > &x) const
evaluate
Definition DecisionTree-inl.h:997
void dot(std::ostream &os, const LabelFormatter &labelFormatter, const ValueFormatter &valueFormatter, bool showZero=true) const
output to graphviz format, stream version
Definition DecisionTree-inl.h:1067
std::pair< DecisionTree< L, A >, DecisionTree< L, B > > split(std::function< std::pair< A, B >(const Y &)> AB_of_Y) const
Convert into two trees with value types A and B.
Definition DecisionTree-inl.h:1109
static NodePtr convertFrom(const typename DecisionTree< L, X >::NodePtr &f, std::function< Y(const X &)> Y_of_X)
Convert from a DecisionTree<L, X> to DecisionTree<L, Y>.
Definition DecisionTree-inl.h:745
bool operator==(const DecisionTree &q) const
equality
Definition DecisionTree-inl.h:991
std::pair< L, size_t > LabelC
A label annotated with cardinality.
Definition DecisionTree.h:80
size_t nrLeaves() const
Return the number of leaves in the tree.
Definition DecisionTree-inl.h:935
static NodePtr create(It begin, It end, ValueIt beginY, ValueIt endY)
Internal helper function to create a tree from keys, cardinalities, and Y values.
Definition DecisionTree-inl.h:736
DecisionTree()
Default constructor (for serialization).
Definition DecisionTree-inl.h:497
---------------------— Node base class ------------------------—
Definition DecisionTree.h:87