export sequence variable names, improve graph export

This commit is contained in:
lperron@google.com
2011-11-25 11:53:00 +00:00
parent 5294624b9e
commit 1cd22b70bf
4 changed files with 160 additions and 104 deletions

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
};