First version with advanced algorithm
This commit is contained in:
19
al_utility.cpp
Normal file
19
al_utility.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include "al_utility.hpp"
|
||||||
|
|
||||||
|
bool print_progress(long current, long total, double print_every) {
|
||||||
|
long integer_part = total * print_every;
|
||||||
|
if ( current % integer_part != 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// сделаем потокобезопасным
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Progress " << current << " of " << total
|
||||||
|
<< " " << std::fixed << std::setw(5) << std::setprecision(2)
|
||||||
|
<< 100. * current / total << "%" << std::endl;
|
||||||
|
std::cout << ss.str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_math_coeff(int k) {
|
||||||
|
return static_cast<int>(pow(1.4, k + 2));
|
||||||
|
}
|
||||||
11
al_utility.hpp
Normal file
11
al_utility.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef _AL_UTILITY_
|
||||||
|
#define _AL_UTILITY_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
bool print_progress(long current, long total, double print_every=0.1);
|
||||||
|
int get_math_coeff(int k);
|
||||||
|
#endif // _AL_UTILITY_
|
||||||
302
main.cpp
302
main.cpp
@@ -16,15 +16,20 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
#include "al_utility.hpp"
|
||||||
#include "finite_function.hpp"
|
#include "finite_function.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const CellType CUR_BASE = 3;
|
const CellType CUR_BASE = 3;
|
||||||
const int ARGS_COUNT = 2;
|
const int ARGS_COUNT = 2;
|
||||||
|
|
||||||
|
struct FunctionTask {
|
||||||
|
set<FiniteFunction<CUR_BASE>> current;
|
||||||
|
bool is_finished;
|
||||||
|
int current_max_coeff;
|
||||||
|
};
|
||||||
|
|
||||||
template <size_t BASE>
|
template <size_t BASE>
|
||||||
class FixedIniter {
|
class FixedIniter {
|
||||||
public:
|
public:
|
||||||
@@ -257,120 +262,207 @@ set<FiniteFunction<BASE>> generate_function_class(FiniteFunction<BASE> base_func
|
|||||||
return set<FiniteFunction<BASE>>(func_class.begin(), func_class.end());
|
return set<FiniteFunction<BASE>>(func_class.begin(), func_class.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Возвращает новый функциональный класс, размером не сильно больше, чем max_size
|
||||||
|
// Вторым результатом возвращает true, если вычисления закончились успешно
|
||||||
|
// и false, если прервались по достижению max_size
|
||||||
|
template <CellType BASE>
|
||||||
|
pair<set<FiniteFunction<BASE>>, bool> extend_function_class(
|
||||||
|
const set<FiniteFunction<BASE>>& base_class,
|
||||||
|
size_t max_size
|
||||||
|
) {
|
||||||
|
auto FiniteFunctionHasher = [](const FiniteFunction<BASE> &f) -> uint32_t {
|
||||||
|
return f.get_hash();
|
||||||
|
};
|
||||||
|
unordered_set<
|
||||||
|
FiniteFunction<CUR_BASE>,
|
||||||
|
decltype(FiniteFunctionHasher)
|
||||||
|
> func_class(1024, FiniteFunctionHasher);
|
||||||
|
for (auto&& base_function: base_class)
|
||||||
|
func_class.insert(base_function);
|
||||||
|
|
||||||
|
bool is_finished = false;
|
||||||
|
size_t last_size = 0; // размер в прошлой итерации
|
||||||
|
while (true) {
|
||||||
|
unordered_set<
|
||||||
|
FiniteFunction<CUR_BASE>,
|
||||||
|
decltype(FiniteFunctionHasher)
|
||||||
|
> new_funcs(1024, FiniteFunctionHasher);
|
||||||
|
|
||||||
|
for (const auto& f_main: func_class) {
|
||||||
|
new_funcs.insert(f_main.reversed());
|
||||||
|
for (const auto& f_applied: func_class) {
|
||||||
|
FiniteFunction<BASE> f_left;
|
||||||
|
f_left = f_main.apply_to_first_partial(f_applied);
|
||||||
|
new_funcs.insert(f_left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( new_funcs.size() == last_size ) {
|
||||||
|
is_finished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_class.insert(new_funcs.begin(), new_funcs.end());
|
||||||
|
last_size = new_funcs.size();
|
||||||
|
|
||||||
|
// слишком много насчитали -- выходим
|
||||||
|
if ( func_class.size() > max_size ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return make_pair(
|
||||||
|
set<FiniteFunction<BASE>>(func_class.begin(), func_class.end()),
|
||||||
|
is_finished
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool is_bad_class(
|
||||||
|
set<FiniteFunction<CUR_BASE>> func_class,
|
||||||
|
const set<FiniteFunction<CUR_BASE>>& bad_funcs
|
||||||
|
) {
|
||||||
|
for (auto&& func: func_class)
|
||||||
|
if ( bad_funcs.find(func) != bad_funcs.end() )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
vector <FiniteFunction<CUR_BASE>> possible_functions;
|
vector <FiniteFunction<CUR_BASE>> possible_functions;
|
||||||
|
|
||||||
size_t total_possible_functions;
|
size_t total_possible_functions;
|
||||||
atomic<long> current_function;
|
atomic<long> current_function;
|
||||||
|
|
||||||
|
atomic<long> completed_tasks;
|
||||||
mutex possible_functions_mutex;
|
mutex possible_functions_mutex;
|
||||||
|
|
||||||
list< set<FiniteFunction<CUR_BASE>> > shared_function_classes;
|
list< set<FiniteFunction<CUR_BASE>> > shared_function_classes;
|
||||||
mutex shared_functions_mutex;
|
mutex shared_functions_mutex;
|
||||||
|
|
||||||
void do_work() {
|
|
||||||
list< set<FiniteFunction<CUR_BASE>> > local_function_classes;
|
|
||||||
|
|
||||||
FiniteFunction<CUR_BASE> identical_x(string("000 111 222"));
|
|
||||||
FiniteFunction<CUR_BASE> identical_y(string("012 012 012"));
|
|
||||||
|
|
||||||
while ( true ) {
|
|
||||||
possible_functions_mutex.lock();
|
|
||||||
if ( current_function >= total_possible_functions ) {
|
|
||||||
possible_functions_mutex.unlock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
FiniteFunction<CUR_BASE> base_function = possible_functions.at(
|
|
||||||
current_function
|
|
||||||
);
|
|
||||||
++current_function;
|
|
||||||
possible_functions_mutex.unlock();
|
|
||||||
|
|
||||||
set< FiniteFunction<CUR_BASE> > func_class = generate_function_class(base_function);
|
|
||||||
func_class.erase(identical_x);
|
|
||||||
func_class.erase(identical_y);
|
|
||||||
|
|
||||||
bool is_need_append = true;
|
list<FunctionTask> task_list;
|
||||||
vector<decltype(local_function_classes)::iterator> functions_to_remove;
|
mutex task_mutex;
|
||||||
for (auto it = local_function_classes.begin(); it != local_function_classes.end(); ++it) {
|
|
||||||
if ( func_class.size() < it->size() ) {
|
list<FunctionTask> processed_task_list;
|
||||||
if (includes(
|
mutex processed_task_mutex;
|
||||||
it->begin(),
|
|
||||||
it->end(),
|
set<FiniteFunction<CUR_BASE>> bad_functions;
|
||||||
func_class.begin(),
|
|
||||||
func_class.end()
|
|
||||||
)
|
void do_work() {
|
||||||
) {
|
std::chrono::milliseconds SLEEP_TIME(10);
|
||||||
// новый класс функций часть уже существующего
|
while ( true ) {
|
||||||
functions_to_remove.push_back(it);
|
FunctionTask task;
|
||||||
}
|
task_mutex.lock();
|
||||||
|
if ( task_list.begin() != task_list.end() ) {
|
||||||
|
task = task_list.front();
|
||||||
|
task_list.pop_front();
|
||||||
|
task_mutex.unlock();
|
||||||
|
} else {
|
||||||
|
task_mutex.unlock();
|
||||||
|
if ( completed_tasks < total_possible_functions ) {
|
||||||
|
// Не все таски, подождём, пока добавят ещё
|
||||||
|
std::this_thread::sleep_for(SLEEP_TIME);
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if (includes(
|
cout << "thread " << this_thread::get_id() << ": "
|
||||||
func_class.begin(),
|
<< " finished" << endl;
|
||||||
func_class.end(),
|
break;
|
||||||
it->begin(),
|
|
||||||
it->end()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// новый класс функций надмножество существующего
|
|
||||||
is_need_append = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( is_need_append )
|
|
||||||
local_function_classes.push_back(func_class);
|
tie(task.current, task.is_finished) = extend_function_class(
|
||||||
for (auto&& to_remove: functions_to_remove)
|
task.current,
|
||||||
local_function_classes.erase(to_remove);
|
get_math_coeff(task.current_max_coeff)
|
||||||
|
);
|
||||||
|
cout << "k=" << task.current_max_coeff << endl;
|
||||||
|
processed_task_mutex.lock();
|
||||||
|
processed_task_list.push_back(task);
|
||||||
|
processed_task_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "local " << this_thread::get_id() << ": "
|
|
||||||
<< local_function_classes.size() << " functions" << endl;
|
|
||||||
|
|
||||||
// Сливаем всё вметсе
|
|
||||||
shared_functions_mutex.lock();
|
|
||||||
for (auto it_local = local_function_classes.begin(); it_local != local_function_classes.end(); ++it_local) {
|
|
||||||
auto func_class = *it_local;
|
|
||||||
bool is_need_append = true;
|
|
||||||
vector<decltype(local_function_classes)::iterator> functions_to_remove;
|
|
||||||
for (auto it = shared_function_classes.begin(); it != shared_function_classes.end(); ++it) {
|
|
||||||
if ( func_class.size() < it->size() ) {
|
|
||||||
if (includes(
|
|
||||||
it->begin(),
|
|
||||||
it->end(),
|
|
||||||
func_class.begin(),
|
|
||||||
func_class.end()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// новый класс функций часть уже существующего
|
|
||||||
functions_to_remove.push_back(it);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (includes(
|
|
||||||
func_class.begin(),
|
|
||||||
func_class.end(),
|
|
||||||
it->begin(),
|
|
||||||
it->end()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// новый класс функций надмножество существующего
|
|
||||||
is_need_append = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( is_need_append )
|
|
||||||
shared_function_classes.push_back(func_class);
|
|
||||||
for (auto&& to_remove: functions_to_remove)
|
|
||||||
shared_function_classes.erase(to_remove);
|
|
||||||
}
|
|
||||||
shared_functions_mutex.unlock();
|
|
||||||
cout << "shared_functions_mutex unlocked" << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void process_task_lists() {
|
||||||
|
cout << "processing starts " << endl;
|
||||||
|
|
||||||
|
std::chrono::milliseconds SLEEP_TIME(10);
|
||||||
|
while ( completed_tasks < total_possible_functions ) {
|
||||||
|
// опустошим выполненные таски
|
||||||
|
processed_task_mutex.lock();
|
||||||
|
list<FunctionTask> local_processed_task_list = processed_task_list;
|
||||||
|
processed_task_list.clear();
|
||||||
|
processed_task_mutex.unlock();
|
||||||
|
|
||||||
|
for ( auto&& task: local_processed_task_list ) {
|
||||||
|
if ( !task.is_finished ) {
|
||||||
|
if ( is_bad_class(task.current, bad_functions) ) {
|
||||||
|
//cout << "bad class" << endl;
|
||||||
|
++completed_tasks;
|
||||||
|
} else {
|
||||||
|
++task.current_max_coeff;
|
||||||
|
task_mutex.lock();
|
||||||
|
task_list.push_back(task);
|
||||||
|
task_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cout << "task finished, appending" << endl;
|
||||||
|
++completed_tasks;
|
||||||
|
auto func_class = task.current;
|
||||||
|
bool is_need_append = true;
|
||||||
|
vector<decltype(shared_function_classes)::iterator> functions_to_remove;
|
||||||
|
for (auto it = shared_function_classes.begin(); it != shared_function_classes.end(); ++it) {
|
||||||
|
if ( func_class.size() < it->size() ) {
|
||||||
|
if (includes(
|
||||||
|
it->begin(),
|
||||||
|
it->end(),
|
||||||
|
func_class.begin(),
|
||||||
|
func_class.end()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// новый класс функций часть уже существующего
|
||||||
|
functions_to_remove.push_back(it);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (includes(
|
||||||
|
func_class.begin(),
|
||||||
|
func_class.end(),
|
||||||
|
it->begin(),
|
||||||
|
it->end()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// новый класс функций надмножество существующего
|
||||||
|
is_need_append = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( is_need_append ) {
|
||||||
|
shared_function_classes.push_back(func_class);
|
||||||
|
for (auto&& func: func_class)
|
||||||
|
bad_functions.insert(func);
|
||||||
|
}
|
||||||
|
for (auto&& to_remove: functions_to_remove) {
|
||||||
|
shared_function_classes.erase(to_remove);
|
||||||
|
cout << "Removing class from shared_function_classes" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local_processed_task_list.clear();
|
||||||
|
|
||||||
|
// Поспим, чтобы не работать слишком часто
|
||||||
|
std::this_thread::sleep_for(SLEEP_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto FiniteFunctionHasher = [](const FiniteFunction<CUR_BASE> &f) -> uint32_t {
|
auto FiniteFunctionHasher = [](const FiniteFunction<CUR_BASE> &f) -> uint32_t {
|
||||||
return f.get_hash();
|
return f.get_hash();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto THREADS_COUNT = thread::hardware_concurrency();
|
auto THREADS_COUNT = max(static_cast<int>(thread::hardware_concurrency()), 2);
|
||||||
cout << "Using " << THREADS_COUNT << " threads" << endl;
|
cout << "Using " << THREADS_COUNT << " threads" << endl;
|
||||||
|
|
||||||
auto funcs = get_funcs<CUR_BASE>();
|
auto funcs = get_funcs<CUR_BASE>();
|
||||||
@@ -404,17 +496,29 @@ int main() {
|
|||||||
allowed_functions.end(),
|
allowed_functions.end(),
|
||||||
back_inserter(possible_functions)
|
back_inserter(possible_functions)
|
||||||
);
|
);
|
||||||
|
completed_tasks = 0;
|
||||||
|
for (auto&& func: allowed_functions) {
|
||||||
|
FunctionTask task;
|
||||||
|
task.current.insert(func);
|
||||||
|
task.is_finished = false;
|
||||||
|
task.current_max_coeff = 1;
|
||||||
|
task_list.push_back(task);
|
||||||
|
}
|
||||||
|
|
||||||
total_possible_functions = possible_functions.size();
|
cout << "Total funcs in list" << task_list.size() << " functions" << endl;
|
||||||
current_function = 0;
|
|
||||||
|
total_possible_functions = task_list.size();
|
||||||
|
|
||||||
vector< thread > thread_pool;
|
vector< thread > thread_pool;
|
||||||
|
thread task_processer(process_task_lists);
|
||||||
|
|
||||||
for (size_t i = 0; i < THREADS_COUNT; ++i)
|
for (size_t i = 0; i < THREADS_COUNT - 1; ++i)
|
||||||
thread_pool.push_back(thread(do_work));
|
thread_pool.push_back(thread(do_work));
|
||||||
|
|
||||||
for (auto&& t: thread_pool)
|
for (auto&& t: thread_pool)
|
||||||
t.join();
|
t.join();
|
||||||
|
|
||||||
|
task_processer.join();
|
||||||
|
|
||||||
cout << "Shared " << shared_function_classes.size() << " functions!" << endl;
|
cout << "Shared " << shared_function_classes.size() << " functions!" << endl;
|
||||||
// перегоняем список с классами в массив с классами
|
// перегоняем список с классами в массив с классами
|
||||||
|
|||||||
Reference in New Issue
Block a user