Base version with linear combinated classes

This commit is contained in:
2019-12-13 18:17:29 +03:00
parent d3b1fc754a
commit 30ddecfa3c
3 changed files with 191 additions and 8 deletions

122
al_bool_matrix.hpp Normal file
View File

@@ -0,0 +1,122 @@
#ifndef _AL_BOOL_MATRIX_HPP
#define _AL_BOOL_MATRIX_HPP
#include <cassert>
#include <cstdint>
#include <bitset>
#include <limits>
#include <string>
template <class STORAGE, size_t SIZE>
class BoolVector {
public:
BoolVector(): _value(0) {
static_assert(not std::numeric_limits<STORAGE>::is_signed);
}
BoolVector(STORAGE val): _value(val) {
static_assert(not std::numeric_limits<STORAGE>::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 STORAGE, size_t SIZE>
class BoolSquareMatrix {
public:
BoolSquareMatrix(): _values(0) {
static_assert(not std::numeric_limits<STORAGE>::is_signed);
}
BoolSquareMatrix(STORAGE val): _values(val) {
static_assert(not std::numeric_limits<STORAGE>::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<STORAGE, SIZE> operator * (BoolVector<STORAGE, SIZE> vec) const {
/* a_1
* a_2
* a_3
*/
STORAGE vector_value = 0;
for (STORAGE ind = 0; ind < SIZE; ++ind) {
BoolVector<STORAGE, SIZE> 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<STORAGE, SIZE>(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<STORAGE, SIZE> 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<STORAGE, SIZE>(vector_value);
}
};
#endif // _AL_BOOL_MATRIX_HPP

View File

@@ -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;

View File

@@ -6,14 +6,16 @@
#include <fstream>
#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<Storage, FUNCTION_LEN> MyFunction;
typedef BoolSquareMatrix<Storage, ARGS_COUNT> MyMatrix;
void test_function() {
Function<uint16_t, 8> 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<uint16_t, 3> 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<class STORAGE, size_t ARGUMENTS_COUNT, class Callable>
Function<STORAGE, 1ll << ARGUMENTS_COUNT > 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<STORAGE, ARGUMENTS_COUNT> vec(cur_vec_value - 1);
function_values *= 2;
function_values += INPUT_FUNCTION(vec);
}
return Function<STORAGE, values_count >(function_values);
}
vector<MyFunction> 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<MyFunction> get_function_class(MyFunction f, const vector< MyMatrix >& tranformations, ostream& out) {
set<MyFunction> cur_res;
for (Storage i = 0; i < FUNCTION_LEN; ++i) {
MyFunction cur_f = f;
@@ -62,7 +94,24 @@ vector<MyFunction> get_function_class(MyFunction f) {
cur_f = cur_f.var_negation(arg_ind + 1);
cur_res.insert(cur_f);
}
return vector<MyFunction>(cur_res.begin(), cur_res.end());
set<MyFunction> transformed_res;
for (auto f: cur_res) {
for (auto transformation: tranformations) {
MyFunction linear_transformed = get_function_from_callable<Storage, ARGS_COUNT>(
[transformation, f](const BoolVector<Storage, ARGS_COUNT> 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<MyFunction>(transformed_res.begin(), transformed_res.end());
}
@@ -143,7 +192,7 @@ void fill_ranks(vector<MyFunction> 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<MyFunction> 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(",") <<endl;
ranks.clear();
for (auto i = total_ranks - 1; i != 0; --i)
ranks.push_back(vector<MyFunction>()); // empty set
@@ -163,13 +217,16 @@ void fill_ranks(vector<MyFunction> monomials) {
continue;
++total_functions;
MyFunction current_fn(fn_value);
vector<MyFunction> function_class = get_function_class(current_fn);
f_out << "Function class for " << current_fn.string() << ": ";
vector<MyFunction> 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;