// // Created by martin on 7/13/18. // #include "DataSetSerialization.h" InvalidDimension::InvalidDimension() : std::runtime_error("Invalid dimension specified!") {}; InvalidDimension::InvalidDimension(std::string msg) : std::runtime_error(msg.c_str()) {}; DataSet::DataSet(std::string file_path) { std::ifstream ifs (file_path); boost::archive::text_iarchive ia(ifs); ia >> *this; ifs.close(); } DataSet::DataSet(std::vector<std::pair<std::vector<double>, std::vector<double>>> *data_ptr) { this->n_elements = data_ptr->size(); this->data = *data_ptr; this->input_dim = this->data[0].first.size(); this->output_dim = this->data[0].second.size(); //TODO check the complete data set for input/output dimensions } DataSet::DataSet(double lower_bound, double upper_bound, unsigned int size, double output) { std::vector<std::pair<std::vector<double>, std::vector<double>>> new_data_vec; this->data = new_data_vec; this->n_elements = 0; this->input_dim = 1; this->output_dim = 1; this->add_isotropic_data(lower_bound, upper_bound, size, output); } DataSet::DataSet(std::vector<double> &bounds, unsigned int no_elems_in_one_dim, std::vector<double> (*output_func)(std::vector<double>&), unsigned int output_dim) { std::vector<std::pair<std::vector<double>, std::vector<double>>> new_data_vec; this->data = new_data_vec; this->input_dim = bounds.size()/2; this->output_dim = output_dim; this->n_elements = 0; this->add_isotropic_data(bounds, no_elems_in_one_dim, output_func); } void DataSet::add_data_pair(std::vector<double> &inputs, std::vector<double> &outputs) { if(inputs.size() != this->input_dim) { throw InvalidDimension("Bad input dimension."); } else if(outputs.size() != this->output_dim) { throw InvalidDimension("Bad output dimension."); } this->n_elements++; this->data.emplace_back(std::make_pair(inputs, outputs)); } void DataSet::add_isotropic_data(double lower_bound, double upper_bound, unsigned int size, double output) { if(this->input_dim != 1 || this->output_dim != 1) { throw InvalidDimension("Cannot add data with dimensionality 1:1 when the data set " "is of different dimensionality!"); } double frac = (upper_bound - lower_bound) / (size - 1); std::vector<double> inp, out; out = {output}; for(unsigned int i = 0; i < size; ++i){ inp = {frac*i}; this->data.emplace_back(std::make_pair(inp, out)); } this->n_elements += size; } void DataSet::add_isotropic_data(std::vector<double> &bounds, unsigned int no_elems_in_one_dim, std::vector<double> (*output_func)(std::vector<double>&)) { // TODO add check of dataset dimensions std::vector<std::vector<double>> grid; std::vector<double> tmp; double frac; for(unsigned int i = 0; i < bounds.size(); i += 2) { frac = (bounds[i] + bounds[i+1]) / (no_elems_in_one_dim - 1); tmp.clear(); for(double j = bounds[i]; j <= bounds[i+1]; j += frac) { tmp.emplace_back(j); } grid.emplace_back(tmp); } grid = this->cartesian_product(&grid); for(auto vec : grid) { this->n_elements++; this->data.emplace_back(std::make_pair(vec, output_func(vec))); } } std::vector<std::pair<std::vector<double>, std::vector<double>>>* DataSet::get_data() { return &(this->data); } size_t DataSet::get_n_elements() { return this->n_elements; } size_t DataSet::get_input_dim() { return this->input_dim; } size_t DataSet::get_output_dim() { return this->output_dim; } void DataSet::print_data() { if (n_elements) { for (auto p : this->data) { /* INPUT */ for (auto v : std::get<0>(p)) { std::cout << v << " "; } std::cout << "-> "; /* OUTPUT */ for (auto v : std::get<1>(p)) { std::cout << v << " "; } std::cout << std::endl; } } } void DataSet::store_text(std::string &file_path) { //TODO check if stream was successfully opened std::ofstream ofs(file_path); boost::archive::text_oarchive oa(ofs); oa << *this; ofs.close(); } template <class T> std::vector<std::vector<T>> DataSet::cartesian_product(const std::vector<std::vector<T>>* v) { std::vector<std::vector<double>> v_combined_old, v_combined, v_tmp; std::vector<double> tmp; for(const auto& e : v->at(0)) { tmp = {e}; v_combined.emplace_back(tmp); } for(unsigned int i = 1; i < v->size(); i++) { // Iterate through remaining vectors of 'v' v_combined_old = v_combined; v_combined.clear(); for(const auto& e : v->at(i)) { for(const auto& vec : v_combined_old) { tmp = vec; tmp.emplace_back(e); /* Add only unique elements */ if(std::find(v_combined.begin(), v_combined.end(), tmp) == v_combined.end()) { v_combined.emplace_back(tmp); } } } } return v_combined; }