From 30ddecfa3cbd86cba776ee8866a4c575433a85ee Mon Sep 17 00:00:00 2001 From: Aleksey Lobanov Date: Fri, 13 Dec 2019 18:17:29 +0300 Subject: [PATCH] Base version with linear combinated classes --- al_bool_matrix.hpp | 122 +++++++++++++++++++++++++++++++++++++++++++++ al_function.hpp | 4 ++ main.cpp | 73 ++++++++++++++++++++++++--- 3 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 al_bool_matrix.hpp diff --git a/al_bool_matrix.hpp b/al_bool_matrix.hpp new file mode 100644 index 0000000..f7c4596 --- /dev/null +++ b/al_bool_matrix.hpp @@ -0,0 +1,122 @@ +#ifndef _AL_BOOL_MATRIX_HPP +#define _AL_BOOL_MATRIX_HPP + +#include +#include + +#include +#include +#include + + +template +class BoolVector { + public: + BoolVector(): _value(0) { + static_assert(not std::numeric_limits::is_signed); + } + BoolVector(STORAGE val): _value(val) { + static_assert(not std::numeric_limits::is_signed); + if ( val > 1ll << SIZE) { + std::cout << "here " << std::endl; + } + } + + BoolVector operator*(BoolVector other) const { + return BoolVector(_value & other.get_value()); + } + + STORAGE get_value() const { + return _value; + } + STORAGE at(STORAGE ind) const { + return (_value >> ind) % 2; + } + std::string string() const { + std::string res(SIZE, '0'); + for (size_t ind = 0; ind < SIZE; ++ind) { + char cur_ch = at(ind) % 2 == 0 ? '0' : '1'; + res[ind] = cur_ch; + } + return res; + } + private: + STORAGE _value; +}; + +template +class BoolSquareMatrix { + public: + BoolSquareMatrix(): _values(0) { + static_assert(not std::numeric_limits::is_signed); + } + BoolSquareMatrix(STORAGE val): _values(val) { + static_assert(not std::numeric_limits::is_signed); + } + STORAGE at(STORAGE row, STORAGE col) const { + return (_values >> index(row, col)) % 2; + } + STORAGE get_determinant() { + if ( SIZE == 2 ) { + return at(0,0) * at(1,1) - at(0,1) * at(1,0); + } else if ( SIZE == 3 ) { + return at(0,0) * at(1,1) * at(2,2) + at(0,1) * at(1,2) * at(2,0) + + at(0,2) * at(1,0) * at(2,1) - at(0,2) * at(1,1) * at(2,0) + - at(0,1) * at(1,0) * at(2,2) - at(0,0) * at(1,2) * at(2,1); + } + } + + BoolVector operator * (BoolVector vec) const { + /* a_1 + * a_2 + * a_3 + */ + STORAGE vector_value = 0; + for (STORAGE ind = 0; ind < SIZE; ++ind) { + BoolVector cur_vec = vec * get_row(ind); + STORAGE cur_sum = 0; + for (STORAGE vec_ind = 0; vec_ind < SIZE; ++vec_ind) + cur_sum += cur_vec.at(vec_ind); + vector_value *= 2; + vector_value += cur_sum % 2; + } + return BoolVector(vector_value); + } + + STORAGE get_value() const { + return _values; + } + std::string string(std::string delimiter="\n") const { + std::string res; + for (STORAGE i = 0; i < SIZE; ++i) { + for (STORAGE j = 0; j < SIZE; ++j) { + char cur_ch = at(i,j) % 2 == 0 ? '0' : '1'; + res += cur_ch; + } + if ( i != SIZE - 1 ) + res += delimiter; + } + return res; + } + + bool operator < (BoolSquareMatrix other) const { + return _values < other._values; + } + bool operator == (BoolSquareMatrix other) const { + return _values == other._values; + } + private: + STORAGE _values; + STORAGE index(STORAGE row, STORAGE col) const { + return SIZE * row + col; + } + BoolVector get_row(STORAGE row) const { + STORAGE vector_value = 0; + for (STORAGE i = 0; i < SIZE; ++i) { + vector_value *= 2; + vector_value += at(row, i); + } + return BoolVector(vector_value); + } +}; +#endif // _AL_BOOL_MATRIX_HPP diff --git a/al_function.hpp b/al_function.hpp index 026e4cb..b80f1c8 100644 --- a/al_function.hpp +++ b/al_function.hpp @@ -76,6 +76,10 @@ class Function { return _function_values == other._function_values; } + STORAGE at(STORAGE index) const { + return (_function_values >> index) % 2; + } + Function var_negation(STORAGE var_index) { // var_index should be in 1..VARS_COUNT STORAGE mask, remains, shift; diff --git a/main.cpp b/main.cpp index bb419d2..b6355ed 100644 --- a/main.cpp +++ b/main.cpp @@ -6,14 +6,16 @@ #include #include "al_function.hpp" +#include "al_bool_matrix.hpp" using namespace std; typedef uint16_t Storage; -const size_t ARGS_COUNT = 4; +const size_t ARGS_COUNT = 3; const size_t FUNCTION_LEN = 1ll << ARGS_COUNT; const size_t FUNCTIONS_COUNT = 1ll << FUNCTION_LEN; typedef Function MyFunction; +typedef BoolSquareMatrix MyMatrix; void test_function() { Function f_8(16); @@ -49,11 +51,41 @@ void test_function() { cout << "f(x_1, x_2, x_3 + 1) = " << negation.var_negation(3).string() << endl; */ + BoolSquareMatrix ones_matrix((1 << 10) - 1), i_matrix(0b100010001), minus_i_matrix(0b001010100); + assert(ones_matrix.string("") == "111111111"); + assert(ones_matrix.get_determinant() == 0); + assert(i_matrix.string("") == "100010001"); + assert(i_matrix.get_determinant() == 1); + assert(minus_i_matrix.string("") == "001010100"); + assert(minus_i_matrix.get_determinant() == uint16_t(-1)); + cout << "self-test passed" << endl; } +template +Function get_function_from_callable(Callable INPUT_FUNCTION) { + const STORAGE values_count = 1ll << ARGUMENTS_COUNT; + STORAGE function_values(0); + for (STORAGE cur_vec_value = values_count; cur_vec_value != 0; --cur_vec_value) { + BoolVector vec(cur_vec_value - 1); + function_values *= 2; + function_values += INPUT_FUNCTION(vec); + } + return Function(function_values); +} -vector get_function_class(MyFunction f) { +vector< MyMatrix > get_good_matrices() { + vector< MyMatrix > res; + for (size_t cur_val = 1ll << (ARGS_COUNT * ARGS_COUNT); cur_val != 0; --cur_val) { + MyMatrix cur_matrix(cur_val); + if ( cur_matrix.get_determinant() != 0 ) + res.push_back(cur_matrix); + } + return res; +} + + +vector get_function_class(MyFunction f, const vector< MyMatrix >& tranformations, ostream& out) { set cur_res; for (Storage i = 0; i < FUNCTION_LEN; ++i) { MyFunction cur_f = f; @@ -62,7 +94,24 @@ vector get_function_class(MyFunction f) { cur_f = cur_f.var_negation(arg_ind + 1); cur_res.insert(cur_f); } - return vector(cur_res.begin(), cur_res.end()); + + set transformed_res; + for (auto f: cur_res) { + for (auto transformation: tranformations) { + MyFunction linear_transformed = get_function_from_callable( + [transformation, f](const BoolVector vec) -> Storage { + return f.at((transformation * vec).get_value()); + } + ); + bool is_inserted = transformed_res.insert(linear_transformed).second; + if ( is_inserted ) { + out << linear_transformed.string() << " = " << f.string() << " with (" + << transformation.string(",") << ")" << endl; + } + } + } + + return vector(transformed_res.begin(), transformed_res.end()); } @@ -143,7 +192,7 @@ void fill_ranks(vector monomials) { MyFunction res_el = el_first xor el_second; if ( used_map[res_el.value()] == 0 ) { --functions_remains; - used_map[res_el.value()] = total_ranks; + used_map.at(res_el.value()) = total_ranks; ranks.at(total_ranks).push_back(res_el); } } @@ -153,6 +202,11 @@ void fill_ranks(vector monomials) { cout << "size for rank " << total_ranks << " is " << ranks.at(total_ranks).size() << endl; } + auto possible_tranformations = get_good_matrices(); + cout << "Total " << possible_tranformations.size() << " linear tranformations" << endl; + //for (auto el: possible_tranformations) + // cout << el.string(",") <()); // empty set @@ -163,13 +217,16 @@ void fill_ranks(vector monomials) { continue; ++total_functions; MyFunction current_fn(fn_value); - vector function_class = get_function_class(current_fn); - f_out << "Function class for " << current_fn.string() << ": "; + vector function_class = get_function_class( + current_fn, possible_tranformations, f_out + ); + cout << "size of function class is " << function_class.size() << endl; + f_out << "Function class for " << current_fn.string() << ": (" << endl; for (auto marked_function: function_class) { used_map[marked_function.value()] = 0; - f_out << marked_function.string() << " "; + f_out << " " << marked_function.string() << endl; } - f_out << endl; + f_out << ")" << endl; ranks.at(cur_rank - 1).push_back(current_fn); } cout << "total unique functions: " << total_functions << endl;