summaryrefslogtreecommitdiff
path: root/fuzzylite/src/imex/FldExporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fuzzylite/src/imex/FldExporter.cpp')
-rw-r--r--fuzzylite/src/imex/FldExporter.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/fuzzylite/src/imex/FldExporter.cpp b/fuzzylite/src/imex/FldExporter.cpp
new file mode 100644
index 0000000..9064250
--- /dev/null
+++ b/fuzzylite/src/imex/FldExporter.cpp
@@ -0,0 +1,246 @@
+/*
+ Author: Juan Rada-Vilela, Ph.D.
+ Copyright (C) 2010-2014 FuzzyLite Limited
+ All rights reserved
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ fuzzylite is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
+
+ fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+
+ */
+
+#include "fl/imex/FldExporter.h"
+
+#include "fl/Engine.h"
+#include "fl/Operation.h"
+#include "fl/variable/Variable.h"
+#include "fl/variable/InputVariable.h"
+#include "fl/variable/OutputVariable.h"
+
+#include <cmath>
+#include <fstream>
+#include <vector>
+
+namespace fl {
+
+ FldExporter::FldExporter(const std::string& separator) : Exporter(),
+ _separator(separator), _exportHeaders(true),
+ _exportInputValues(true), _exportOutputValues(true) {
+
+ }
+
+ FldExporter::~FldExporter() {
+ }
+
+ std::string FldExporter::name() const {
+ return "FldExporter";
+ }
+
+ void FldExporter::setSeparator(const std::string& separator) {
+ this->_separator = separator;
+ }
+
+ std::string FldExporter::getSeparator() const {
+ return this->_separator;
+ }
+
+ void FldExporter::setExportHeader(bool exportHeaders) {
+ this->_exportHeaders = exportHeaders;
+ }
+
+ bool FldExporter::exportsHeader() const {
+ return this->_exportHeaders;
+ }
+
+ void FldExporter::setExportInputValues(bool exportInputValues) {
+ this->_exportInputValues = exportInputValues;
+ }
+
+ bool FldExporter::exportsInputValues() const {
+ return this->_exportInputValues;
+ }
+
+ void FldExporter::setExportOutputValues(bool exportOutputValues) {
+ this->_exportOutputValues = exportOutputValues;
+ }
+
+ bool FldExporter::exportsOutputValues() const {
+ return this->_exportOutputValues;
+ }
+
+ std::string FldExporter::header(const Engine* engine) const {
+ std::vector<std::string> result;
+ if (_exportInputValues) {
+ for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ InputVariable* inputVariable = engine->getInputVariable(i);
+ result.push_back("@InputVariable: " + inputVariable->getName() + ";");
+ }
+ }
+ if (_exportOutputValues) {
+ for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ OutputVariable* outputVariable = engine->getOutputVariable(i);
+ result.push_back("@OutputVariable: " + outputVariable->getName() + ";");
+ }
+ }
+ return "#@Engine: " + engine->getName() + ";\n#" + Op::join(result, _separator);
+ }
+
+ std::string FldExporter::toString(const Engine* engine) const {
+ return toString(const_cast<Engine*> (engine), 1024);
+ }
+
+ std::string FldExporter::toString(Engine* engine, int maximumNumberOfResults) const {
+ std::ostringstream result;
+ write(engine, result, maximumNumberOfResults);
+ return result.str();
+ }
+
+ void FldExporter::toFile(const std::string& path, Engine* engine, int maximumNumberOfResults) const {
+ std::ofstream writer(path.c_str());
+ if (not writer.is_open()) {
+ throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT);
+ }
+ write(engine, writer, maximumNumberOfResults);
+ writer.close();
+ }
+
+ std::string FldExporter::toString(Engine* engine, const std::string& inputData) const {
+ std::ostringstream writer;
+ if (_exportHeaders) writer << header(engine) << "\n";
+ std::istringstream reader(inputData);
+ std::string line;
+ while (std::getline(reader, line)) {
+ line = Op::trim(line);
+ if (not line.empty() and line.at(0) == '#') continue; //comments are ignored, blank lines are retained
+ std::vector<scalar> inputValues = parse(line);
+ write(engine, writer, inputValues);
+ writer.flush();
+ }
+ return writer.str();
+ }
+
+ void FldExporter::toFile(const std::string& path, Engine* engine, const std::string& inputData) const {
+ std::ofstream writer(path.c_str());
+ if (not writer.is_open()) {
+ throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT);
+ }
+ if (_exportHeaders) writer << header(engine) << "\n";
+ std::istringstream reader(inputData);
+ std::string line;
+ while (std::getline(reader, line)) {
+ line = Op::trim(line);
+ if (not line.empty() and line.at(0) == '#') continue; //comments are ignored, blank lines are retained
+ std::vector<scalar> inputValues = parse(line);
+ write(engine, writer, inputValues);
+ writer.flush();
+ }
+ writer.close();
+ }
+
+ std::vector<scalar> FldExporter::parse(const std::string& x) const {
+ std::vector<scalar> inputValues;
+ if (not (x.empty() or x.at(0) == '#')) {
+ std::istringstream tokenizer(x);
+ std::string token;
+ while (tokenizer >> token)
+ inputValues.push_back(fl::Op::toScalar(token));
+ }
+ return inputValues;
+ }
+
+ void FldExporter::write(Engine* engine, std::ostream& writer, int maximum) const {
+ if (_exportHeaders) writer << header(engine) << "\n";
+
+ int resolution = -1 + (int) std::max(1.0, std::pow(
+ maximum, 1.0 / engine->numberOfInputVariables()));
+ std::vector<int> sampleValues, minSampleValues, maxSampleValues;
+ for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ sampleValues.push_back(0);
+ minSampleValues.push_back(0);
+ maxSampleValues.push_back(resolution);
+ }
+
+ engine->restart();
+
+ bool overflow = false;
+ std::vector<scalar> inputValues(engine->numberOfInputVariables());
+ while (not overflow) {
+ for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ InputVariable* inputVariable = engine->getInputVariable(i);
+ inputValues.at(i) = inputVariable->getMinimum()
+ + sampleValues.at(i) * inputVariable->range() / std::max(1, resolution);
+ }
+ write(engine, writer, inputValues);
+ overflow = Op::increment(sampleValues, minSampleValues, maxSampleValues);
+ }
+ }
+
+ void FldExporter::write(Engine* engine, std::ostream& writer, std::istream& reader) const {
+ if (_exportHeaders) writer << header(engine) << "\n";
+
+ engine->restart();
+
+ std::string line;
+ int lineNumber = 0;
+ while (std::getline(reader, line)) {
+ ++lineNumber;
+ std::vector<scalar> inputValues = parse(Op::trim(line));
+ try {
+ write(engine, writer, inputValues);
+ } catch (fl::Exception& ex) {
+ ex.append(" writing line <" + Op::str(lineNumber) + ">");
+ throw;
+ }
+ }
+ }
+
+ void FldExporter::write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues) const {
+ if (inputValues.empty()) {
+ writer << "\n";
+ return;
+ }
+ if (int(inputValues.size()) < engine->numberOfInputVariables()) {
+ std::ostringstream ex;
+ ex << "[export error] engine has <" << engine->numberOfInputVariables() << "> "
+ "input variables, but input data provides <" << inputValues.size() << "> values";
+ throw fl::Exception(ex.str(), FL_AT);
+ }
+
+ std::vector<std::string> values;
+ for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ InputVariable* inputVariable = engine->getInputVariable(i);
+ scalar inputValue = inputVariable->isEnabled() ? inputValues.at(i) : fl::nan;
+ inputVariable->setInputValue(inputValue);
+ if (_exportInputValues) values.push_back(Op::str(inputValue));
+ }
+
+ engine->process();
+
+ for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ OutputVariable* outputVariable = engine->getOutputVariable(i);
+ outputVariable->defuzzify();
+ if (_exportOutputValues)
+ values.push_back(Op::str(outputVariable->getOutputValue()));
+ }
+
+ writer << Op::join(values, _separator) << "\n";
+ }
+
+ FldExporter* FldExporter::clone() const {
+ return new FldExporter(*this);
+ }
+
+}