A set of benchmarks to compare a new prototype MiniZinc implementation
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 * Gleb Belov <gleb.belov@monash.edu>
7 */
8
9/* This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
12
13#ifndef __MINIZINC_SOLNS2OUT_H__
14#define __MINIZINC_SOLNS2OUT_H__
15
16#include <minizinc/astexception.hh>
17#include <minizinc/builtins.hh>
18#include <minizinc/file_utils.hh>
19#include <minizinc/flatten.hh>
20#include <minizinc/flatten_internal.hh> // temp., TODO
21#include <minizinc/model.hh>
22#include <minizinc/optimize.hh>
23#include <minizinc/parser.hh>
24#include <minizinc/solver_instance.hh>
25#include <minizinc/typecheck.hh>
26#include <minizinc/utils.hh>
27
28#include <ctime>
29#include <iomanip>
30#include <memory>
31#include <set>
32#include <string>
33#include <unordered_map>
34#include <vector>
35
36namespace MiniZinc {
37
38/// Class handling fzn solver's output
39/// could facilitate exhange of raw/final outputs in a portfolio
40class Solns2Out {
41protected:
42 std::unique_ptr<Env> pEnv_guard;
43 Env* pEnv = 0;
44 Model* pOutput = 0;
45
46 typedef std::pair<VarDecl*, KeepAlive> DE;
47 std::unordered_map<std::string, DE> declmap;
48 Expression* outputExpr = NULL;
49 std::string checkerModel;
50 bool fNewSol2Print = false; // should be set for evalOutput to work
51
52public:
53 std::string solution;
54 std::string comments;
55 int nLinesIgnore = 0;
56
57 struct Options {
58 std::string flag_output_file;
59 bool flag_output_comments = true;
60 bool flag_output_flush = true;
61 bool flag_output_time = false;
62 int flag_ignore_lines = 0;
63 bool flag_unique = 1;
64 bool flag_canonicalize = 0;
65 bool flag_standaloneSolns2Out = false;
66 std::string flag_output_noncanonical;
67 std::string flag_output_raw;
68 int flag_number_output = -1;
69 /// Default values, also used for input
70 const char* const solution_separator_00 = "----------";
71 const char* const unsatisfiable_msg_00 = "=====UNSATISFIABLE=====";
72 const char* const unbounded_msg_00 = "=====UNBOUNDED=====";
73 const char* const unsatorunbnd_msg_00 = "=====UNSATorUNBOUNDED=====";
74 const char* const unknown_msg_00 = "=====UNKNOWN=====";
75 const char* const error_msg_00 = "=====ERROR=====";
76 const char* const search_complete_msg_00 = "==========";
77 /// Output values
78 std::string solution_separator = solution_separator_00;
79 std::string solution_comma = "";
80 std::string unsatisfiable_msg = unsatisfiable_msg_00;
81 std::string unbounded_msg = unbounded_msg_00;
82 std::string unsatorunbnd_msg = unsatorunbnd_msg_00;
83 std::string unknown_msg = unknown_msg_00;
84 std::string error_msg = error_msg_00;
85 std::string search_complete_msg = search_complete_msg_00;
86 } _opt;
87
88public:
89 ~Solns2Out();
90 Solns2Out(std::ostream& os, std::ostream& log, const std::string& stdlibDir);
91
92 bool processOption(int& i, std::vector<std::string>& argv);
93 void printHelp(std::ostream&);
94
95 /// The output model (~.ozn) can be passed in 1 way in this base class:
96 /// passing Env* containing output()
97 bool initFromEnv(Env* pE);
98
99 /// Then, variable assignments can be passed either as text
100 /// or put directly into envi()->output() ( latter done externally
101 /// by e.g. SolverInstance::assignSolutionToOutput() )
102 /// In the 1st case, (part of) the assignment text is passed as follows,
103 /// original end-of-lines need to be there as well
104 bool feedRawDataChunk(const char*);
105
106 SolverInstance::Status status = SolverInstance::UNKNOWN;
107 bool fStatusPrinted = false;
108 /// Should be called when entering new solution into the output model.
109 /// Default assignSolutionToOutput() does it by using findOutputVar().
110 void declNewOutput();
111
112 /// This can be used by assignSolutionToOutput()
113 DE& findOutputVar(ASTString);
114
115 /// In the other case,
116 /// the evaluation procedures print output/status to os
117 /// returning false means need to stop (error/ too many solutions)
118 /// Solution validation here TODO
119 /// Note that --canonicalize delays output
120 /// until ... exit, eof, ?? TODO
121 /// These functions should only be called explicitly
122 /// from SolverInstance
123 bool evalOutput(const std::string& s_ExtraInfo = "");
124 /// This means the solver exits
125 bool evalStatus(SolverInstance::Status status);
126
127 void printStatistics(std::ostream&);
128
129 Env* getEnv() const { return pEnv; }
130 Model* getModel() const {
131 assert(getEnv()->output());
132 return getEnv()->output();
133 }
134 /// Get the primary output stream
135 /// First call restores stdout
136 std::ostream& getOutput();
137 /// Get the secondary output stream
138 std::ostream& getLog();
139
140private:
141 Timer starttime;
142
143 std::unique_ptr<std::ostream> pOut; // file output
144 std::unique_ptr<std::ostream> pOfs_non_canon;
145 std::unique_ptr<std::ostream> pOfs_raw;
146 int nSolns = 0;
147 std::set<std::string> sSolsCanon;
148 std::string line_part; // non-finished line from last chunk
149
150 /// Initialise from ozn file
151 void initFromOzn(const std::string& filename);
152
153protected:
154 std::ostream& os;
155 std::ostream& log;
156 std::vector<std::string> includePaths;
157 std::string stdlibDir;
158
159 // Basically open output
160 void init();
161 void createOutputMap();
162 std::map<std::string, SolverInstance::Status> mapInputStatus;
163 void createInputMap();
164 void restoreDefaults();
165 /// Parsing fznsolver's complete raw text output
166 void parseAssignments(std::string&);
167 /// Checking solution against checker model
168 void checkSolution(std::ostream& os);
169 bool __evalOutput(std::ostream& os);
170 bool __evalOutputFinal(bool flag_flush);
171 bool __evalStatusMsg(SolverInstance::Status status);
172};
173
174// Passthrough Solns2Out class
175class Solns2Log {
176private:
177 std::ostream& _log;
178 std::ostream& _err_log;
179
180public:
181 Solns2Log(std::ostream& log, std::ostream& errLog) : _log(log), _err_log(errLog) {}
182 bool feedRawDataChunk(const char* data) {
183 _log << data << std::flush;
184 return true;
185 }
186 std::ostream& getLog(void) { return _err_log; }
187};
188
189} // namespace MiniZinc
190
191#endif // __MINIZINC_SOLNS2OUT_H__