export sequence variable names, improve graph export
This commit is contained in:
@@ -783,6 +783,9 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
CPIntervalVariableProto* const var_proto = model_proto_->add_intervals();
|
||||
var_proto->set_index(index);
|
||||
var_proto->set_type_index(TagIndex(ModelVisitor::kIntervalVariable));
|
||||
if (variable->HasName()) {
|
||||
var_proto->set_name(variable->name());
|
||||
}
|
||||
CPArgumentProto* const sub_proto = var_proto->add_arguments();
|
||||
sub_proto->set_argument_index(TagIndex(operation));
|
||||
for (int i = 0; i < size; ++i) {
|
||||
@@ -795,6 +798,9 @@ class SecondPassVisitor : public ModelVisitor {
|
||||
CPSequenceVariableProto* const var_proto = model_proto_->add_sequences();
|
||||
var_proto->set_index(index);
|
||||
var_proto->set_type_index(TagIndex(ModelVisitor::kSequenceVariable));
|
||||
if (sequence->HasName()) {
|
||||
var_proto->set_name(sequence->name());
|
||||
}
|
||||
CPArgumentProto* const sub_proto = var_proto->add_arguments();
|
||||
sub_proto->set_argument_index(TagIndex(ModelVisitor::kIntervalsArgument));
|
||||
for (int i = 0; i < sequence->size(); ++i) {
|
||||
|
||||
@@ -46,6 +46,15 @@ namespace operations_research {
|
||||
static const int kProblem = -1;
|
||||
static const int kOk = 0;
|
||||
|
||||
// Colors
|
||||
static const char kGreen1[] = "#A2CD5A";
|
||||
static const char kGreen2[] = "#76EEC6";
|
||||
static const char kGreen3[] = "#00CD00";
|
||||
static const char kWhite[] = "#FAFAFA";
|
||||
static const char kBlue[] = "#87CEFA";
|
||||
static const char kYellow[] = "#FFF68F";
|
||||
static const char kRed[] = "#A52A2A";
|
||||
|
||||
// Creates node labels.
|
||||
string ExprLabel(int index) {
|
||||
return StringPrintf("expr_%i", index);
|
||||
@@ -140,15 +149,15 @@ void DeclareExpression(int index,
|
||||
const string label = ExprLabel(index);
|
||||
int64 value = 0;
|
||||
if (expr.has_name()) {
|
||||
exporter->WriteNode(label, expr.name(), "oval", GraphExporter::kGreen);
|
||||
exporter->WriteNode(label, expr.name(), "oval", kGreen1);
|
||||
} else if (GetValueIfConstant(proto, expr, &value)) {
|
||||
exporter->WriteNode(label,
|
||||
StringPrintf("%lld", value),
|
||||
"oval",
|
||||
GraphExporter::kYellow);
|
||||
kYellow);
|
||||
} else {
|
||||
const string& type = proto.tags(expr.type_index());
|
||||
exporter->WriteNode(label, type, "oval", GraphExporter::kWhite);
|
||||
exporter->WriteNode(label, type, "oval", kWhite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,13 +167,10 @@ void DeclareInterval(int index,
|
||||
const CPIntervalVariableProto& interval = proto.intervals(index);
|
||||
const string label = IntervalLabel(index);
|
||||
if (interval.has_name()) {
|
||||
exporter->WriteNode(label,
|
||||
interval.name(),
|
||||
"circle",
|
||||
GraphExporter::kGreen);
|
||||
exporter->WriteNode(label, interval.name(), "circle", kGreen2);
|
||||
} else {
|
||||
const string& type = proto.tags(interval.type_index());
|
||||
exporter->WriteNode(label, type, "circle", GraphExporter::kWhite);
|
||||
exporter->WriteNode(label, type, "circle", kWhite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,13 +180,10 @@ void DeclareSequence(int index,
|
||||
const CPSequenceVariableProto& sequence = proto.sequences(index);
|
||||
const string label = SequenceLabel(index);
|
||||
if (sequence.has_name()) {
|
||||
exporter->WriteNode(label,
|
||||
sequence.name(),
|
||||
"circle",
|
||||
GraphExporter::kGreen);
|
||||
exporter->WriteNode(label, sequence.name(), "circle", kGreen3);
|
||||
} else {
|
||||
const string& type = proto.tags(sequence.type_index());
|
||||
exporter->WriteNode(label, type, "circle", GraphExporter::kWhite);
|
||||
exporter->WriteNode(label, type, "circle", kWhite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +193,7 @@ void DeclareConstraint(int index,
|
||||
const CPConstraintProto& ct = proto.constraints(index);
|
||||
const string& type = proto.tags(ct.type_index());
|
||||
const string label = ConstraintLabel(index);
|
||||
exporter->WriteNode(label, type, "rectangle", GraphExporter::kBlue);
|
||||
exporter->WriteNode(label, type, "rectangle", kBlue);
|
||||
}
|
||||
|
||||
// Parses the proto and exports it to a graph file.
|
||||
@@ -219,7 +222,7 @@ void ExportToGraphFile(const CPModelProto& proto,
|
||||
const char kObjLabel[] = "obj";
|
||||
if (proto.has_objective()) {
|
||||
const string name = proto.objective().maximize() ? "Maximize" : "Minimize";
|
||||
exporter->WriteNode(kObjLabel, name, "diamond", GraphExporter::kRed);
|
||||
exporter->WriteNode(kObjLabel, name, "diamond", kRed);
|
||||
}
|
||||
|
||||
for (int i = 0; i < proto.expressions_size(); ++i) {
|
||||
|
||||
@@ -25,118 +25,170 @@ namespace operations_research {
|
||||
|
||||
GraphExporter::~GraphExporter() {}
|
||||
|
||||
const char GraphExporter::kGreen[] = "#A2CD5A";
|
||||
const char GraphExporter::kWhite[] = "#FAFAFA";
|
||||
const char GraphExporter::kBlue[] = "#87CEFA";
|
||||
const char GraphExporter::kYellow[] = "#FFF68F";
|
||||
const char GraphExporter::kRed[] = "#A52A2A";
|
||||
|
||||
namespace {
|
||||
class GraphSyntax {
|
||||
public:
|
||||
virtual ~GraphSyntax() {}
|
||||
|
||||
// Node in the right syntax.
|
||||
virtual string Node(const string& name,
|
||||
const string& label,
|
||||
const string& shape,
|
||||
const string& color) = 0;
|
||||
// Adds one link in the generated graph.
|
||||
virtual string Link(const string& source,
|
||||
const string& destination,
|
||||
const string& label) = 0;
|
||||
// File header.
|
||||
virtual string Header(const string& name) = 0;
|
||||
|
||||
// File footer.
|
||||
virtual string Footer() = 0;
|
||||
};
|
||||
|
||||
class DotSyntax : public GraphSyntax {
|
||||
public:
|
||||
virtual ~DotSyntax() {}
|
||||
|
||||
virtual string Node(const string& name,
|
||||
const string& label,
|
||||
const string& shape,
|
||||
const string& color) {
|
||||
return StringPrintf("%s [shape=%s label=\"%s\" color=%s]\n",
|
||||
name.c_str(),
|
||||
shape.c_str(),
|
||||
label.c_str(),
|
||||
color.c_str());
|
||||
}
|
||||
|
||||
// Adds one link in the generated graph.
|
||||
virtual string Link(const string& source,
|
||||
const string& destination,
|
||||
const string& label) {
|
||||
return StringPrintf("%s -> %s [label=%s]\n",
|
||||
source.c_str(),
|
||||
destination.c_str(),
|
||||
label.c_str());
|
||||
}
|
||||
|
||||
// File header.
|
||||
virtual string Header(const string& name) {
|
||||
return StringPrintf("graph %s {\n", name.c_str());
|
||||
}
|
||||
|
||||
// File footer.
|
||||
virtual string Footer() {
|
||||
return "}\n";
|
||||
}
|
||||
};
|
||||
|
||||
class GmlSyntax : public GraphSyntax {
|
||||
public:
|
||||
virtual ~GmlSyntax() {}
|
||||
|
||||
virtual string Node(const string& name,
|
||||
const string& label,
|
||||
const string& shape,
|
||||
const string& color) {
|
||||
return StringPrintf(" node [\n"
|
||||
" name \"%s\"\n"
|
||||
" label \"%s\"\n"
|
||||
" graphics [\n"
|
||||
" type \"%s\"\n"
|
||||
" fill \"%s\"\n"
|
||||
" ]\n"
|
||||
" ]\n",
|
||||
name.c_str(),
|
||||
label.c_str(),
|
||||
shape.c_str(),
|
||||
color.c_str());
|
||||
}
|
||||
|
||||
// Adds one link in the generated graph.
|
||||
virtual string Link(const string& source,
|
||||
const string& destination,
|
||||
const string& label) {
|
||||
return StringPrintf(" edge [\n"
|
||||
" label \"%s\"\n"
|
||||
" source \"%s\"\n"
|
||||
" target \"%s\"\n"
|
||||
" ]\n",
|
||||
label.c_str(),
|
||||
source.c_str(),
|
||||
destination.c_str());
|
||||
}
|
||||
|
||||
// File header.
|
||||
virtual string Header(const string& name) {
|
||||
return StringPrintf("graph [\n"
|
||||
" name \"%s\"\n"
|
||||
, name.c_str());
|
||||
}
|
||||
|
||||
// File footer.
|
||||
virtual string Footer() {
|
||||
return "]\n";
|
||||
}
|
||||
};
|
||||
|
||||
// Graph exporter that will write to a file with a given format.
|
||||
class FileGraphExporter : public GraphExporter {
|
||||
public:
|
||||
FileGraphExporter(File* const file, GraphExporter::GraphFormat format)
|
||||
: file_(file), format_(format) {}
|
||||
FileGraphExporter(File* const file, GraphSyntax* const syntax)
|
||||
: file_(file), syntax_(syntax) {}
|
||||
|
||||
virtual ~FileGraphExporter() {}
|
||||
|
||||
void Write(const string& string) {
|
||||
file_->Write(string.c_str(), string.size());
|
||||
}
|
||||
|
||||
// Write node in GML or DOT format.
|
||||
// Write node in GML or DOT format.
|
||||
virtual void WriteNode(const string& name,
|
||||
const string& label,
|
||||
const string& shape,
|
||||
const string& color) {
|
||||
if (format_ == GML_FORMAT) {
|
||||
Write(StringPrintf(" node [\n"
|
||||
" name \"%s\"\n"
|
||||
" label \"%s\"\n"
|
||||
" graphics [\n"
|
||||
" type \"%s\"\n"
|
||||
" fill \"%s\"\n"
|
||||
" ]\n"
|
||||
" ]\n",
|
||||
name.c_str(),
|
||||
label.c_str(),
|
||||
shape.c_str(),
|
||||
color.c_str()));
|
||||
} else if (format_ == DOT_FORMAT) {
|
||||
Write(StringPrintf("%s [shape=%s label=\"%s\" color=%s]\n",
|
||||
name.c_str(),
|
||||
shape.c_str(),
|
||||
label.c_str(),
|
||||
color.c_str()));
|
||||
}
|
||||
Append(syntax_->Node(name, label, shape, color));
|
||||
}
|
||||
|
||||
// Adds one link in the generated graph.
|
||||
virtual void WriteLink(const string& source,
|
||||
const string& destination,
|
||||
const string& label) {
|
||||
switch (format_) {
|
||||
case DOT_FORMAT: {
|
||||
Write(StringPrintf("%s -- %s [label=%s]\n",
|
||||
source.c_str(),
|
||||
destination.c_str(),
|
||||
label.c_str()));
|
||||
break;
|
||||
}
|
||||
case GML_FORMAT: {
|
||||
Write(StringPrintf(" edge [\n"
|
||||
" label \"%s\"\n"
|
||||
" source \"%s\"\n"
|
||||
" target \"%s\"\n"
|
||||
" ]\n",
|
||||
label.c_str(),
|
||||
source.c_str(),
|
||||
destination.c_str()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Append(syntax_->Link(source, destination, label));
|
||||
}
|
||||
|
||||
virtual void WriteHeader(const string& name) {
|
||||
switch (format_) {
|
||||
case DOT_FORMAT: {
|
||||
Write(StringPrintf("graph %s {\n", name.c_str()));
|
||||
break;
|
||||
}
|
||||
case GML_FORMAT: {
|
||||
Write(StringPrintf("graph [\n name \"%s\"\n", name.c_str()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Append(syntax_->Header(name));
|
||||
}
|
||||
|
||||
virtual void WriteFooter() {
|
||||
switch (format_) {
|
||||
case DOT_FORMAT: {
|
||||
Write("}\n");
|
||||
break;
|
||||
}
|
||||
case GML_FORMAT: {
|
||||
Write("]\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Append(syntax_->Footer());
|
||||
}
|
||||
|
||||
private:
|
||||
void Append(const string& string) {
|
||||
file_->Write(string.c_str(), string.size());
|
||||
}
|
||||
|
||||
File* const file_;
|
||||
const GraphFormat format_;
|
||||
scoped_ptr<GraphSyntax> syntax_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
GraphExporter* GraphExporter::MakeFileExporter(
|
||||
File* const file,
|
||||
GraphExporter::GraphFormat format) {
|
||||
return new FileGraphExporter(file, format);
|
||||
GraphSyntax* syntax = NULL;
|
||||
switch (format) {
|
||||
case GraphExporter::DOT_FORMAT: {
|
||||
syntax = new DotSyntax();
|
||||
break;
|
||||
}
|
||||
case GraphExporter::GML_FORMAT: {
|
||||
syntax = new GmlSyntax();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(FATAL) << "Unknown graph format";
|
||||
}
|
||||
CHECK(syntax != NULL);
|
||||
return new FileGraphExporter(file, syntax);
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -28,6 +28,8 @@ using std::string;
|
||||
namespace operations_research {
|
||||
// ----- Export to graph file -----
|
||||
|
||||
// This class will allow the creation of a graph representation.
|
||||
// It supports different formats (see GraphFormat).
|
||||
class GraphExporter {
|
||||
public:
|
||||
// Supported graph formats.
|
||||
@@ -36,13 +38,6 @@ class GraphExporter {
|
||||
GML_FORMAT,
|
||||
};
|
||||
|
||||
// Colors
|
||||
static const char kGreen[];
|
||||
static const char kWhite[];
|
||||
static const char kBlue[];
|
||||
static const char kYellow[];
|
||||
static const char kRed[];
|
||||
|
||||
virtual ~GraphExporter();
|
||||
|
||||
// Write the header of the graph file.
|
||||
@@ -62,7 +57,7 @@ class GraphExporter {
|
||||
const string& destination,
|
||||
const string& label) = 0;
|
||||
|
||||
// Creates a graph exporter that will write to file with a given format.
|
||||
// Creates a graph exporter that will write to file with a given format.
|
||||
static GraphExporter* MakeFileExporter(File* const file,
|
||||
GraphExporter::GraphFormat format);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user