#include "coxeter.h" #include "linalg.h" #include "mat.h" #include "enumerate_triangle_group.h" #define SWAP(t,x,y) do { t _tmp = (x); (x) = (y); (y) = _tmp; } while (0); //#define DEBUG(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__) #define DEBUG(msg, ...) struct result { int id; int count; mpq_t tr; mpq_t trinv; double x; double y; }; static int compare_result(const void *a_, const void *b_) { int d = 0; struct result **a = (struct result **)a_; struct result **b = (struct result **)b_; d = mpq_cmp((*a)->tr,(*b)->tr); if(d == 0) { d = mpq_cmp((*a)->trinv, (*b)->trinv); } return d; } static int compare_result_with_id(const void *a_, const void *b_) { int d = 0; struct result **a = (struct result **)a_; struct result **b = (struct result **)b_; d = mpq_cmp((*a)->tr,(*b)->tr); if(d == 0) { d = mpq_cmp((*a)->trinv, (*b)->trinv); if(d == 0) { d = (*b)->id - (*a)->id; } } return d; } static int compare_result_by_slope(const void *a_, const void *b_) { int d = 0; struct result **a = (struct result **)a_; struct result **b = (struct result **)b_; double slopea = (*a)->x / (*a)->y; double slopeb = (*b)->x / (*b)->y; return slopea > slopeb ? -1 : slopea < slopeb ? 1 : 0; } int main(int argc, char *argv[]) { mpq_t s, q, t, tmp; double sapprox, tapprox, qapprox, tqfactor; mat *matrices; group_t *group; int index; mps_context *solver; int acc = 100; int n, nuniq, nmax; int retval; double evs[3]; double max_slope; char buf[100]; char buf2[100]; struct result *invariants; struct result **distinct_invariants; if(argc < 4) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } nmax = atoi(argv[1]); DEBUG("Allocate\n"); mpq_inits(s, q, t, tmp, NULL); matrices = malloc(nmax*sizeof(mat)); for(int i = 0; i < nmax; i++) mat_init(matrices[i], 3); invariants = malloc(nmax*sizeof(struct result)); distinct_invariants = malloc(nmax*sizeof(struct result)); for(int i = 0; i < nmax; i++) { mpq_init(invariants[i].tr); mpq_init(invariants[i].trinv); distinct_invariants[i] = &invariants[i]; } solver = mps_context_new(); mps_context_set_output_prec(solver, 20); // relative precision mps_context_set_output_goal(solver, MPS_OUTPUT_GOAL_APPROXIMATE); DEBUG("Approximate parameters\n"); // get approximate s and q values sapprox = atof(argv[2]); qapprox = atof(argv[3]); // tapprox = atof(argv[3]); // tqfactor = pow((sapprox*sapprox-sapprox+1)*(sapprox*sapprox-sapprox+1)*(sapprox*sapprox+1), 1/6.0); // qapprox = tapprox/tqfactor; for(int i = 0; ; i++) { continued_fraction_approximation(tmp, sapprox, i); if(fabs(mpq_get_d(t)-sapprox) < 1e-10 || (mpz_cmpabs_ui(mpq_numref(tmp),acc) > 0 && mpz_cmpabs_ui(mpq_denref(tmp),acc) > 0)) break; mpq_set(s, tmp); } mpq_canonicalize(s); for(int i = 0; ; i++) { continued_fraction_approximation(tmp, qapprox, i); if(fabs(mpq_get_d(t)-qapprox) < 1e-10 || (mpz_cmpabs_ui(mpq_numref(tmp),acc) > 0 && mpz_cmpabs_ui(mpq_denref(tmp),acc) > 0)) break; mpq_set(q, tmp); } mpq_canonicalize(q); tqfactor = pow((mpq_get_d(s)*mpq_get_d(s)-mpq_get_d(s)+1)*(mpq_get_d(s)*mpq_get_d(s)-mpq_get_d(s)+1)*(mpq_get_d(s)*mpq_get_d(s)+1), 1/6.0); // group // order of the triangle reflection generators: a, b, c // order of the rotation orders: bc, ac, ab DEBUG("Generate group\n"); group = coxeter_init_triangle(4, 3, 3, nmax); DEBUG("Compute matrices\n"); enumerate(group, matrices, 4, 3, 3, s, q); n = 0; DEBUG("Compute traces\n"); for(int i = 0; i < nmax; i++) { if(group->elements[i].length % 2 != 0 || !group->elements[i].inverse) continue; invariants[i].id = i; mat_trace(invariants[i].tr, matrices[i]); mat_trace(invariants[i].trinv, matrices[group->elements[i].inverse->id]); distinct_invariants[n++] = &invariants[i]; } DEBUG("Get unique traces\n"); qsort(distinct_invariants, n, sizeof(struct result*), compare_result); nuniq = 0; for(int i = 0; i < n; i++) { if(i == 0 || compare_result(&distinct_invariants[i], &distinct_invariants[nuniq-1]) != 0) { distinct_invariants[nuniq] = distinct_invariants[i]; distinct_invariants[nuniq]->count = 1; nuniq++; } else { distinct_invariants[nuniq-1]->count++; int oldlength = group->elements[distinct_invariants[nuniq-1]->id].length; int newlength = group->elements[distinct_invariants[i]->id].length; if(newlength < oldlength) distinct_invariants[nuniq-1]->id = distinct_invariants[i]->id; } // gmp_printf("%d %d %s\n", i, nuniq-1, print_word(&group->elements[i], buf)); } max_slope = 0; int max_slope_index; DEBUG("Solve characteristic polynomials\n"); for(int i = 0; i < nuniq; i++) { retval = solve_characteristic_polynomial(solver, distinct_invariants[i]->tr, distinct_invariants[i]->trinv, evs); if(retval == 1) { fprintf(stderr, "Error! Could not solve polynomial.\n"); continue; } else if(retval == 2) { continue; } if(fabs(evs[0]) < fabs(evs[1])) SWAP(double, evs[0], evs[1]); if(fabs(evs[1]) < fabs(evs[2])) SWAP(double, evs[1], evs[2]); if(fabs(evs[0]) < fabs(evs[1])) SWAP(double, evs[0], evs[1]); double x = log(fabs(evs[0])); double y = -log(fabs(evs[2])); distinct_invariants[i]->x = x; distinct_invariants[i]->y = y; if(y/x > max_slope && (x > 0.1 || y > 0.1)) { max_slope_index = distinct_invariants[i] - invariants; max_slope = y/x; } } qsort(distinct_invariants, nuniq, sizeof(struct result*), compare_result_by_slope); gmp_fprintf(stdout, "\"s = %Qd = %.3f, q = %Qd, t = %.3f\"\n", s, mpq_get_d(s), q, mpq_get_d(q)*tqfactor); // printf("- 0 0 - - - - 0.5\n"); int cumulative = 0; double slope; for(int i = 0; i < nuniq; i++) { slope = distinct_invariants[i]->y/distinct_invariants[i]->x; mpq_set_si(tmp, 1, 1); if(mpq_cmp(distinct_invariants[i]->tr, tmp) == 0 && mpq_cmp(distinct_invariants[i]->trinv, tmp) == 0) { continue; } mpq_set_si(tmp, 0, 1); if(mpq_cmp(distinct_invariants[i]->tr, tmp) == 0 && mpq_cmp(distinct_invariants[i]->trinv, tmp) == 0) { continue; } mpq_set_si(tmp, -1, 1); if(mpq_cmp(distinct_invariants[i]->tr, tmp) == 0 && mpq_cmp(distinct_invariants[i]->trinv, tmp) == 0) { continue; } mpq_set_si(tmp, 3, 1); if(mpq_cmp(distinct_invariants[i]->tr, tmp) == 0 && mpq_cmp(distinct_invariants[i]->trinv, tmp) == 0) { continue; } cumulative += distinct_invariants[i]->count; gmp_printf("%d %d %d %Qd %Qd %f %f %f %f %f %s\n", distinct_invariants[i]->id, distinct_invariants[i]->count, cumulative, distinct_invariants[i]->tr, distinct_invariants[i]->trinv, log(fabs(mpq_get_d(distinct_invariants[i]->tr))), log(fabs(mpq_get_d(distinct_invariants[i]->trinv))), distinct_invariants[i]->x, distinct_invariants[i]->y, slope, print_word(&group->elements[distinct_invariants[i]->id], buf) ); } // printf("- 0 %d - - - - 2.0\n", cumulative); DEBUG("Clean up\n"); for(int i = 0; i < nmax; i++) { mpq_clear(invariants[i].tr); mpq_clear(invariants[i].trinv); } free(invariants); free(distinct_invariants); for(int i = 0; i < nmax; i++) mat_clear(matrices[i]); free(matrices); coxeter_clear(group); mpq_clears(s, q, t, tmp, NULL); mps_context_free(solver); }