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& /*env*/) : _os(o), _constraintIndex(0) {}
23
24void PathFilePrinter::addBetterName(Id* id, const string& name, const string& path,
25 bool overwrite = false) {
26 string oname;
27 string opath;
28
29 auto it = _betternames.find(id);
30 if (it != _betternames.end()) {
31 oname = it->second.first;
32 opath = it->second.second;
33 }
34
35 if (!name.empty() && (overwrite || oname.empty())) {
36 oname = name;
37 }
38 if (!path.empty() && (overwrite || opath.empty())) {
39 opath = path;
40 }
41
42 _betternames[id] = NamePair(oname, opath);
43}
44
45string path2name(const string& path) {
46 std::stringstream name;
47
48 size_t idpos = path.rfind("id:");
49 if (idpos != string::npos) {
50 idpos += 3;
51 size_t semi = path.find(';', idpos);
52 if (semi != string::npos) {
53 // Variable name
54 name << path.substr(idpos, semi - idpos);
55
56 // Check for array
57 int dim = 0;
58 size_t ilpos = semi - idpos;
59 do {
60 ilpos = path.find("il:", ilpos);
61 if (ilpos != string::npos) {
62 ilpos += 3;
63 semi = path.find(';', ilpos);
64 if (semi != string::npos) {
65 if (dim == 0) {
66 name << "[";
67 } else {
68 name << ",";
69 }
70 name << path.substr(ilpos, semi - ilpos);
71 dim++;
72 }
73 }
74 } while (ilpos != string::npos);
75
76 if (dim > 0) {
77 name << "?]";
78 }
79
80 // Check for anon
81 if (path.find(":anon") != string::npos || path.find('=') != string::npos) {
82 name.str("");
83 name.clear();
84 }
85 }
86 }
87
88 return name.str();
89}
90
91void PathFilePrinter::print(Model* m) {
92 // Build map
93 for (VarDeclIterator vdit = m->vardecls().begin(); vdit != m->vardecls().end(); ++vdit) {
94 VarDecl* e = vdit->e();
95 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) {
96 if (Call* ca = (*it)->dynamicCast<Call>()) {
97 ASTString cid = ca->id();
98 if (cid == constants().ann.output_array) {
99 if (auto* rhs = e->e()->dynamicCast<ArrayLit>()) {
100 for (unsigned int ind = 0; ind < rhs->size(); ind++) {
101 if (Id* id = (*rhs)[ind]->dynamicCast<Id>()) {
102 std::stringstream bettername;
103 bettername << *e->id() << "[";
104
105 // Array of sets
106 ArrayLit& dimsets = *ca->arg(0)->cast<ArrayLit>();
107 vector<IntVal> dims(dimsets.size(), 1);
108 for (unsigned int i = 0; i < dimsets.size(); i++) {
109 auto* sl = dimsets[i]->cast<SetLit>();
110 dims[i] = sl->isv()->card();
111 }
112 vector<IntVal> dimspan(dims.size(), 1);
113 for (unsigned int i = 0; i < dims.size(); i++) {
114 for (unsigned int j = i + 1; j < dims.size(); j++) {
115 dimspan[i] *= dims[j];
116 }
117 }
118
119 IntVal curind = ind;
120 for (unsigned int i = 0; i < dims.size() - 1; i++) {
121 IntVal thisind = curind / dimspan[i];
122 curind -= thisind * dimspan[i];
123 bettername << dimsets[i]->cast<SetLit>()->isv()->min() + thisind << ",";
124 }
125 bettername << dimsets[dimsets.size() - 1]->cast<SetLit>()->isv()->min() + curind
126 << "]";
127
128 addBetterName(id, bettername.str(), "", true);
129 }
130 }
131 }
132 } else if (ca->id() == constants().ann.mzn_path) {
133 auto* sl = ca->arg(0)->cast<StringLit>();
134 addBetterName(e->id(), path2name(string(sl->v().c_str(), sl->v().size())),
135 string(sl->v().c_str()));
136 }
137 }
138 }
139 }
140
141 // Print values
142 for (Item* item : *m) {
143 print(item);
144 }
145}
146
147void PathFilePrinter::print(Item* item) {
148 if (auto* vdi = item->dynamicCast<VarDeclI>()) {
149 Id* id = vdi->e()->id();
150 NamePair np = _betternames[id];
151 if (!np.first.empty() || !np.second.empty()) {
152 // FlatZinc name
153 _os << *id << "\t";
154
155 // Nice name
156 if (np.first.empty()) {
157 _os << *id << "\t";
158 } else {
159 string name = np.first;
160 _os << name;
161 if (name.find('?') != string::npos) {
162 _os << "(" << *id << ")";
163 }
164 _os << "\t";
165 }
166
167 // Path
168 _os << np.second << std::endl;
169 }
170 } else if (auto* ci = item->dynamicCast<ConstraintI>()) {
171 StringLit* sl = nullptr;
172 Expression* e = ci->e();
173 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) {
174 if (Call* ca = (*it)->dynamicCast<Call>()) {
175 ASTString cid = ca->id();
176 if (cid == constants().ann.mzn_path) {
177 sl = ca->arg(0)->cast<StringLit>();
178 }
179 }
180 }
181
182 _os << _constraintIndex << "\t";
183 _os << _constraintIndex << "\t";
184 if (sl != nullptr) {
185 _os << sl->v();
186 } else {
187 _os << "";
188 }
189 _os << std::endl;
190 _constraintIndex++;
191 }
192}
193} // namespace MiniZinc