// Licensed under the MIT License . // SPDX-License-Identifier: MIT // Copyright (c) 2021 Noah H. and Tom H. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "robin_hood.h" typedef unsigned long long int LI_t; typedef int pLI_t; namespace hash_tuple { template struct hash { size_t operator()(TT const& tt) const { return robin_hood::hash()(tt); } }; } namespace hash_tuple{ namespace { template inline void hash_combine(std::size_t& seed, T const& v) { seed ^= hash_tuple::hash()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } } } namespace hash_tuple{ namespace { // Recursive template code derived from Matthieu M. template ::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl::apply(seed, tuple); hash_combine(seed, std::get(tuple)); } }; template struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template struct hash> { size_t operator()(std::tuple const& tt) const { size_t seed = 0; HashValueImpl >::apply(seed, tt); return seed; } }; } using namespace std; // 0 INVASION PERCOLATION // 1 LEATH ALGORITHM #define RUN 0 //3 H_3 //4 H_4 #define TYPE 4 #if TYPE == 3 //H3 typedef tuple Vertex; typedef tuple VVertex; #endif #if TYPE == 4 //H4 typedef tuple Vertex; typedef tuple VVertex; #endif vector vertex_neighbours(Vertex); tuple LeathRun(int,double); vector rand_bernoulli(float,int); void write_to_file(vector> &vec, string file_name) { std::ofstream f(file_name); for(vector>::const_iterator i = vec.begin(); i != vec.end(); ++i) { f << get<0>(*i) << ','<< get<1>(*i) << ','<(*i) << '\n'; } } LI_t rand_long() { thread_local static random_device rd; thread_local static mt19937_64 rng(rd()); thread_local static uniform_int_distribution dist; return dist(rng); } //The fractal coordinates are encoded in binary vector nbs4(LI_t vertex) { short first = vertex &15; LI_t cleared = vertex; LI_t vertex_copy = vertex; for(int i = 0;i <4;i++) { cleared &= ~(1ULL<>4; flipped &= ~(1ULL << (4*i+4)); flipped &= ~(1ULL << (4*i+5)); flipped &= ~(1ULL << (4*i+6)); flipped &= ~(1ULL << (4*i+7)); if((vertex_copy &15)!=first) { break; } } short after = vertex_copy &15; short replace_first_1=-1; short replace_after_1; short replace_first_2; short replace_after_2; if(first ==0 && after ==15) { replace_first_1=1; replace_after_1=0; replace_first_2=15; replace_after_2=14; } else if(first ==15 && after ==14) { replace_first_1=0; replace_after_1=15; replace_first_2=14; replace_after_2=13; } else if(first ==14 && after ==13) { replace_first_1=15; replace_after_1=14; replace_first_2=13; replace_after_2=12; } else if(first ==13 && after ==12) { replace_first_1=14; replace_after_1=13; replace_first_2=12; replace_after_2=11; } else if(first ==12 && after ==11) { replace_first_1=13; replace_after_1=12; replace_first_2=11; replace_after_2=10; } else if(first ==11 && after ==10) { replace_first_1=12; replace_after_1=11; replace_first_2=10; replace_after_2=9; } else if(first ==10 && after ==9) { replace_first_1=11; replace_after_1=10; replace_first_2=9; replace_after_2=8; } else if(first ==9 && after ==8) { replace_first_1=10; replace_after_1=9; replace_first_2=8; replace_after_2=7; } else if(first ==8 && after ==7) { replace_first_1=9; replace_after_1=8; replace_first_2=7; replace_after_2=6; } else if(first ==7 && after ==6) { replace_first_1=8; replace_after_1=7; replace_first_2=6; replace_after_2=5; } else if(first ==6 && after ==5) { replace_first_1=7; replace_after_1=6; replace_first_2=5; replace_after_2=4; } else if(first ==5 && after ==4) { replace_first_1=6; replace_after_1=5; replace_first_2=4; replace_after_2=3; } else if(first ==4 && after ==3) { replace_first_1=5; replace_after_1=4; replace_first_2=3; replace_after_2=2; } else if(first ==3 && after ==2) { replace_first_1=4; replace_after_1=3; replace_first_2=2; replace_after_2=1; } else if(first ==2 && after ==1) { replace_first_1=3; replace_after_1=2; replace_first_2=1; replace_after_2=0; } else if(first ==1 && after ==0) { replace_first_1=2; replace_after_1=1; replace_first_2=0; replace_after_2=15; } else { vector nbs; if(first == 0 ) { nbs={cleared|1,cleared|15}; } else if(first == 1) { nbs={cleared|2,cleared|0}; } else if(first == 2) { nbs={cleared|3,cleared|1}; } else if(first == 3) { nbs={cleared|4,cleared|2}; } else if(first == 4) { nbs={cleared|5,cleared|3}; } else if(first == 5) { nbs={cleared|6,cleared|4}; } else if(first == 6) { nbs={cleared|7,cleared|5}; } else if(first == 7) { nbs={cleared|8,cleared|6}; } else if(first == 8) { nbs={cleared|9,cleared|7}; } else if(first == 9) { nbs={cleared|10,cleared|8}; } else if(first == 10) { nbs={cleared|11,cleared|9}; } else if(first == 11) { nbs={cleared|12,cleared|10}; } else if(first == 12) { nbs={cleared|13,cleared|11}; } else if(first == 13) { nbs={cleared|14,cleared|12}; } else if(first == 14) { nbs={cleared|15,cleared|13}; } else if(first == 15) { nbs={cleared|0,cleared|14}; } return nbs; } LI_t flipped_2 = flipped; for(int j=0;j<=i;j++) { flipped |=(replace_first_1<<4*j); } flipped |=(replace_after_1<<4*(i+1)); for(int j=0;j<=i;j++) { flipped_2 |=(replace_first_2<<4*j); } flipped_2 |=(replace_after_2<<4*(i+1)); vector nbs; if(first == 0 ) { nbs={flipped,flipped_2,cleared|1,cleared|15}; } else if(first == 1) { nbs={flipped,flipped_2,cleared|2,cleared|0}; } else if(first == 2) { nbs={flipped,flipped_2,cleared|3,cleared|1}; } else if(first == 3) { nbs={flipped,flipped_2,cleared|4,cleared|2}; } else if(first == 4) { nbs={flipped,flipped_2,cleared|5,cleared|3}; } else if(first == 5) { nbs={flipped,flipped_2,cleared|6,cleared|4}; } else if(first == 6) { nbs={flipped,flipped_2,cleared|7,cleared|5}; } else if(first == 7) { nbs={flipped,flipped_2,cleared|8,cleared|6}; } else if(first == 8) { nbs={flipped,flipped_2,cleared|9,cleared|7}; } else if(first == 9) { nbs={flipped,flipped_2,cleared|10,cleared|8}; } else if(first == 10) { nbs={flipped,flipped_2,cleared|11,cleared|9}; } else if(first == 11) { nbs={flipped,flipped_2,cleared|12,cleared|10}; } else if(first == 12) { nbs={flipped,flipped_2,cleared|13,cleared|11}; } else if(first == 13) { nbs={flipped,flipped_2,cleared|14,cleared|12}; } else if(first == 14) { nbs={flipped,flipped_2,cleared|15,cleared|13}; } else if(first == 15) { nbs={flipped,flipped_2,cleared|0,cleared|14}; } return nbs; } vector nbs3(LI_t vertex) { short first = vertex &7; LI_t cleared = vertex; LI_t vertex_copy = vertex; for(int i = 0;i <3;i++) { cleared &= ~(1ULL<>3; flipped &= ~(1ULL << (3*i+3)); flipped &= ~(1ULL << (3*i+4)); flipped &= ~(1ULL << (3*i+5)); if((vertex_copy &7)!=first) { break; } } short after = vertex_copy &7; short replace_first_1=-1; short replace_after_1; short replace_first_2; short replace_after_2; if(first ==0 && after ==7) { replace_first_1=1; replace_after_1=0; replace_first_2=7; replace_after_2=6; } else if(first ==7 && after ==6) { replace_first_1=0; replace_after_1=7; replace_first_2=6; replace_after_2=5; } else if(first ==6 && after ==5) { replace_first_1=7; replace_after_1=6; replace_first_2=5; replace_after_2=4; } else if(first ==5 && after ==4) { replace_first_1=6; replace_after_1=5; replace_first_2=4; replace_after_2=3; } else if(first ==4 && after ==3) { replace_first_1=5; replace_after_1=4; replace_first_2=3; replace_after_2=2; } else if(first ==3 && after ==2) { replace_first_1=4; replace_after_1=3; replace_first_2=2; replace_after_2=1; } else if(first ==2 && after ==1) { replace_first_1=3; replace_after_1=2; replace_first_2=1; replace_after_2=0; } else if(first ==1 && after ==0) { replace_first_1=2; replace_after_1=1; replace_first_2=0; replace_after_2=7; } else { vector nbs; if(first == 0 ) { nbs={cleared|1,cleared|7}; } else if(first == 1) { nbs={cleared|2,cleared|0}; } else if(first == 2) { nbs={cleared|3,cleared|1}; } else if(first == 3) { nbs={cleared|4,cleared|2}; } else if(first == 4) { nbs={cleared|5,cleared|3}; } else if(first == 5) { nbs={cleared|6,cleared|4}; } else if(first == 6) { nbs={cleared|7,cleared|5}; } else if(first == 7) { nbs={cleared|0,cleared|6}; } return nbs; } LI_t flipped_2 = flipped; for(int j=0;j<=i;j++) { flipped |=(replace_first_1<<3*j); } flipped |=(replace_after_1<<3*(i+1)); for(int j=0;j<=i;j++) { flipped_2 |=(replace_first_2<<3*j); } flipped_2 |=(replace_after_2<<3*(i+1)); vector nbs; if(first == 0 ) { nbs={flipped,flipped_2,cleared|1,cleared|7}; } else if(first == 1) { nbs={flipped,flipped_2,cleared|2,cleared|0}; } else if(first == 2) { nbs={flipped,flipped_2,cleared|3,cleared|1}; } else if(first == 3) { nbs={flipped,flipped_2,cleared|4,cleared|2}; } else if(first == 4) { nbs={flipped,flipped_2,cleared|5,cleared|3}; } else if(first == 5) { nbs={flipped,flipped_2,cleared|6,cleared|4}; } else if(first == 6) { nbs={flipped,flipped_2,cleared|7,cleared|5}; } else if(first == 7) { nbs={flipped,flipped_2,cleared|0,cleared|6}; } return nbs; } vector nbs3o2(LI_t vertex) { short first = vertex &7; LI_t cleared = vertex; LI_t vertex_copy = vertex; for(int i = 0;i <3;i++) { cleared &= ~(1ULL<>3; flipped &= ~(1ULL << (3*i+3)); flipped &= ~(1ULL << (3*i+4)); flipped &= ~(1ULL << (3*i+5)); if((vertex_copy &7)!=first) { break; } } short after = vertex_copy &7; short replace_first_1; short replace_after_1; short replace_first_2=-1; short replace_after_2; if(after==1 && first ==5) { replace_after_1=0; replace_first_1=1; } else if(after==0 && first ==1) { replace_after_1=1; replace_first_1=5; } else if(after==7 && first ==3) { replace_after_1=6; replace_first_1=7; } else if(after==6 && first ==7) { replace_after_1=7; replace_first_1=3; } else if(after==2 && first ==3) { replace_after_1=3; replace_first_1=7; } else if(after==3 && first ==7) { replace_after_1=2; replace_first_1=3; } else if(after==4 && first ==5) { replace_after_1=5; replace_first_1=1; } else if(after==5 && first ==1) { replace_after_1=4; replace_first_1=5; } else if(after==0 && first ==5) { replace_after_1=2; replace_first_1=7; replace_after_2=6; replace_first_2=3; } else if(after==2 && first ==7) { replace_after_1=0; replace_first_1=5; replace_after_2=4; replace_first_2=1; } else if(after==4 && first ==1) { replace_after_1=2; replace_first_1=7; replace_after_2=6; replace_first_2=3; } else if(after==6 && first ==3) { replace_after_1=0; replace_first_1=5; replace_after_2=4; replace_first_2=1; } else { vector nbs; if(first == 0 ) { nbs={cleared|1,cleared|2,cleared|6}; } else if(first == 1) { nbs={cleared|0}; } else if(first == 2) { nbs={cleared|3,cleared|4,cleared|0}; } else if(first == 3) { nbs={cleared|2}; } else if(first == 4) { nbs={cleared|5,cleared|6,cleared|2}; } else if(first == 5) { nbs={cleared|4}; } else if(first == 6) { nbs={cleared|7,cleared|0,cleared|4}; } else if(first == 7) { nbs={cleared|6}; } return nbs; } if(replace_first_2!=-1) { LI_t flipped_2 = flipped; for(int j=0;j<=i;j++) { flipped |=(replace_first_1<<3*j); } flipped |=(replace_after_1<<3*(i+1)); for(int j=0;j<=i;j++) { flipped_2 |=(replace_first_2<<3*j); } flipped_2 |=(replace_after_2<<3*(i+1)); vector nbs; if(first == 0 ) { nbs={flipped,flipped_2,cleared|1,cleared|2,cleared|6}; } else if(first == 1) { nbs={flipped,flipped_2,cleared|0}; } else if(first == 2) { nbs={flipped,flipped_2,cleared|3,cleared|4,cleared|0}; } else if(first == 3) { nbs={flipped,flipped_2,cleared|2}; } else if(first == 4) { nbs={flipped,flipped_2,cleared|5,cleared|6,cleared|2}; } else if(first == 5) { nbs={flipped,flipped_2,cleared|4}; } else if(first == 6) { nbs={flipped,flipped_2,cleared|7,cleared|0,cleared|4}; } else if(first == 7) { nbs={flipped,flipped_2,cleared|6}; } return nbs; } else { for(int j=0;j<=i;j++) { flipped |=(replace_first_1<<3*j); } flipped |=(replace_after_1<<3*(i+1)); vector nbs; if(first == 0 ) { nbs={flipped,cleared|1,cleared|2,cleared|6}; } else if(first == 1) { nbs={flipped,cleared|0}; } else if(first == 2) { nbs={flipped,cleared|3,cleared|4,cleared|0}; } else if(first == 3) { nbs={flipped,cleared|2}; } else if(first == 4) { nbs={flipped,cleared|5,cleared|6,cleared|2}; } else if(first == 5) { nbs={flipped,cleared|4}; } else if(first == 6) { nbs={flipped,cleared|7,cleared|0,cleared|4}; } else if(first == 7) { nbs={flipped,cleared|6}; } return nbs; } } #if TYPE ==3 vector vertex_neighbours(Vertex v) { LI_t nbs3_1 = get<0>(v); LI_t nbs3_2 = get<1>(v); pLI_t z1 = get<2>(v); pLI_t z2 = get<3>(v); vector nbs3_1_neighbours = nbs3(nbs3_1); vector nbs3_2_neighbours = nbs3(nbs3_2); //vector quad_neighbours = neighbours_cub(quad); //std::cout< neighbours; //neighbours.reserve(tri_1_neighbours.size()+tri_2_neighbours.size()+quad_neighbours.size()); neighbours.reserve(4+nbs3_1_neighbours.size()+nbs3_2_neighbours.size()); for (int i=0;i vertex_neighbours(Vertex v) { LI_t a3o2_1 = get<0>(v); LI_t a3o2_2 = get<1>(v); LI_t a4_1 = get<2>(v); pLI_t z = get<3>(v); vector a3o2_1_neighbours = nbs3o2(a3o2_1); vector a3o2_2_neighbours = nbs3o2(a3o2_2); vector a4_1_neighbours = nbs4(a4_1); vector neighbours; neighbours.reserve(a3o2_1_neighbours.size()+\ a3o2_2_neighbours.size()+\ a4_1_neighbours.size()+2); for (int i=0;i rand_bernoulli(double p,int n) { thread_local static random_device rd; thread_local static mt19937 rng(rd()); thread_local static bernoulli_distribution dist(p); thread_local auto gen = [](){ return dist(rng); }; vector open(n); generate(begin(open), end(open), gen); return open; } void write_to_file(vector vec, string file_name) { std::ofstream outFile(file_name); for (const auto &e : vec) outFile << e << "\n"; } vector rand_uniform(int n) { thread_local static random_device rd; thread_local static mt19937_64 rng(rd()); thread_local static uniform_real_distribution dist(0.0,1.0); thread_local auto gen = [](){ return dist(rng); }; vector values(n); generate(begin(values), end(values), gen); return values; } class Compare { public: bool operator() (const VVertex& v1 , const VVertex& v2 ) { return get<0>(v1)>get<0>(v2); } }; LI_t vector_to_int(vector coords,int mult) { LI_t total = 0; int i=0; for (auto it = coords.rbegin(); it != coords.rend(); ++it) { total+=pow(mult,i)* (*it); i++; } return total; } vector int_to_vector(LI_t num,short mult) { if(num==0) { return vector{0}; } std::vector digits (floor(log(num)/log(mult))+1); int i=0; while(num > 0) { digits[digits.size()-1-i] = num%mult; num /= mult; i++; } return digits; } vector> int_to_vector(vector nums,int mult) { vector> all(nums.size()); for (int i=0;i ostream& operator<< (ostream& out, const vector& v) { out << "{"; size_t last = v.size() - 1; for(size_t i = 0; i < v.size(); ++i) { out << v[i]; if (i != last) out << ", "; } out << "}"; return out; } vector invasion_percolation(int n) { int max_t = ceil(4*log(float(n)/100)/log(2))+1; //std::cout< rec_vals(max_t); for (int i=0;i> visited_vertices; visited_vertices.reserve(n+1); visited_vertices.insert(initial_vertex); vector frontier_edges = vertex_neighbours(initial_vertex); int s = frontier_edges.size(); vector frontier_values = rand_uniform(s); priority_queue, Compare> frontier; for (int i=0;i visited_numbers; visited_numbers.reserve(max_t); int visited_number_running = 4; double current_marker = 1; int visited = 0; while(visited0 && visited%1000000==0) { auto it=frontier.lower_bound(make_tuple(current_marker,0,0)); frontier.erase(it,frontier.end()); }*/ visited+=1; VVertex currentE = frontier.top(); Vertex current = make_tuple(get<1>(currentE),get<2>(currentE),get<3>(currentE),get<4>(currentE)); frontier.pop(); //current_marker=1; //Hmult3 #if TYPE==3 current_marker = (double)visited/(double)visited_number_running+1.005*pow(visited,-0.461); #endif //Hmult4 #if TYPE==4 current_marker = (double)visited/(double)visited_number_running+0.5578*pow(visited,-0.41583); #endif if (visited_vertices.find(current) != visited_vertices.end()) { if (visited==rec_vals[rec_index]) { rec_index+=1; visited_numbers.push_back(visited_number_running); } continue; } visited_vertices.insert(current); vector neighbours = vertex_neighbours(current); int num_n_v = 0; short ss = neighbours.size(); vector random = rand_uniform(ss); for (int i=0;i(nb),get<1>(nb),get<2>(nb),get<3>(nb)); } } } visited_number_running += num_n_v; if(visited==rec_vals[rec_index]) { rec_index+=1; visited_numbers.push_back(visited_number_running); } } return visited_numbers; } void write_to_file(vector vec, string file_name) { std::ofstream outFile(file_name); for (const auto &e : vec) outFile << e << "\n"; } tuple LeathRun(int n, double p) { Vertex initial_vertex = std::make_tuple(rand_long(),rand_long(),rand_long(),0); robin_hood::unordered_set > visited_vertices; queue vertex_frontier; vertex_frontier.push(initial_vertex); int visited = 1; int num_open_edges = 0; int num_closed_edges = 0; while(visited < n) { if (vertex_frontier.empty()) { break; } Vertex current = vertex_frontier.front(); vertex_frontier.pop(); if (visited_vertices.find(current) != visited_vertices.end()) { continue; } visited_vertices.insert(current); vector neighbours = vertex_neighbours(current); short nn = neighbours.size(); vector open = rand_bernoulli(p,nn); int num_open = 0; int num = 0; for(int i=0; i < nn; i++) { if(visited_vertices.find(neighbours[i]) == visited_vertices.end()) { if(open[num] == true) { num_open += 1; vertex_frontier.push(neighbours[i]); } num+=1; } } num_open_edges += num_open; num_closed_edges += (num-num_open); visited+=1; } return make_tuple(visited,num_open_edges,num_closed_edges); } // RUN LEATH ALGORITHM // 1. n = max distance/number of steps (depending on TERM) // 2. p = percolation probability // 3. N = number of samples // 4. filename = output path #if RUN == 1 int main(int argc, char** argv) { int n = stoi(argv[1]); double p = stod(argv[2]); int N = stoi(argv[3]); string filename = argv[4]; std::cout << "n="<> file_results(num_this_file); for (int w=0; w results; results.reserve((ceil(4*log(float(n)/100)/log(2))+1)* num_runs_this_file); for (int i=0;i visited_numbers = invasion_percolation(n); copy (visited_numbers.begin(), visited_numbers.end(),back_inserter(results)); } write_to_file(results,filename+"/f"+to_string(j)); } std::cout << "done\n"; } #endif