Skip to content
Snippets Groups Projects
NormalizationStrategyACSF.cpp 3.79 KiB
Newer Older

#include <cmath>
#include <stdexcept>

#include "../mpi_wrapper.h"

#include "NormalizationStrategyACSF.h"
#include "exceptions.h"



lib4neuro::NormalizationStrategyACSF::NormalizationStrategyACSF( 		
	const std::unordered_map<ELEMENT_SYMBOL, Element*>& element_description,
	const std::vector<ELEMENT_SYMBOL> &element_order,
	const std::vector<std::pair<std::vector<double>, std::vector<double>>> &data
){
	
	this->order_of_elements = element_order;
	
	this->outputs_min = std::numeric_limits<double>::max();
	this->outputs_max = std::numeric_limits<double>::min();
	
	for( auto el: element_description ){
		this->number_of_inputs_per_element[ el.first ] = el.second->getSymmetryFunctions()->size();
		
		this->inputs_min[el.first] = std::vector<double>(this->number_of_inputs_per_element[ el.first ]);
		this->inputs_max[el.first] = std::vector<double>(this->number_of_inputs_per_element[ el.first ]);
		std::fill(this->inputs_min[el.first].begin(), inputs_min[el.first].end(), std::numeric_limits<double>::max());
		std::fill(this->inputs_max[el.first].begin(), inputs_max[el.first].end(), std::numeric_limits<double>::min());
	}
	
	unsigned int first_input_idx;
	for( auto d: data ){
		
		first_input_idx = 0;
		for( auto el: this->order_of_elements ){
			for( unsigned int j = 0; j < this->number_of_inputs_per_element[ el ]; ++j ){
				
				this->inputs_min[el][ j ] = std::min(this->inputs_min[el][ j ], d.first[ j + first_input_idx ] );
				this->inputs_max[el][ j ] = std::max(this->inputs_max[el][ j ], d.first[ j + first_input_idx ] );
				
			}
			first_input_idx += this->number_of_inputs_per_element[ el ];
		}
		
		this->outputs_min = std::min( this->outputs_min, d.second[ 0 ] );
		this->outputs_max = std::max( this->outputs_max, d.second[ 0 ] );
		
	}
	
	/* sycnhronization of normalized data */
	MPI_Allreduce( MPI_IN_PLACE, &this->outputs_min, 1, MPI_DOUBLE, MPI_MIN, lib4neuro::mpi_active_comm );
	MPI_Allreduce( MPI_IN_PLACE, &this->outputs_max, 1, MPI_DOUBLE, MPI_MAX, lib4neuro::mpi_active_comm );
	for( auto el: element_description ){
		MPI_Allreduce( MPI_IN_PLACE, &this->inputs_min[el.first][ 0 ], this->inputs_min[el.first].size(), MPI_DOUBLE, MPI_MIN, lib4neuro::mpi_active_comm );
		MPI_Allreduce( MPI_IN_PLACE, &this->inputs_max[el.first][ 0 ], this->inputs_max[el.first].size(), MPI_DOUBLE, MPI_MAX, lib4neuro::mpi_active_comm );
	}
}

void lib4neuro::NormalizationStrategyACSF::normalize_input(std::vector<double> &inp){
	
	unsigned int first_input_idx = 0;
	double len, dist2min;

	for( auto el: this->order_of_elements ){
		for( unsigned int j = 0; j < this->number_of_inputs_per_element[ el ]; ++j ){

			len = this->inputs_max[ el ][ j ] - this->inputs_min[ el ][ j ];
			dist2min = inp[ j + first_input_idx ] - this->inputs_min[ el ][ j ];

			inp[ j + first_input_idx ] = 2*(dist2min/len) - 1.0;
		}
		first_input_idx += this->number_of_inputs_per_element[ el ];
	}
}

void lib4neuro::NormalizationStrategyACSF::de_normalize_input(std::vector<double> &inp){
	unsigned int first_input_idx = 0;
	double len, dist2min;

	for( auto el: this->order_of_elements ){
		for( unsigned int j = 0; j < this->number_of_inputs_per_element[ el ]; ++j ){

			len = this->inputs_max[ el ][ j ] - this->inputs_min[ el ][ j ];

			inp[ j + first_input_idx ] = (inp[ j + first_input_idx ] + 1.0)*len*0.5 + this->inputs_min[ el ][ j ];
		}
		first_input_idx += this->number_of_inputs_per_element[ el ];
	}
}

void lib4neuro::NormalizationStrategyACSF::normalize_output(std::vector<double> &out){
	double len, dist2min;
	
	len = this->outputs_max - this->outputs_min;
	dist2min = out[ 0 ] - this->outputs_min;
	
	out[ 0 ] = 2*(dist2min/len) - 1.0;
}

void lib4neuro::NormalizationStrategyACSF::de_normalize_output(std::vector<double> &out){
	double len;
	
	len = this->outputs_max - this->outputs_min;
	
	out[ 0 ] = (out[ 0 ] + 1.0) * len * 0.5 + this->outputs_min;
}