1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Guido Tack <guido.tack@monash.edu>
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <minizinc/prettyprinter.hh>
#include <minizinc/statistics.hh>
#include <cmath>
#include <iostream>
#include <limits>
#include <unordered_set>
namespace MiniZinc {
StatisticsStream::StatisticsStream(std::ostream& os, bool json)
: _os(os), _json(json), _ios(nullptr) {
_ios.copyfmt(os);
if (_json) {
_os << "{\"type\": \"statistics\", \"statistics\": {";
}
}
StatisticsStream::~StatisticsStream() {
if (_json) {
_os << "}}\n";
} else {
_os << "%%%mzn-stat-end\n";
}
if (!_warnings.empty()) {
for (auto& w : _warnings) {
if (_json) {
w->json(_os, false);
} else {
w->print(_os, false);
}
}
}
_os.copyfmt(_ios);
}
void StatisticsStream::precision(std::streamsize prec, bool fixed) {
_os.precision(prec);
if (fixed) {
_os.setf(std::ios::fixed);
} else {
_os.unsetf(std::ios::fixed);
}
}
void StatisticsStream::add(const std::string& stat, const Expression* value) {
if (Expression::isa<Id>(value)) {
std::stringstream ss;
ss << "invalid statistic %%%mzn-stat: " << stat << "=" << *value << " ignored.";
_warnings.emplace_back(new Warning(ss.str()));
} else {
addInternal(stat, *value);
}
}
void StatisticsStream::add(const std::string& stat, int value) { addInternal(stat, value); }
void StatisticsStream::add(const std::string& stat, unsigned int value) {
addInternal(stat, value);
}
void StatisticsStream::add(const std::string& stat, long value) { addInternal(stat, value); }
void StatisticsStream::add(const std::string& stat, unsigned long value) {
addInternal(stat, value);
}
void StatisticsStream::add(const std::string& stat, long long value) { addInternal(stat, value); }
void StatisticsStream::add(const std::string& stat, unsigned long long value) {
addInternal(stat, value);
}
void StatisticsStream::add(const std::string& stat, double value) {
if (std::isfinite(value)) {
addInternal(stat, value);
} else if (!_json) {
auto inf = std::numeric_limits<double>::infinity();
if (value == inf) {
addInternal(stat, "infinity");
} else if (value == -inf) {
addInternal(stat, "-infinity");
}
}
}
void StatisticsStream::add(const std::string& stat, const std::string& value) {
addInternal(stat, "\"" + Printer::escapeStringLit(value) + "\"");
}
void StatisticsStream::addRaw(const std::string& stat, const std::string& value) {
addInternal(stat, value);
}
/// TODO all key words should be standard and defined in 1 place
void Statistics::print(std::ostream& os) {
// TODO When is this ever called???
StatisticsStream stats(os);
stats.add("solveTime", _time);
stats.add("nodes", _nodes);
stats.add("failures", _failures);
stats.add("objective", _objective);
};
void Statistics::time(unsigned long long t) { _time = t; }
void Statistics::nodes(unsigned long long n) { _nodes = n; }
void Statistics::failures(unsigned long long f) { _failures = f; }
void Statistics::objective(double o) { _objective = o; }
unsigned long long Statistics::time() const { return _time; };
unsigned long long Statistics::nodes() const { return _nodes; };
unsigned long long Statistics::failures() const { return _failures; };
double Statistics::objective() const { return _objective; };
Statistics& Statistics::operator+=(Statistics& s) {
_time += s.time();
_nodes += s.nodes();
_failures += s.failures();
_objective = s.objective();
return *this;
}
} // namespace MiniZinc
|