Skip to content

Commit

Permalink
Merge pull request #105 from czgdp1807/lnn
Browse files Browse the repository at this point in the history
Port ``integration_tests/lnn`` from LPython
  • Loading branch information
czgdp1807 authored Mar 12, 2024
2 parents 06f6814 + 996e340 commit 5feab59
Show file tree
Hide file tree
Showing 11 changed files with 587 additions and 13 deletions.
2 changes: 2 additions & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,5 @@ RUN(NAME vector_01.cpp LABELS gcc llvm NOFAST)
RUN(NAME vector_02.cpp LABELS gcc llvm NOFAST)

RUN(NAME loop_01.cpp LABELS gcc llvm NOFAST)

RUN(NAME test_pkg_lnn_01.cpp LABELS gcc llvm NOFAST)
123 changes: 123 additions & 0 deletions integration_tests/lnn/perceptron/perceptron_main.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <vector>
#include <iostream>

struct Perceptron {
int32_t no_of_inputs;
std::vector<double> weights;
double learn_rate;
int32_t iterations_limit;
double des_accuracy;
double cur_accuracy;
int32_t epochs_cnt;
};

int32_t predict_perceptron(const struct Perceptron& p, const std::vector<double>& input_vector);
int32_t activation_function(double value);
double test_perceptron(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<int32_t>& outputs);

std::vector<double> get_inp_vec_with_bias(std::vector<double>& a) {
std::vector<double> b = {};
size_t i;
for( i = 0; i < a.size(); i++ ) {
b.push_back(a[i]);
}
b.push_back(1.0);
return b;
}

std::vector<double> init_weights(int32_t size) {
std::vector<double> weights = {};
int32_t i;
for( i = 0; i < size; i++ ) {
weights.push_back(0.0);
}
weights.push_back(0.0);
return weights;
}

void init_perceptron(struct Perceptron& p, int32_t n, double rate,
int32_t iterations_limit, double des_accuracy) {
if (n < 1 or n > 1000) {
std::cout << "no_of_inputs must be between [1, 1000]" << std::endl;
exit(2);
}
p.no_of_inputs = n;
p.weights = init_weights(n);
p.learn_rate = rate;
p.iterations_limit = iterations_limit;
p.des_accuracy = des_accuracy;
p.cur_accuracy = 0.0;
p.epochs_cnt = 0;
}

void train_perceptron(struct Perceptron& p, const std::vector<double>& input_vector, int32_t actual_output) {
int32_t predicted_output = predict_perceptron(p, input_vector);
int32_t error = actual_output - predicted_output;
size_t i;
for( i = 0; i < input_vector.size(); i++ ) {
p.weights[i] += p.learn_rate * double(error) * double(input_vector[i]);
}
}

int32_t predict_perceptron(const struct Perceptron& p, const std::vector<double>& input_vector) {
double weighted_sum = 0.0;
size_t i = 0;
for( i = 0; i < input_vector.size(); i++ ) {
weighted_sum = weighted_sum + p.weights[i] * double(input_vector[i]);
}
return activation_function(weighted_sum);
}

int32_t activation_function(double value) {
if ( value >= 0.0 ) {
return 1;
}
return -1;
}

void train_epoch(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<int32_t>& outputs) {
size_t i;
for( i = 0; i < input_vectors.size(); i++ ) {
std::vector<double> input_vector = get_inp_vec_with_bias(input_vectors[i]);
if( predict_perceptron(p, input_vector) != outputs[i] ) {
train_perceptron(p, input_vector, outputs[i]);
}
}
}

void train_dataset(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<int32_t>& outputs) {
p.cur_accuracy = 0.0;
p.epochs_cnt = 0;
while( p.cur_accuracy < p.des_accuracy and p.epochs_cnt < p.iterations_limit ) {
p.epochs_cnt += 1;
train_epoch(p, input_vectors, outputs);
p.cur_accuracy = test_perceptron(p, input_vectors, outputs);
}
}

double test_perceptron(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<int32_t>& outputs) {
int32_t correctly_classified_cnt = 0;
size_t i;
for( i = 0; i < input_vectors.size(); i++ ) {
std::vector<double> input_vector = get_inp_vec_with_bias(input_vectors[i]);
if( predict_perceptron(p, input_vector) == outputs[i] ) {
correctly_classified_cnt += 1;
}
}
return (correctly_classified_cnt / input_vectors.size()) * 100.0;
}

void print_perceptron(struct Perceptron& p) {
std::cout<<"weights = [";
int32_t i;
for( i = 0; i < p.no_of_inputs; i++ ) {
std::cout<<p.weights[i]<<", ";
}
std::cout<<p.weights[p.no_of_inputs]<<"(bias)]\n";
std::cout<<"learn_rate = ";
std::cout<<p.learn_rate<<"\n";
std::cout<<"accuracy = ";
std::cout<<p.cur_accuracy<<"\n";
std::cout<<"epochs_cnt = ";
std::cout<<p.epochs_cnt<<"\n";
}
114 changes: 114 additions & 0 deletions integration_tests/lnn/regression/regression_main.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <iostream>

struct Perceptron {
int32_t no_of_inputs;
std::vector<double> weights;
double learn_rate;
int32_t iterations_limit;
double err_limit;
double err;
int32_t epochs_cnt;
};

