14namespace layer1_foundations {
42 const char *label,
int aEqnAnz,
int aVarAnz)
48 nb_calls_to_solve = 0;
52 unitcoeffs.resize(_eqnanz);
53 active.resize(_eqnanz);
54 problem_label = label;
58 m =
MAXIMUM(_eqnanz, _varanz) + 1;
67 vector<equation> &eqn, vector<int> &lorhs, vector<int> &hirhs,
68 vector<int> &neqn,
int numeqn,
int numvar,
int verbose_level)
70 int f_v = (verbose_level >= 1);
71 int f_v4 = (verbose_level >= 4);
76 cout <<
"possolve" << endl;
78 nb_calls_to_solve = 0;
79 first_moved = INT_MAX;
80 second_moved = INT_MAX;
83 if (numeqn > _eqnanz || numvar > _varanz) {
84 cerr<<
"*** >E intsolve: limits exceeded\n";
94 for (i = 0; i < numeqn; ++i) {
97 if (lorhs[i] > 0 || hirhs[i] < 0) hopeless =
true;
102 for (j = neqn[i]; --j >= 0;)
if (eqn[i][j].coeff != 1)
break;
103 unitcoeffs[i] = (j < 0);
108 puteqns(lo,hi,numvar,lorhs,hirhs,eqn,neqn,numeqn);
116 cout <<
"mckay::tMCKAY::possolve: calling solve" << endl;
118 solve(0,lo,hi,active,numvar,lorhs,hirhs,eqn,neqn,numeqn, verbose_level);
120 cout <<
"mckay::tMCKAY::possolve done" << endl;
132 int eqn1,
equation &e1,
int l1,
int lors1,
int hirs1,
133 int eqn2,
equation &e2,
int *pl2,
int *plors2,
int *phirs2,
136 int f_v = (verbose_level >= 1);
139 int l2,factor,minfactor;
144 if (l1 > l2 || hirs1 > lors1)
return false;
148 for (i = 0; i < l1; ++i) {
150 for (; j < l2 && e2[j].var != e1i.
var; ++j) {}
151 if (j == l2 || e2[j].coeff < e1i.
coeff)
return false;
153 if (factor < minfactor) minfactor = factor;
158 for (i = j = 0; i < l1; ++i, ++j)
161 for (; j < l2 && e2[j].var != e1i.
var; ++j) e2[k++] = e2[j];
162 if (j < l2 && e2[j].coeff > minfactor*e1i.
coeff) {
163 e2[k].
var = e2[j].var;
164 e2[k].coeff = e2[j].coeff - minfactor*e1i.
coeff;
168 for (; j < l2; ++j) e2[k++] = e2[j];
171 *plors2 -= minfactor*lors1;
172 *phirs2 -= minfactor*hirs1;
176 cout <<
"subtract: subtracted equation " << eqn1
177 <<
" from equation " << eqn2 << endl;
187 vector<int> &lorhs, vector<int> &hirhs,
188 vector<equation> &eqn, vector<int> &neqn,
189 int numeqn,
int verbose_level)
191 int f_v = (verbose_level >= 1);
194 done.resize(_eqnanz);
199 for (i = 0; i < numeqn; ++i) {
205 for (i = 0; i < numeqn; ++i) {
206 if (!done[i] && neqn[i] > 0) {
207 for (j = 0; j < numeqn; ++j) {
209 subtract(i, eqn[i],neqn[i],
210 lorhs[i],hirhs[i],j, eqn[j],
211 &neqn[j],&lorhs[j],&hirhs[j],
214 cout <<
"mckay::tMCKAY::pruneqn after subtract:" << endl;
216 numvar, lorhs, hirhs, eqn, neqn, numeqn);
236 vector<int> &lorhs, vector<int> &hirhs,
237 vector<equation> &eqn, vector<int> &neqn,
238 int numeqn,
int verbose_level)
240 int f_v = (verbose_level >= 1);
243 for (j = 0; j < numeqn; ++j) {
248 for (i = 0; i < len;) {
249 if (lo[eqn[j][i].var] == hi[eqn[j][i].var]) {
250 sum += eqn[j][i].coeff*lo[eqn[j][i].var];
252 cout <<
"varprune: equation " << j <<
" variable "
253 << eqn[j][i].var <<
" is not free any more, "
254 "sum += " << eqn[j][i].coeff * lo[eqn[j][i].var]
257 eqn[j][i] = eqn[j][--len];
266 cout <<
"varprune: equation " << j <<
" reducing RHS by "
267 << sum <<
" to lorhs[j]=" << lorhs[j] <<
" hirhs[j]="
276 int numvar, vector<int> &lorhs, vector<int> &hirhs,
277 vector<equation> &eqn, vector<int> &neqn,
int numeqn)
282 cout <<
"CON" << endl;
283 for (i = 0; i < numvar; ++i) {
284 if (i > 0) cout <<
"," << endl;
285 if (lo[i] > 0) cout <<
"x" << i <<
" >= " << lo[i] <<
", ";
286 cout <<
"x" << i <<
" <= " << hi[i];
290 for (i = 0; i < numeqn; ++i) {
292 cout <<
"Equation " << i <<
" : ";
293 for (j = 0; j < neqn[i]; ++j) {
294 if (j % 16 == 15) cout << endl <<
" ";
295 cout << (j == 0 ?
"" :
"+") << eqn[i][j].coeff
296 <<
"*x" << eqn[i][j].var;
298 cout << (lorhs[i] < hirhs[i] ?
" >= " :
" = ") << lorhs[i];
300 if (lorhs[i] == hirhs[i])
continue;
304 for (j = 0; j < neqn[i]; ++j) {
305 if (j % 16 == 15) cout << endl <<
" ";
306 cout << (j == 0 ?
"" :
"+") << eqn[i][j].coeff
307 <<
"*x" << eqn[i][j].var;
309 cout <<
" <= " << hirhs[i];
320 vector<int> &hirhs, vector<equation> &eqn,
321 vector<int> &neqn,
int numeqn)
325 for (j = 0; j < numeqn; ++j)
328 if (len == 0)
continue;
332 for (i = 1; i < len && g > 1; ++i) g = gcd(g,eqn[j][i].coeff);
336 if (g == 1)
continue;
337 for (i = 0; i < len; ++i) eqn[j][i].coeff /= g;
339 lorhs[j] = lorhs[j] < 0 ? 0 : (lorhs[j] + g - 1) / g;
340 hirhs[j] = hirhs[j] < 0 ? -1 : hirhs[j] / g;
343 cerr<<
"eqn "<<j<<
": g="<<g<<
" lorhs="<<lorhs[j]
344 <<
" hirhs="<<hirhs[j]<<
"\n";
346 if (lorhs[j] > hirhs[j])
return j;
367 while ((c = a % b) > 0) {
379 vector<int> &alo, vector<int> &ahi,
380 vector<bool> &aactive,
int numvar,
381 vector<int> &lorhs, vector<int> &hirhs,
382 vector<equation> &eqn, vector<int> &neqn,
383 int numeqn,
int verbose_level)
385 int f_v = (verbose_level >= 1);
387 int f_vvv = (verbose_level >= 3);
394 active.resize(_eqnanz);
396 int f_restriction_made;
402 log_12l(nb_calls_to_solve, level);
404 cout <<
"mckay::tMCKAY::solve " << problem_label
406 <<
" first_moved " << first_moved
407 <<
" second_moved " << second_moved
408 <<
" level " << level << endl;
413 for (i = 0; i < level; ++i) {
414 cout <<
"x_" << split[i] <<
"=" << branch[i];
427 cout <<
"level=" << level << endl;
428 cout <<
"i : split[i] : range[i] : branch[i]" << endl;
429 for (i = 0; i < level; ++i) {
430 cout << i <<
" : " << split[i] <<
" : " << range[i]
431 <<
" : " << branch[i] <<
" : " << endl;
433 cout <<
"low and high:" << endl;
434 for (j = 0; j < numvar; j++) {
435 cout << j <<
" : " << alo[j] <<
" : " << ahi[j] << endl;
442 log_12l(current_node, level);
443 cout <<
" current system:" << endl;
444 puteqns(alo,ahi,numvar,lorhs,hirhs,eqn,neqn,numeqn);
458 cout <<
" SOLVE level "<<level<< endl;
459 cout<<
"Number of active equations: ";
460 for (i = numeqn; --i >= 0;)
if (aactive[i]) ++nacc;
461 cout<<
":"<<nacc<<endl;
462 for (i = 0; i < numeqn; i++) {
467 cout <<
"low and high:" << endl;
468 for (j = 0; j < numvar; j++) {
469 cout << j <<
" : " << alo[j] <<
" : " << ahi[j] << endl;
477 puteqns(alo,ahi,numvar,lorhs,hirhs,eqn,neqn,numeqn);
478 cout <<
"level=" << level << endl;
479 cout <<
"range[] : branch[] :" << endl;
480 for (i = 0; i < level; ++i)
481 cout << range[i] <<
" : " << branch[i] <<
" : " << endl;
491 for (i = 0; i < numvar; ++i) {
495 for (i = 0; i < numeqn; ++i) {
496 active[i] = aactive[i];
500 if (!restrict_variables(level, lo, hi, active, numvar,
503 numeqn, f_restriction_made, verbose_level - 1)) {
507 log_12l(nb_calls_to_solve, level);
509 cout <<
"solve restrict_variables returns FALSE, "
510 "backtracking" << endl;
519 if (f_vvv && f_restriction_made) {
520 log_12l(nb_calls_to_solve, level);
522 cout <<
" after restriction: low and high:" << endl;
523 for (i = 0; i < numvar; i++) {
524 cout << i <<
" : " << lo[i] <<
" : " << hi[i] << endl;
537 log_12l(nb_calls_to_solve, level);
539 cout <<
"searching part" << endl;
545 for (i = 0; i < numvar; ++i) {
546 if (hi[i] != lo[i] && hi[i] - lo[i] < mindiff) {
548 mindiff = hi[i] - lo[i];
559 log_12l(nb_calls_to_solve, level);
560 cout <<
" solution " << D->_resultanz << endl;
562 D->_results.push_back(lo);
564 if (D->_resultanz < D->_maxresults) {
573 varprune(lo,hi,lorhs,hirhs,eqn,neqn,numeqn, verbose_level);
580 pruneqn(lo,hi,numvar,lorhs,hirhs,eqn,neqn,numeqn, verbose_level);
586 log_12l(nb_calls_to_solve, level);
588 cout <<
" after varprune and pruneqn:" << endl;
589 puteqns(lo,hi,numvar,lorhs,hirhs,eqn,neqn,numeqn);
608 log_12l(nb_calls_to_solve, level);
609 cout <<
"solve choosing variable " << isplit
610 <<
" lo=" << lo[isplit] <<
" hi=" << hi[isplit] << endl;
613 for (i = 0; i <= mindiff; ++i) {
614 int first_moved_orig = first_moved;
615 int second_moved_orig = second_moved;
616 int f_first_moved_has_changed =
FALSE;
617 int f_second_moved_has_changed =
FALSE;
622 if (level < first_moved) {
624 second_moved = INT_MAX;
626 else if (level < second_moved) {
627 second_moved = level;
629 if (first_moved != first_moved_orig) {
630 f_first_moved_has_changed =
TRUE;
632 if (second_moved != second_moved_orig) {
633 f_second_moved_has_changed =
TRUE;
636 if (f_first_moved_has_changed || f_second_moved_has_changed ||
637 (nb_calls_to_solve % 10000000) == 0) {
638 log_12l(nb_calls_to_solve, level);
639 cout <<
" x_" << isplit <<
" = " << lo[isplit] << endl;
641 hi[isplit] = lo[isplit];
643 split[level] = isplit;
644 branch[level] = lo[isplit];
645 range[level] = mindiff+1;
651 cout <<
"solve level " << level <<
" isplit=" << isplit <<
" before solve i=" << i <<
" / " << mindiff << endl;
652 for (j = 0; j < numeqn; j++) {
657 cout <<
"low and high:" << endl;
658 for (j = 0; j <= level; j++) {
659 cout << j <<
" : " << alo[j] <<
" : " << ahi[j] << endl;
667 puteqns(alo,ahi,numvar,lorhs,hirhs,eqn,neqn,numeqn);
668 cout <<
"level=" << level << endl;
669 cout <<
"range[] : branch[] :" << endl;
670 for (j = 0; j <= level; j++) {
671 cout << range[j] <<
" : " << branch[j] <<
" : " << endl;
679 solve(level + 1, lo, hi, active, numvar,
680 lorhs, hirhs, eqn, neqn, numeqn,
684 cout <<
"solve level " << level <<
" isplit=" << isplit <<
" after solve" << endl;
692 log_12l(nb_calls_to_solve, level);
694 cout <<
" done" << endl;
700 vector<int> &lo, vector<int> &hi,
701 vector<bool> &active,
int numvar,
702 vector<int> &lorhs, vector<int> &hirhs,
703 vector<equation> &eqn, vector<int> &neqn,
704 int numeqn,
int &f_restriction_made,
int verbose_level)
706 int f_v = (verbose_level >= 1);
707 int f_vv = (verbose_level >= 2);
711 long int current_node;
712 int losum,hisum,eic,eiv,lx,hx;
713 int nfree,ok, xlo,xhi;
715 int f_restriction_made_in_this_eqn;
718 cout <<
"mckay::tMCKAY::restrict_variables" << endl;
721 cout <<
"low and high:" << endl;
722 for (j = 0; j <= level; j++) {
723 cout << j <<
" : " << lo[j] <<
" : " << hi[j] << endl;
725 puteqns(lo, hi, numvar, lorhs, hirhs, eqn, neqn, numeqn);
726 cout <<
"level=" << level << endl;
727 cout <<
"range[] : branch[] :" << endl;
728 for (j = 0; j <= level; j++) {
729 cout << range[j] <<
" : " << branch[j] <<
" : " << endl;
732 current_node = nb_calls_to_solve;
748 f_restriction_made =
FALSE;
749 for (j = 0; ok < numeqn; j = (j == numeqn-1 ? 0 : j+1)) {
753 cout <<
"mckay::tMCKAY::restrict_variables checking equation " << j << endl;
758 f_restriction_made_in_this_eqn =
FALSE;
771 cout <<
"checking equation " << j
772 <<
" with unitcoeffs" << endl;
776 for (i = neqn[j]; --i >= 0;) {
777 losum += lo[eqn[j][i].var];
779 hisum += hi[eqn[j][i].var];
782 if (losum > hirhs[j]) {
784 cout <<
"solve " << problem_label <<
" node "
785 << current_node <<
" level " << level
786 <<
"return b/c for equation " << j
787 <<
" with unitcoeffs "
788 "we have losum = " << losum <<
" > "
789 << hirhs[j] <<
" = hirhs[j]" << endl;
793 if (hisum < lorhs[j]) {
795 cout <<
"solve " << problem_label <<
" node "
796 << current_node <<
" level " << level
797 <<
"return b/c for equation " << j
798 <<
" with unitcoeffs "
799 " we have hisum = " << hisum <<
" < "
800 << lorhs[j] <<
" = lorhs[j]" << endl;
811 for (i = neqn[j]; --i >= 0;) {
817 xlo = lorhs[j] + hx - hisum;
824 xhi = hirhs[j] + lx - losum;
834 if (lo[eiv] != save) {
835 f_restriction_made =
TRUE;
836 f_restriction_made_in_this_eqn =
TRUE;
838 cout <<
"increasing lo[" << eiv
839 <<
"] from " << save <<
" to "
851 if (lo[eiv] != save) {
852 f_restriction_made =
TRUE;
853 f_restriction_made_in_this_eqn =
TRUE;
855 cout <<
"reducing hi[" << eiv
856 <<
"] from " << save <<
" to "
862 if (lo[eiv] != hi[eiv]) {
878 cout <<
"mckay::tMCKAY::restrict_variables checking equation " << j
879 <<
" without unitcoeffs" << endl;
883 for (i = neqn[j]; --i >= 0;) {
884 losum += eqn[j][i].coeff * lo[eqn[j][i].var];
885 hisum += eqn[j][i].coeff * hi[eqn[j][i].var];
887 if (losum > hirhs[j]) {
889 cout <<
"mckay::tMCKAY::restrict_variables "
890 << problem_label <<
" node "
891 << current_node <<
" level " << level
892 <<
"return b/c for equation " << j
893 <<
" without unitcoeffs "
894 "we have losum = " << losum <<
" > "
895 << hirhs[j] <<
" = hirhs[j]" << endl;
899 if (hisum < lorhs[j]) {
901 cout <<
"mckay::tMCKAY::restrict_variables "
902 << problem_label <<
" node "
903 << current_node <<
" level " << level
904 <<
"return b/c for equation " << j
905 <<
" without unitcoeffs "
906 "we have hisum = " << hisum <<
" < "
907 << lorhs[j] <<
" = lorhs[j]" << endl;
912 if (f_vv && f_restriction_made_in_this_eqn) {
913 cout <<
"mckay::tMCKAY::restrict_variables "
914 "equation " << j <<
", after restriction: "
915 "low and high:" << endl;
916 for (i = 0; i < numvar; i++) {
917 cout << i <<
" : " << lo[i] <<
" : "
920 cout <<
"hisum=" << hisum << endl;
921 cout <<
"losum=" << losum << endl;
927 f_restriction_made_in_this_eqn =
FALSE;
930 for (i = neqn[j]; --i >= 0;) {
932 cout <<
"restricting lower and upper "
933 "bounds equation " << j << endl;
935 if (hi[eqn[j][i].var] != lo[eqn[j][i].var]) {
936 eic = eqn[j][i].coeff;
940 xlo = lorhs[j] + hx - hisum;
946 xhi = hirhs[j] + lx - losum;
954 lo[eiv] = (xlo + eic - 1) / eic;
955 if (lo[eiv] != save) {
956 f_restriction_made =
TRUE;
957 f_restriction_made_in_this_eqn =
TRUE;
959 cout <<
"increasing lo[" << eiv
961 << save <<
" to " << lo[eiv] <<
" : "
962 <<
"eqn j=" << j <<
" variable "
963 << eiv <<
" coeff=" << eic
964 <<
" lorhs[j]=" << lorhs[j]
965 <<
" hisum=" << hisum
967 <<
" hisum - hx=" << hisum - hx
971 if (lo[eiv] > hi[eiv]) {
973 cout <<
"return bc for eqn " << j
974 <<
" term " << i <<
" xlo > lx "
975 "and lo[eiv] > hi[eiv]" << endl;
984 if (hi[eiv] < save) {
985 f_restriction_made =
TRUE;
986 f_restriction_made_in_this_eqn =
TRUE;
988 cout <<
"reducing hi[" << eiv <<
"] from "
989 << save <<
" to " << hi[eiv] <<
" : "
990 <<
"eqn j=" << j <<
" variable "
991 << eiv <<
" coeff=" << eic
992 <<
" hirhs[j]=" << hirhs[j]
993 <<
" losum=" << losum
995 <<
" losum - lx=" << losum - lx
999 if (lo[eiv] > hi[eiv]) {
1001 cout <<
"return bc for eqn " << j
1002 <<
" term " << i <<
" xhi < hx "
1003 "and lo[eiv] > hi[eiv]" << endl;
1004 cout <<
"xlo=" << xlo << endl;
1005 cout <<
"xhi=" << xhi << endl;
1006 cout <<
"lx=" << lx << endl;
1007 cout <<
"hx=" << hx << endl;
1008 cout <<
"eic=" << eic << endl;
1009 cout <<
"eiv=" << eiv << endl;
1010 cout <<
"lo[eiv]=" << lo[eiv] << endl;
1011 cout <<
"hi[eiv]=" << hi[eiv] << endl;
1017 if (lo[eiv] != hi[eiv]) {
1023 if (f_vv && f_restriction_made_in_this_eqn) {
1024 cout <<
"mckay::tMCKAY::restrict_variables "
1025 "equation " << j <<
", after restriction: "
1026 "low and high:" << endl;
1027 for (i = 0; i < numvar; i++) {
1028 cout << i <<
" : " << lo[i] <<
" : "
1031 cout <<
"hisum=" << hisum << endl;
1032 cout <<
"losum=" << losum << endl;
1047 if (ok > 0 && nfree == 0) {
1058 cout <<
"solve " << problem_label
1059 <<
" node " << current_node
1062 if (first_moved < INT_MAX) {
1063 cout << first_moved;
1069 cout <<
" second_moved ";
1070 if (second_moved < INT_MAX) {
1071 cout << second_moved;
1077 cout <<
" level " << level;
1078 cout <<
" nb_sol=" << D->_resultanz;
interface to system functions
int os_ticks_per_second()
diophantine systems of equations (i.e., linear systems over the integers)
void possolve(std::vector< int > &lo, std::vector< int > &hi, std::vector< equation > &eqn, std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< int > &neqn, int numeqn, int numvar, int verbose_level)
void Init(diophant *lgs, const char *label, int aEqnAnz, int aVarAnz)
void varprune(std::vector< int > &lo, std::vector< int > &hi, std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< equation > &eqn, std::vector< int > &neqn, int numeqn, int verbose_level)
void pruneqn(std::vector< int > &lo, std::vector< int > &hi, int numvar, std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< equation > &eqn, std::vector< int > &neqn, int numeqn, int verbose_level)
void puteqns(std::vector< int > &lo, std::vector< int > &hi, int numvar, std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< equation > &eqn, std::vector< int > &neqn, int numeqn)
int restrict_variables(int level, std::vector< int > &lo, std::vector< int > &hi, std::vector< bool > &active, int numvar, std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< equation > &eqn, std::vector< int > &neqn, int numeqn, int &f_restriction_made, int verbose_level)
int divideeqns(std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< equation > &eqn, std::vector< int > &neqn, int numeqn)
bool subtract(int eqn1, equation &e1, int l1, int lors1, int hirs1, int eqn2, equation &e2, int *pl2, int *plors2, int *phirs2, int verbose_level)
long int nb_calls_to_solve
void log_12l(long int current_node, int level)
void solve(int level, std::vector< int > &alo, std::vector< int > &ahi, std::vector< bool > &aactive, int numvar, std::vector< int > &lorhs, std::vector< int > &hirhs, std::vector< equation > &eqn, std::vector< int > &neqn, int numeqn, int verbose_level)
const char * problem_label
std::vector< term > equation
the orbiter library for the classification of combinatorial objects
#define INTERVAL_IN_SECONDS
a term in a diophantine system of type tMCKAY