First version with advanced algorithm

This commit is contained in:
2018-04-25 23:57:18 +03:00
parent 23f18e9e15
commit 6d07558df8
3 changed files with 233 additions and 99 deletions

19
al_utility.cpp Normal file
View 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
View 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
View File

@@ -16,15 +16,20 @@
#include <atomic>
#include <iterator>
#include "al_utility.hpp"
#include "finite_function.hpp"
using namespace std;
const CellType CUR_BASE = 3;
const int ARGS_COUNT = 2;
struct FunctionTask {
set<FiniteFunction<CUR_BASE>> current;
bool is_finished;
int current_max_coeff;
};
template <size_t BASE>
class FixedIniter {
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());
}
// Возвращает новый функциональный класс, размером не сильно больше, чем 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;
size_t total_possible_functions;
atomic<long> current_function;
atomic<long> completed_tasks;
mutex possible_functions_mutex;
list< set<FiniteFunction<CUR_BASE>> > shared_function_classes;
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;
vector<decltype(local_function_classes)::iterator> functions_to_remove;
for (auto it = local_function_classes.begin(); it != local_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);
}
list<FunctionTask> task_list;
mutex task_mutex;
list<FunctionTask> processed_task_list;
mutex processed_task_mutex;
set<FiniteFunction<CUR_BASE>> bad_functions;
void do_work() {
std::chrono::milliseconds SLEEP_TIME(10);
while ( true ) {
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 {
if (includes(
func_class.begin(),
func_class.end(),
it->begin(),
it->end()
)
) {
// новый класс функций надмножество существующего
is_need_append = false;
break;
}
cout << "thread " << this_thread::get_id() << ": "
<< " finished" << endl;
break;
}
}
if ( is_need_append )
local_function_classes.push_back(func_class);
for (auto&& to_remove: functions_to_remove)
local_function_classes.erase(to_remove);
tie(task.current, task.is_finished) = extend_function_class(
task.current,
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() {
auto FiniteFunctionHasher = [](const FiniteFunction<CUR_BASE> &f) -> uint32_t {
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;
auto funcs = get_funcs<CUR_BASE>();
@@ -404,17 +496,29 @@ int main() {
allowed_functions.end(),
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();
current_function = 0;
cout << "Total funcs in list" << task_list.size() << " functions" << endl;
total_possible_functions = task_list.size();
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));
for (auto&& t: thread_pool)
t.join();
task_processer.join();
cout << "Shared " << shared_function_classes.size() << " functions!" << endl;
// перегоняем список с классами в массив с классами