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 <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;
|
||||
// перегоняем список с классами в массив с классами
|
||||
|
||||
Reference in New Issue
Block a user