double predict_perceptron(struct Perceptron& p, std::vector<double>& input_vector);
double activation_function(double value);
double test_perceptron(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<double>& outputs);

std::vector<double> get_inp_vec_with_bias(std::vector<double>& a) {
std::vector<double> b = {};
size_t i;
for( i = 0; i < a.size(); i++ ) {
b.push_back(a[i]);
}
b.push_back(1.0);
return b;
}

std::vector<double> init_weights(int32_t size) {
std::vector<double> weights = {};
int32_t i;
for( i = 0; i < size; i++ ) {
weights.push_back(0.0);
}
weights.push_back(0.0);
return weights;
}

void init_perceptron(struct Perceptron& p, int32_t n, double rate, int32_t iterations_limit, double err_limit) {
p.no_of_inputs = n;
p.weights = init_weights(n);
p.learn_rate = rate;
p.iterations_limit = iterations_limit;
p.err_limit = err_limit;
p.err = 1.0;
p.epochs_cnt = 0;
}

void train_perceptron(struct Perceptron& p, std::vector<double>& input_vector, double actual_output) {
double predicted_output = predict_perceptron(p, input_vector);
double error = actual_output - predicted_output;
int32_t i;
for( i = 0; i < input_vector.size(); i++ ) {
p.weights[i] += p.learn_rate * error * input_vector[i];
}
}

double predict_perceptron(struct Perceptron& p, std::vector<double>& input_vector) {
double weighted_sum = 0.0;
int32_t i = 0;
for( i = 0; i < input_vector.size(); i++ ) {
weighted_sum = weighted_sum + p.weights[i] * input_vector[i];
}
return activation_function(weighted_sum);
}

double activation_function(double value) {
return value;
}

void train_epoch(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<double>& outputs) {
int32_t i;
for( i = 0; i < input_vectors.size(); i++ ) {
std::vector<double> input_vector = get_inp_vec_with_bias(input_vectors[i]);
if ( predict_perceptron(p, input_vector) != outputs[i] ) {
train_perceptron(p, input_vector, outputs[i]);
}
}
}

void train_dataset(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<double>& outputs) {
double prev_err = 0.0;
p.err = 1.0;
p.epochs_cnt = 0;
while( abs(p.err - prev_err) >= p.err_limit and p.epochs_cnt < p.iterations_limit ) {
p.epochs_cnt += 1;
train_epoch(p, input_vectors, outputs);
prev_err = p.err;
p.err = test_perceptron(p, input_vectors, outputs);
}
}

double test_perceptron(struct Perceptron& p, std::vector<std::vector<double>>& input_vectors, std::vector<double>& outputs) {
double err = 0.0;
int32_t i;
for( i = 0; i < input_vectors.size(); i++ ) {
std::vector<double> input_vector = get_inp_vec_with_bias(input_vectors[i]);
err = err + pow((outputs[i] - predict_perceptron(p, input_vector)), 2.0);
}
return err;
}

void print_perceptron(struct Perceptron& p) {
std::cout << "weights = [";
int32_t i;
for( i = 0; i < p.no_of_inputs; i++ ) {
std::cout << p.weights[i] << ", ";
}
std::cout << p.weights[p.no_of_inputs] << "\n";
std::cout << "learn_rate = ";
std::cout << p.learn_rate << "\n";
std::cout << "error = ";
std::cout << p.err << "\n";
std::cout << "epochs_cnt = ";
std::cout << p.epochs_cnt << "\n";
}
56 changes: 56 additions & 0 deletions integration_tests/lnn/utils/utils_main.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <vector>

double normalize(double value, double leftMin, double leftMax, double rightMin, double rightMax) {
// Figure out how 'wide' each range is
double leftSpan = leftMax - leftMin;
double rightSpan = rightMax - rightMin;

// Convert the left range into a 0-1 range (float)
double valueScaled = (value - leftMin) / leftSpan;

// Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan);
}

void normalize_input_vectors(std::vector<std::vector<double>>& input_vectors) {
int32_t rows = input_vectors.size();
int32_t cols = input_vectors[0].size();

int32_t j;
for( j = 0; j < cols; j++ ) {
double colMinVal = input_vectors[0][j];
double colMaxVal = input_vectors[0][j];
int32_t i;
for( i = 0; i < rows; i++ ) {
if( input_vectors[i][j] > colMaxVal ) {
colMaxVal = input_vectors[i][j];
}
if( input_vectors[i][j] < colMinVal ) {
colMinVal = input_vectors[i][j];
}
}

for( i = 0; i < rows; i++ ) {
input_vectors[i][j] = normalize(input_vectors[i][j], colMinVal, colMaxVal, -1.0, 1.0);
}
}
}

void normalize_output_vector(std::vector<double>& output_vector) {
int32_t rows = output_vector.size();
double colMinVal = output_vector[0];
double colMaxVal = output_vector[0];
int32_t i;
for( i = 0; i < rows; i++ ) {
if( output_vector[i] > colMaxVal ) {
colMaxVal = output_vector[i];
}
if( output_vector[i] < colMinVal ) {
colMinVal = output_vector[i];
}
}

for( i = 0; i < rows; i++ ) {
output_vector[i] = normalize(output_vector[i], colMinVal, colMaxVal, -1.0, 1.0);
}
}
Loading

0 comments on commit 5feab59

Please sign in to comment.