265 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #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> <s> <q>\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);
 | |
| }
 |