7 #ifndef WONTON_EQUIFACTOR_H_ 8 #define WONTON_EQUIFACTOR_H_ 12 #include <unordered_set> 45 void print_sets(
std::vector<std::vector<int>> sets);
51 #if defined(__GNUC__) && (__GNUC__ == 7 && __GNUC_MINOR__ == 3) 52 __attribute__ ((unused))
55 std::vector<int> equifactor(
int const N,
int const D,
int const randseed = 0) {
56 clock_t startclock, curclock;
59 assert(N > 0 && D > 0);
62 return std::vector<int>(1, N);
66 std::vector<int> prime_facs = prime_factors(N);
67 std::sort(prime_facs.begin(), prime_facs.end());
68 int const prime_facs_size = prime_facs.size();
69 if (prime_facs_size < D) {
70 for (
int i = prime_facs_size; i < D; i++)
71 prime_facs.push_back(1);
75 std::vector<std::vector<int>> sets(D, {1});
76 std::vector<std::vector<int>> minsets;
83 for (
int const n : prime_facs) {
84 sets[kset%D].push_back(n);
90 std::cerr <<
"\n\nNumber of sets D " << D <<
"\n";
91 std::cerr <<
"INITIAL STATE:\n";
96 std::vector<int> products(D);
98 bool outer_done =
false;
101 int num_no_change = 0;
102 bool allow_swap_climb =
false, allow_move_climb =
false;
111 while (!outer_done) {
114 products.assign(D, 1.0);
115 for (
int i = 0; i < D; i++)
116 for (
int const n : sets[i])
120 int minprod = *(std::min_element(products.begin(), products.end()));
121 int maxprod = *(std::max_element(products.begin(), products.end()));
123 int diff = maxprod-minprod;
130 std::vector<int> iminsets, imaxsets;
131 for (
int i = 0; i < D; i++) {
132 if (products[i] == minprod) iminsets.push_back(i);
133 if (products[i] == maxprod) imaxsets.push_back(i);
139 srand(curclock - startclock);
142 int iset1 = iminsets[rand() % iminsets.size()];
143 int iset2 = imaxsets[rand() % imaxsets.size()];
145 std::vector<int>& set1 = sets[iset1];
146 std::vector<int>& set2 = sets[iset2];
147 int & prod1 = products[iset1];
148 int & prod2 = products[iset2];
153 bool inner_done =
false;
154 while (!inner_done) {
158 srand(curclock - startclock);
161 int offset = rand() % set1.size();
162 auto j_set1 = set1.begin() + offset;
164 while (*j_set1 == 1) {
165 offset = rand() % set1.size();
166 j_set1 = set1.begin() + offset;
169 int& val_set1 = *j_set1;
173 srand(curclock - startclock);
176 offset = rand() % set2.size();
177 auto j_set2 = set2.begin() + offset;
179 while (*j_set2 == 1) {
180 offset = rand() % set2.size();
181 j_set2 = set2.begin() + offset;
184 int& val_set2 = *j_set2;
191 int prod1_new = val_set2*prod1/val_set1;
192 int prod2_new = val_set1*prod2/val_set2;
194 int diff1 = prod2_new - prod1_new;
196 if (std::abs(diff1) < std::abs(diff) || allow_swap_climb) {
198 std::swap(val_set1, val_set2);
203 allow_swap_climb =
false;
211 prod1_new = prod1*val_set2;
212 prod2_new = prod2/val_set2;
214 diff1 = prod2_new - prod1_new;
216 if (std::abs(diff1) < std::abs(diff) || allow_move_climb) {
218 set1.push_back(val_set2);
224 allow_move_climb =
false;
229 if (
unsigned(inner_iter) > 2*set1.size()) inner_done =
true;
235 minprod = *(std::min_element(products.begin(), products.end()));
236 maxprod = *(std::max_element(products.begin(), products.end()));
238 int maxdiff = maxprod-minprod;
240 if (maxdiff == olddiff)
244 if (maxdiff < olddiff)
249 if (num_no_change > 5) {
251 allow_swap_climb =
true;
253 allow_move_climb =
true;
257 if (nclimbs > 10) outer_done =
true;
258 if (outer_iter > maxiter) outer_done =
true;
262 std::cerr <<
"\nFINAL STATE:\n";
263 std::vector<std::vector<int>> newsets(D);
264 for (
int i = 0; i < D; i++) {
265 if (minsets[i].size() == 1)
266 newsets[i].push_back(minsets[i][0]);
268 for (
int const n : minsets[i])
269 if (n != 1) newsets[i].push_back(n);
271 std::swap(minsets,newsets);
275 products.assign(D, 1.0);
276 for (
int i = 0; i < D; i++) {
278 for (
int const n : minsets[i])
287 void print_sets(
std::vector<std::vector<int>> sets) {
288 int nsets = sets.size();
289 int minprod = std::numeric_limits<int>::max();
290 int maxprod = std::numeric_limits<int>::min();
291 for (
int i = 0; i < nsets; i++) {
292 std::cerr <<
"Set " << i <<
": ";
294 for (
int const n : sets[i]) {
296 std::cerr << n <<
" ";
298 std::cerr <<
"prod=" << prod <<
"\n";
304 int maxdiff = maxprod - minprod;
305 std::cerr <<
"Max diff: " << maxdiff <<
"\n";
Factorize a number N into D equal (or nearly equal) factors.
Definition: adaptive_refinement_mesh.h:31
std::vector< T > vector
Definition: wonton.h:285