this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#include <minizinc/flatten_internal.hh>
13#include <minizinc/pathfileprinter.hh>
14
15#include <sstream>
16
17namespace MiniZinc {
18
19using std::string;
20using std::vector;
21
22PathFilePrinter::PathFilePrinter(std::ostream& o, EnvI&) : os(o), constraint_index(0) {}
23
24void PathFilePrinter::addBetterName(Id* id, string name, string path, bool overwrite = false) {
25 string oname;
26 string opath;
27
28 NameMap::iterator it = betternames.find(id);
29 if (it != betternames.end()) {
30 oname = it->second.first;
31 opath = it->second.second;
32 }
33
34 if (!name.empty() && (overwrite || oname.empty())) oname = name;
35 if (!path.empty() && (overwrite || opath.empty())) opath = path;
36
37 betternames[id] = NamePair(oname, opath);
38}
39
40string path2name(string path) {
41 std::stringstream name;
42
43 size_t idpos = path.rfind("id:");
44 if (idpos != string::npos) {
45 idpos += 3;
46 size_t semi = path.find(";", idpos);
47 if (semi != string::npos) {
48 // Variable name
49 name << path.substr(idpos, semi - idpos);
50
51 // Check for array
52 int dim = 0;
53 size_t ilpos = semi - idpos;
54 do {
55 ilpos = path.find("il:", ilpos);
56 if (ilpos != string::npos) {
57 ilpos += 3;
58 semi = path.find(";", ilpos);
59 if (semi != string::npos) {
60 if (dim == 0)
61 name << "[";
62 else
63 name << ",";
64 name << path.substr(ilpos, semi - ilpos);
65 dim++;
66 }
67 }
68 } while (ilpos != string::npos);
69
70 if (dim > 0) name << "?]";
71
72 // Check for anon
73 if (path.find(":anon") != string::npos || path.find("=") != string::npos) {
74 name.str("");
75 name.clear();
76 }
77 }
78 }
79
80 return name.str();
81}
82
83void PathFilePrinter::print(Model* m) {
84 // Build map
85 for (VarDeclIterator vdit = m->begin_vardecls(); vdit != m->end_vardecls(); ++vdit) {
86 VarDecl* e = vdit->e();
87 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) {
88 if (Call* ca = (*it)->dyn_cast<Call>()) {
89 ASTString cid = ca->id();
90 if (cid == constants().ann.output_array) {
91 if (ArrayLit* rhs = e->e()->dyn_cast<ArrayLit>()) {
92 for (unsigned int ind = 0; ind < rhs->size(); ind++) {
93 if (Id* id = (*rhs)[ind]->dyn_cast<Id>()) {
94 std::stringstream bettername;
95 bettername << *e->id() << "[";
96
97 // Array of sets
98 ArrayLit& dimsets = *ca->arg(0)->cast<ArrayLit>();
99 vector<IntVal> dims(dimsets.size(), 1);
100 for (unsigned int i = 0; i < dimsets.size(); i++) {
101 SetLit* sl = dimsets[i]->cast<SetLit>();
102 dims[i] = sl->isv()->card();
103 }
104 vector<IntVal> dimspan(dims.size(), 1);
105 for (unsigned int i = 0; i < dims.size(); i++)
106 for (unsigned int j = i + 1; j < dims.size(); j++) dimspan[i] *= dims[j];
107
108 IntVal curind = ind;
109 for (unsigned int i = 0; i < dims.size() - 1; i++) {
110 IntVal thisind = curind / dimspan[i];
111 curind -= thisind * dimspan[i];
112 bettername << dimsets[i]->cast<SetLit>()->isv()->min() + thisind << ",";
113 }
114 bettername << dimsets[dimsets.size() - 1]->cast<SetLit>()->isv()->min() + curind
115 << "]";
116
117 addBetterName(id, bettername.str(), "", true);
118 }
119 }
120 }
121 } else if (ca->id() == constants().ann.mzn_path) {
122 StringLit* sl = ca->arg(0)->cast<StringLit>();
123 addBetterName(e->id(), path2name(sl->v().str()), sl->v().str());
124 }
125 }
126 }
127 }
128
129 // Print values
130 for (Item* item : *m) print(item);
131}
132
133void PathFilePrinter::print(Item* item) {
134 if (VarDeclI* vdi = item->dyn_cast<VarDeclI>()) {
135 Id* id = vdi->e()->id();
136 NamePair np = betternames[id];
137 if (!np.first.empty() || !np.second.empty()) {
138 // FlatZinc name
139 os << *id << "\t";
140
141 // Nice name
142 if (np.first.empty()) {
143 os << *id << "\t";
144 } else {
145 string name = np.first;
146 os << name;
147 if (name.find("?") != string::npos) os << "(" << *id << ")";
148 os << "\t";
149 }
150
151 // Path
152 os << np.second << std::endl;
153 }
154 } else if (ConstraintI* ci = item->dyn_cast<ConstraintI>()) {
155 StringLit* sl = nullptr;
156 Expression* e = ci->e();
157 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) {
158 if (Call* ca = (*it)->dyn_cast<Call>()) {
159 ASTString cid = ca->id();
160 if (cid == constants().ann.mzn_path) {
161 sl = ca->arg(0)->cast<StringLit>();
162 }
163 }
164 }
165
166 os << constraint_index << "\t";
167 os << constraint_index << "\t";
168 if (sl) {
169 os << sl->v();
170 } else {
171 os << "";
172 }
173 os << std::endl;
174 constraint_index++;
175 }
176}
177} // namespace MiniZinc