00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <string.h>
00015 #include <algorithm>
00016 #include "base/hash.h"
00017 #include <limits>
00018 #include <map>
00019 #include <set>
00020 #include <string>
00021 #include <vector>
00022
00023 #include "base/integral_types.h"
00024 #include "base/logging.h"
00025 #include "base/scoped_ptr.h"
00026 #include "base/stringprintf.h"
00027 #include "base/file.h"
00028 #include "base/concise_iterator.h"
00029 #include "base/map-util.h"
00030 #include "base/stl_util.h"
00031 #include "base/hash.h"
00032 #include "constraint_solver/constraint_solver.h"
00033 #include <iostream>
00034 #include <fstream>
00035 #include "util/xml_helper.h"
00036
00037 namespace operations_research {
00038
00039
00040 struct NaturalLess {
00041 bool operator()(const string& s1, const string& s2) const {
00042 int start = 0;
00043 int length = std::min(s1.length(), s2.length());
00044
00045 while (start < length) {
00046
00047 while (start < length && s1[start] == s2[start] &&
00048 (s1[start] < '0' || s1[start] > '9')) {
00049 ++start;
00050 }
00051
00052
00053
00054 if (start == length) {
00055 return s1.length() < s2.length();
00056 }
00057
00058 int number_s1 = 0;
00059 int number_s2 = 0;
00060
00061
00062 for (int i = start;
00063 i < s1.length() && s1[i] >= '0' && s1[i] <= '9';
00064 ++i) {
00065 number_s1 = number_s1 * 10 + (s1[i] - '0');
00066 }
00067
00068 for (; start < s2.length() && s2[start] >= '0' && s2[start] <= '9';
00069 ++start) {
00070 number_s2 = number_s2 * 10 + (s2[start] - '0');
00071 }
00072
00073
00074 if (number_s1 && number_s2) {
00075
00076
00077 if (number_s1 != number_s2) {
00078 return number_s1 < number_s2;
00079 }
00080 } else {
00081 return s1.compare(s2) < 0;
00082 }
00083 }
00084
00085 return s1.length() < s2.length();
00086 }
00087 };
00088
00089 bool CompareStringsUsingNaturalLess(const string& s1, const string& s2) {
00090 return NaturalLess()(s1, s2);
00091 }
00092
00093 class XmlHelper;
00094
00095 namespace {
00096 const char* kConfigXml =
00097 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00098 "<configuration version=\"1.0\">\n"
00099 " <tool show=\"tree\" fileroot=\"tree\" display=\"expanded\""
00100 " repeat=\"all\"/>\n"
00101 " <tool show=\"viz\" fileroot=\"viz\" repeat=\"all\"/>\n"
00102 "</configuration>";
00103
00104
00105 class TreeNode;
00106
00107
00108
00109 class TreeDecisionVisitor : public DecisionVisitor {
00110 public:
00111 TreeDecisionVisitor() {}
00112 virtual ~TreeDecisionVisitor() {}
00113
00114 virtual void VisitSetVariableValue(IntVar* const var, int64 value) {
00115 name_ = var->name();
00116 value_ = value;
00117 valid_ = true;
00118 }
00119
00120 virtual void VisitSplitVariableDomain(IntVar* const var,
00121 int64 value,
00122 bool start_with_lower_half) {
00123 name_ = var->name();
00124 value_ = value;
00125 valid_ = true;
00126 }
00127
00128 virtual void VisitScheduleOrPostpone(IntervalVar* const var, int64 est) {
00129 name_ = var->name();
00130 value_ = est;
00131 valid_ = true;
00132 }
00133
00134 virtual void VisitTryRankFirst(SequenceVar* const sequence, int index) {
00135 name_ = sequence->name();
00136 value_ = index;
00137 valid_ = true;
00138 }
00139
00140 virtual void VisitTryRankLast(SequenceVar* const sequence, int index) {
00141 name_ = sequence->name();
00142 value_ = index;
00143 valid_ = true;
00144 }
00145
00146 virtual void VisitUnknownDecision() {
00147 valid_ = false;
00148 }
00149
00150
00151 bool valid() { return valid_; }
00152
00153
00154 const string& name() {
00155 CHECK(valid_);
00156 return name_;
00157 }
00158
00159
00160 int64 value() {
00161 CHECK(valid_);
00162 return value_;
00163 }
00164
00165 private:
00166 string name_;
00167 int64 value_;
00168 bool valid_;
00169 };
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 class TreeMonitor: public SearchMonitor {
00183 public:
00184 typedef hash_map<string, IntVar const*> IntVarMap;
00185
00186 TreeMonitor(Solver* const solver, const IntVar* const* vars, int size,
00187 const string& filename_tree, const string& filename_visualizer);
00188
00189 TreeMonitor(Solver* const solver, const IntVar* const* vars, int size,
00190 string* const tree_xml, string* const visualization_xml);
00191
00192 TreeMonitor(Solver* const solver, const IntVar* const* vars, int size,
00193 const string& filename_config, const string& filename_tree,
00194 const string& filename_visualizer);
00195
00196 TreeMonitor(Solver* const solver, const IntVar* const* vars, int size,
00197 string* const config_xml, string* const tree_xml,
00198 string* const visualization_xml);
00199
00200 ~TreeMonitor();
00201
00202
00203 virtual void EnterSearch();
00204
00205
00206
00207 virtual void EndNextDecision(DecisionBuilder* const decision_builder,
00208 Decision* const decision);
00209
00210 virtual void ExitSearch();
00211
00212
00213 virtual string DebugString() const;
00214
00215
00216 string GenerateTreeXML() const;
00217
00218
00219 string GenerateVisualizationXML() const;
00220
00221
00222
00223
00224 virtual void RefuteDecision(Decision* const decision);
00225
00226
00227 static string StripSpecialCharacters(string attribute);
00228
00229 private:
00230
00231 void Init(const IntVar* const* vars, int size);
00232
00233 string* const config_xml_;
00234 TreeNode* current_node_;
00235 const string filename_config_;
00236 const string filename_tree_;
00237 const string filename_visualizer_;
00238 int id_counter_;
00239 string last_decision_;
00240 hash_map<string, int64> last_value_;
00241 string last_variable_;
00242 int64 min_;
00243 int64 max_;
00244 scoped_ptr<TreeNode> root_node_;
00245 int search_level_;
00246 string* const tree_xml_;
00247 IntVarMap vars_;
00248 string* const visualization_xml_;
00249 };
00250
00251
00252
00253 class TreeNode {
00254 public:
00255 typedef std::map<string, std::vector<int64>, NaturalLess> DomainMap;
00256 enum TreeNodeType { ROOT, TRY, FAIL, SOLUTION };
00257
00258 TreeNode(TreeNode* parent, int id)
00259 : cycles_(1),
00260 id_(id),
00261 name_(""),
00262 node_type_(TRY),
00263 parent_(parent) {}
00264
00265 ~TreeNode() {
00266 STLDeleteElements(&children_);
00267 }
00268
00269
00270 int64 branch_value(int branch) const { return branch_values_[branch]; }
00271
00272
00273 const DomainMap& domain() const { return domain_; }
00274
00275
00276 void SetDomain(TreeMonitor::IntVarMap const& vars) {
00277 domain_.clear();
00278
00279 for (ConstIter<TreeMonitor::IntVarMap> it(vars); !it.at_end(); ++it) {
00280 std::vector<int64> domain;
00281
00282 scoped_ptr<IntVarIterator> intvar_it(
00283 it->second->MakeDomainIterator(false));
00284
00285 for (intvar_it->Init(); intvar_it->Ok(); intvar_it->Next()) {
00286 domain.push_back(intvar_it->Value());
00287 }
00288
00289 domain_[it->first] = domain;
00290 }
00291 }
00292
00293
00294 void SetDomain(DomainMap const& domain) { domain_ = domain; }
00295
00296
00297 int id() const { return id_; }
00298
00299
00300 const string& name() const { return name_; }
00301
00302
00303 void set_name(const string& name) { name_ = name; }
00304
00305
00306 TreeNodeType node_type() const { return node_type_; }
00307
00308
00309 void set_node_type(TreeNodeType node_type) { node_type_ = node_type; }
00310
00311
00312 TreeNode* Parent() {
00313 return --cycles_ ? this : parent_;
00314 }
00315
00316
00317 void AddCycle() {
00318 cycles_++;
00319 }
00320
00321
00322 bool AddChild(int id, const string& name,
00323 hash_map<string, int64> const& last_value, bool is_final_node,
00324 TreeMonitor::IntVarMap const& vars, TreeNode** child) {
00325 CHECK_NOTNULL(child);
00326
00327 if (!is_final_node) {
00328 for (int i = 0; i < children_.size(); ++i) {
00329
00330 if (children_[i]->name_ == name &&
00331 branch_values_[i] == FindOrDie(last_value, name_)) {
00332 children_[i]->AddCycle();
00333 *child = children_[i];
00334 return false;
00335 }
00336 }
00337 }
00338
00339 TreeNode* tree_node(new TreeNode(this, id));
00340 tree_node->set_name(name);
00341 tree_node->SetDomain(vars);
00342 children_.push_back(tree_node);
00343 branch_values_.push_back(FindOrDie(last_value, name_));
00344 *child = tree_node;
00345
00346 return true;
00347 }
00348
00349
00350 void GenerateVisualizationXML(XmlHelper* const visualization_writer) {
00351 CHECK_NOTNULL(visualization_writer);
00352
00353
00354 const int kVisualizerState = 0;
00355
00356 visualization_writer->StartElement("state");
00357 visualization_writer->AddAttribute("id", id_);
00358 visualization_writer->AddAttribute("tree_node", id_);
00359 visualization_writer->StartElement("visualizer_state");
00360 visualization_writer->AddAttribute("id", kVisualizerState);
00361
00362 int index = 0;
00363 int name = -1;
00364
00365 for (ConstIter<DomainMap> it(domain_); !it.at_end(); ++it) {
00366 std::vector<int64> current = it->second;
00367 visualization_writer->StartElement(current.size() == 1 ?
00368 "integer" :
00369 "dvar");
00370 visualization_writer->AddAttribute("index", ++index);
00371
00372 if (it->first == name_) {
00373 name = index;
00374 }
00375
00376 if (current.size() > 1
00377 && current.size() == (current.back() - current[0] + 1)) {
00378
00379 visualization_writer->AddAttribute(
00380 "domain",
00381 StringPrintf("%" GG_LL_FORMAT "d .. %" GG_LL_FORMAT "d",
00382 current[0], current.back()));
00383 } else {
00384
00385 string domain;
00386
00387 for (int j = 0; j < current.size(); ++j) {
00388 StringAppendF(&domain, " %" GG_LL_FORMAT "d", current[j]);
00389 }
00390
00391 visualization_writer->AddAttribute(current.size() == 1 ?
00392 "value" :
00393 "domain", domain.substr(1));
00394 }
00395
00396 visualization_writer->EndElement();
00397 }
00398
00399 if (node_type_ == FAIL) {
00400 visualization_writer->StartElement("failed");
00401 visualization_writer->AddAttribute("index", name);
00402 visualization_writer->AddAttribute(
00403 "value",
00404 StringPrintf("%" GG_LL_FORMAT "d", parent_->branch_value(0)));
00405 visualization_writer->EndElement();
00406 } else if (node_type_ == TRY) {
00407 visualization_writer->StartElement("focus");
00408 visualization_writer->AddAttribute("index", name);
00409 visualization_writer->EndElement();
00410 }
00411
00412 visualization_writer->EndElement();
00413 visualization_writer->EndElement();
00414
00415 for (int i = 0; i < children_.size(); ++i) {
00416 children_[i]->GenerateVisualizationXML(visualization_writer);
00417 }
00418 }
00419
00420
00421 void GenerateTreeXML(XmlHelper* const tree_writer) {
00422 CHECK_NOTNULL(tree_writer);
00423
00424
00425 const char* kElementName[] = { "root", "try", "fail", "try" };
00426
00427 if (node_type_ == ROOT) {
00428 tree_writer->StartElement(kElementName[node_type_]);
00429 tree_writer->AddAttribute("id", id_);
00430 tree_writer->EndElement();
00431 }
00432
00433 for (int i = 0; i < children_.size(); ++i) {
00434 TreeNode* child = children_[i];
00435 tree_writer->StartElement(kElementName[child->node_type_]);
00436 tree_writer->AddAttribute("id", child->id_);
00437 tree_writer->AddAttribute("parent", id_);
00438 tree_writer->AddAttribute("name",
00439 TreeMonitor::StripSpecialCharacters(name_));
00440
00441 if (name_.empty()) {
00442 tree_writer->AddAttribute("size", "0");
00443 tree_writer->AddAttribute("value", "0");
00444 } else {
00445
00446 const DomainMap& domain = parent_ && parent_->children_.size() ?
00447 parent_->children_[0]->domain() :
00448 domain_;
00449
00450 const std::vector<int64>* const domain_values = FindOrNull(domain, name_);
00451 if (domain_values) {
00452 tree_writer->AddAttribute("size",
00453 StringPrintf("%zu", domain_values->size()));
00454 } else {
00455 tree_writer->AddAttribute("size", "unknown");
00456 }
00457 tree_writer->AddAttribute("value", StringPrintf("%" GG_LL_FORMAT "d",
00458 branch_values_[i]));
00459 }
00460
00461 tree_writer->EndElement();
00462
00463 if (child->node_type_ == SOLUTION) {
00464
00465 tree_writer->StartElement("succ");
00466 tree_writer->AddAttribute("id", child->id_);
00467 tree_writer->EndElement();
00468 }
00469
00470 children_[i]->GenerateTreeXML(tree_writer);
00471 }
00472 }
00473
00474 private:
00475 std::vector<int64> branch_values_;
00476 std::vector<TreeNode*> children_;
00477 int cycles_;
00478 DomainMap domain_;
00479 const int id_;
00480 string name_;
00481 TreeNodeType node_type_;
00482 TreeNode* const parent_;
00483 };
00484
00485 TreeMonitor::TreeMonitor(Solver* const solver, const IntVar* const* vars,
00486 int size, const string& filename_tree,
00487 const string& filename_visualizer)
00488 : SearchMonitor(solver),
00489 config_xml_(NULL),
00490 current_node_(NULL),
00491 filename_config_(""),
00492 filename_tree_(filename_tree),
00493 filename_visualizer_(filename_visualizer),
00494 root_node_(NULL),
00495 search_level_(0),
00496 tree_xml_(NULL),
00497 visualization_xml_(NULL) {
00498 CHECK_NOTNULL(solver);
00499 CHECK_NOTNULL(vars);
00500
00501 Init(vars, size);
00502 }
00503
00504 TreeMonitor::TreeMonitor(Solver* const solver, const IntVar* const* vars,
00505 int size, string* const tree_xml,
00506 string* const visualization_xml)
00507 : SearchMonitor(solver),
00508 config_xml_(NULL),
00509 current_node_(NULL),
00510 filename_config_(""),
00511 filename_tree_(""),
00512 filename_visualizer_(""),
00513 root_node_(NULL),
00514 search_level_(0),
00515 tree_xml_(tree_xml),
00516 visualization_xml_(visualization_xml) {
00517 CHECK_NOTNULL(solver);
00518 CHECK_NOTNULL(vars);
00519 CHECK_NOTNULL(tree_xml);
00520 CHECK_NOTNULL(visualization_xml);
00521
00522 Init(vars, size);
00523 }
00524
00525 TreeMonitor::TreeMonitor(Solver* const solver, const IntVar* const* vars,
00526 int size, const string& filename_config,
00527 const string& filename_tree,
00528 const string& filename_visualizer)
00529 : SearchMonitor(solver),
00530 config_xml_(NULL),
00531 current_node_(NULL),
00532 filename_config_(filename_config),
00533 filename_tree_(filename_tree),
00534 filename_visualizer_(filename_visualizer),
00535 root_node_(NULL),
00536 search_level_(0),
00537 tree_xml_(NULL),
00538 visualization_xml_(NULL) {
00539 CHECK_NOTNULL(solver);
00540 CHECK_NOTNULL(vars);
00541
00542 Init(vars, size);
00543 }
00544
00545 TreeMonitor::TreeMonitor(Solver* const solver, const IntVar* const* vars,
00546 int size, string* const config_xml,
00547 string* const tree_xml,
00548 string* const visualization_xml)
00549 : SearchMonitor(solver),
00550 config_xml_(config_xml),
00551 current_node_(NULL),
00552 filename_config_(""),
00553 filename_tree_(""),
00554 filename_visualizer_(""),
00555 root_node_(NULL),
00556 search_level_(0),
00557 tree_xml_(tree_xml),
00558 visualization_xml_(visualization_xml) {
00559 CHECK_NOTNULL(solver);
00560 CHECK_NOTNULL(vars);
00561 CHECK_NOTNULL(config_xml);
00562 CHECK_NOTNULL(tree_xml);
00563 CHECK_NOTNULL(visualization_xml);
00564
00565 Init(vars, size);
00566 }
00567
00568 TreeMonitor::~TreeMonitor() {}
00569
00570 void TreeMonitor::Init(const IntVar* const* vars, int size) {
00571 min_ = std::numeric_limits<int64>::max();
00572 max_ = std::numeric_limits<int64>::min();
00573
00574
00575 for (int i = 0; i < size; ++i) {
00576 min_ = std::min(min_, vars[i]->Min());
00577 max_ = std::max(max_, vars[i]->Max());
00578
00579 string name = vars[i]->name();
00580
00581 if (name.empty()) {
00582 name = StringPrintf("%d", i);
00583 }
00584
00585 vars_[name] = vars[i];
00586 }
00587 }
00588
00589 void TreeMonitor::EnterSearch() {
00590 if (!root_node_.get()) {
00591 id_counter_ = 0;
00592 root_node_.reset(new TreeNode(NULL, id_counter_++));
00593 root_node_->set_node_type(TreeNode::ROOT);
00594 root_node_->SetDomain(vars_);
00595 current_node_ = root_node_.get();
00596 last_value_[""] = 0;
00597 }
00598
00599 ++search_level_;
00600
00601 VLOG(1) << "Current search level " << search_level_;
00602 }
00603
00604 void TreeMonitor::EndNextDecision(DecisionBuilder* const decision_builder,
00605 Decision* const decision) {
00606 if (decision) {
00607 TreeDecisionVisitor visitor;
00608 decision->Accept(&visitor);
00609
00610 if (visitor.valid()) {
00611 last_variable_ = visitor.name();
00612 last_value_[last_variable_] = visitor.value();
00613 }
00614 }
00615
00616 if (!decision || decision->DebugString() != last_decision_) {
00617 if (current_node_->AddChild(id_counter_, last_variable_, last_value_,
00618 !decision , vars_, ¤t_node_)) {
00619 ++id_counter_;
00620 }
00621 } else {
00622 current_node_->AddCycle();
00623 }
00624
00625 last_decision_ = decision ? decision->DebugString() : "";
00626
00627 if (!decision) {
00628 current_node_->set_node_type(TreeNode::SOLUTION);
00629 }
00630 }
00631
00632 void TreeMonitor::RefuteDecision(Decision* const decision) {
00633
00634
00635
00636 CHECK_NOTNULL(decision);
00637
00638 if (current_node_->node_type() == TreeNode::SOLUTION) {
00639
00640
00641
00642 current_node_ = current_node_->Parent();
00643 } else if (current_node_->node_type() == TreeNode::TRY) {
00644
00645
00646 current_node_->set_node_type(TreeNode::TRY);
00647
00648 if (current_node_->AddChild(id_counter_, last_variable_,
00649 last_value_, true, vars_, ¤t_node_)) {
00650 ++id_counter_;
00651 }
00652
00653 current_node_->set_node_type(TreeNode::FAIL);
00654 current_node_ = current_node_->Parent();
00655 }
00656
00657 current_node_ = current_node_->Parent();
00658 }
00659
00660 string TreeMonitor::GenerateTreeXML() const {
00661 XmlHelper xml_writer;
00662 xml_writer.StartDocument();
00663
00664 xml_writer.StartElement("tree");
00665 xml_writer.AddAttribute("version", "1.0");
00666 xml_writer.AddAttribute("xmlns:xsi",
00667 "http://www.w3.org/2001/XMLSchema-instance");
00668 xml_writer.AddAttribute("xsi:noNamespaceSchemaLocation", "tree.xsd");
00669
00670 root_node_->GenerateTreeXML(&xml_writer);
00671
00672 xml_writer.EndElement();
00673 xml_writer.EndDocument();
00674
00675 return xml_writer.GetContent();
00676 }
00677
00678 string TreeMonitor::GenerateVisualizationXML() const {
00679 XmlHelper xml_writer;
00680 xml_writer.StartDocument();
00681
00682 xml_writer.StartElement("visualization");
00683 xml_writer.AddAttribute("version", "1.0");
00684 xml_writer.AddAttribute("xmlns:xsi",
00685 "http://www.w3.org/2001/XMLSchema-instance");
00686 xml_writer.AddAttribute("xsi:noNamespaceSchemaLocation", "visualization.xsd");
00687
00688 xml_writer.StartElement("visualizer");
00689 xml_writer.AddAttribute("id", 0);
00690 xml_writer.AddAttribute("type", "vector");
00691 xml_writer.AddAttribute("display", "expanded");
00692 xml_writer.AddAttribute("min", StringPrintf("%" GG_LL_FORMAT "d", min_));
00693 xml_writer.AddAttribute("max", StringPrintf("%" GG_LL_FORMAT "d", max_));
00694 xml_writer.AddAttribute("width", StringPrintf("%zd", vars_.size()));
00695 xml_writer.AddAttribute("height",
00696 StringPrintf("%" GG_LL_FORMAT "d", max_ - min_ + 1));
00697 xml_writer.EndElement();
00698
00699 root_node_->GenerateVisualizationXML(&xml_writer);
00700
00701 xml_writer.EndElement();
00702 xml_writer.EndDocument();
00703
00704 return xml_writer.GetContent();
00705 }
00706
00707 string TreeMonitor::DebugString() const {
00708 return StringPrintf("TreeMonitor:\n%s", GenerateTreeXML().c_str());
00709 }
00710
00711 void TreeMonitor::ExitSearch() {
00712 --search_level_;
00713
00714 VLOG(1) << "Current search level " << search_level_;
00715
00716 if (!search_level_) {
00717
00718
00719 if (!filename_tree_.empty()) {
00720 std::ofstream file_tree_(filename_tree_.c_str());
00721
00722 if (file_tree_.is_open()) {
00723 file_tree_ << GenerateTreeXML().c_str();
00724 file_tree_.close();
00725 } else {
00726 LG << "Failed to gain write access to file: " << filename_tree_;
00727 }
00728
00729 std::ofstream file_visualizer_(filename_visualizer_.c_str());
00730
00731 if (file_visualizer_.is_open()) {
00732 file_visualizer_ << GenerateVisualizationXML().c_str();
00733 file_visualizer_.close();
00734 } else {
00735 LG << "Failed to gain write access to file: " << filename_tree_;
00736 }
00737
00738 if(!filename_config_.empty()) {
00739 std::ofstream file_config_(filename_config_.c_str());
00740
00741 if (file_config_.is_open()) {
00742 file_config_ << kConfigXml;
00743 file_config_.close();
00744 } else {
00745 LG << "Failed to gain write access to file: " << filename_config_;
00746 }
00747 }
00748 } else {
00749 CHECK_NOTNULL(tree_xml_);
00750 *tree_xml_ = GenerateTreeXML();
00751
00752 CHECK_NOTNULL(visualization_xml_);
00753 *visualization_xml_ = GenerateVisualizationXML();
00754
00755 if (config_xml_) {
00756 *config_xml_ = kConfigXml;
00757 }
00758 }
00759 }
00760 }
00761
00762 string TreeMonitor::StripSpecialCharacters(string attribute) {
00763
00764
00765 const char* kAllowedCharacters = "0123456789abcdefghijklmnopqrstuvwxyz"
00766 "ABCDEFGHIJKLMNOPQRSTUVWXYZ_-[]:/.?()";
00767
00768 std::set<char> character_set;
00769
00770 char* allowed = const_cast<char*>(kAllowedCharacters);
00771
00772 while (*allowed) {
00773 character_set.insert(*(allowed++));
00774 }
00775
00776 for (int i = 0; i < attribute.length(); ++i) {
00777 if (character_set.find(attribute[i]) == character_set.end()) {
00778 attribute.replace(i,1,"_");
00779 }
00780 }
00781
00782 return attribute;
00783 }
00784 }
00785
00786
00787
00788
00789 string TreeMonitorStripSpecialCharacters(string attribute) {
00790 return TreeMonitor::StripSpecialCharacters(attribute);
00791 }
00792
00793
00794
00795 SearchMonitor* Solver::MakeTreeMonitor(const IntVar* const* vars, int size,
00796 const string& file_tree,
00797 const string& file_visualization) {
00798 return RevAlloc(new TreeMonitor(this, vars, size, file_tree,
00799 file_visualization));
00800 }
00801
00802 SearchMonitor* Solver::MakeTreeMonitor(const std::vector<IntVar*>& vars,
00803 const string& file_tree,
00804 const string& file_visualization) {
00805 return RevAlloc(new TreeMonitor(this, vars.data(), vars.size(), file_tree,
00806 file_visualization));
00807 }
00808
00809 SearchMonitor* Solver::MakeTreeMonitor(const IntVar* const* vars, int size,
00810 const string& file_config,
00811 const string& file_tree,
00812 const string& file_visualization) {
00813 return RevAlloc(new TreeMonitor(this, vars, size, file_config, file_tree,
00814 file_visualization));
00815 }
00816
00817 SearchMonitor* Solver::MakeTreeMonitor(const std::vector<IntVar*>& vars,
00818 const string& file_config,
00819 const string& file_tree,
00820 const string& file_visualization) {
00821 return RevAlloc(new TreeMonitor(this, vars.data(), vars.size(), file_config,
00822 file_tree, file_visualization));
00823 }
00824
00825 SearchMonitor* Solver::MakeTreeMonitor(const IntVar* const* vars,
00826 int size, string* const tree_xml,
00827 string* const visualization_xml) {
00828 return RevAlloc(new TreeMonitor(this, vars, size, tree_xml,
00829 visualization_xml));
00830 }
00831
00832 SearchMonitor* Solver::MakeTreeMonitor(const std::vector<IntVar*>& vars,
00833 string* const tree_xml,
00834 string* const visualization_xml) {
00835 return RevAlloc(new TreeMonitor(this, vars.data(), vars.size(), tree_xml,
00836 visualization_xml));
00837 }
00838
00839 SearchMonitor* Solver::MakeTreeMonitor(const IntVar* const* vars,
00840 int size, string* const config_xml,
00841 string* const tree_xml,
00842 string* const visualization_xml) {
00843 return RevAlloc(new TreeMonitor(this, vars, size, config_xml, tree_xml,
00844 visualization_xml));
00845 }
00846
00847 SearchMonitor* Solver::MakeTreeMonitor(const std::vector<IntVar*>& vars,
00848 string* const config_xml,
00849 string* const tree_xml,
00850 string* const visualization_xml) {
00851 return RevAlloc(new TreeMonitor(this, vars.data(), vars.size(), config_xml,
00852 tree_xml, visualization_xml));
00853 }
00854 }