this repo has no description
at develop 5.6 kB view raw
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