nissy-fmc

A Rubik's cube FMC assistant
git clone https://git.tronto.net/nissy-fmc
Download | Log | Files | Refs | README | LICENSE

build.c (7951B)


      1 #include <inttypes.h>
      2 #include <stdbool.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "../src/cube.h"
      8 #include "../src/coord.h"
      9 #include "../src/solve.h"
     10 #include "../src/steps.h"
     11 #include "../src/nissy.h"
     12 
     13 static void gen_coord_comp(Coordinate *);
     14 static void gen_coord_sym(Coordinate *);
     15 static void gen_ptable(Coordinate *);
     16 static void gen_ptable_bfs(Coordinate *, int);
     17 static void gen_ptable_fixnasty(Coordinate *, coord_value_t, int);
     18 static void gen_ptable_compress(Coordinate *);
     19 static void gen_ptable_setbase(Coordinate *);
     20 
     21 static char buf[TABLESFILESIZE];
     22 
     23 static void
     24 gen_coord_comp(Coordinate *coord)
     25 {
     26 	coord_value_t ui;
     27 	Cube c, mvd;
     28 	Move m;
     29 	Trans t;
     30 
     31 	fprintf(stderr, "%s: generating COMP coordinate\n", coord->name);
     32 
     33 	coord->max = indexers_getmax(coord->i);
     34 
     35 	fprintf(stderr, "%s: size is %" PRIu32 "\n", coord->name, coord->max);
     36 
     37 	fprintf(stderr, "%s: generating mtable\n", coord->name);
     38 	alloc_mtable(coord);
     39 	for (ui = 0; ui < coord->max; ui++) {
     40 		if (ui % 100000 == 0)
     41 			fprintf(stderr, "\t(%" PRIu32 " done)\n", ui);
     42 		indexers_makecube(coord->i, ui, &c);
     43 		for (m = 0; m < NMOVES_HTM; m++) {
     44 			copy_cube(&c, &mvd);
     45 			apply_move(m, &mvd);
     46 			coord->mtable[m][ui] = indexers_getind(coord->i, &mvd);
     47 		}
     48 	}
     49 	fprintf(stderr, "\t(%" PRIu32 " done)\n", coord->max);
     50 
     51 	fprintf(stderr, "%s: generating ttable\n", coord->name);
     52 	alloc_ttable(coord);
     53 	for (ui = 0; ui < coord->max; ui++) {
     54 		if (ui % 100000 == 0)
     55 			fprintf(stderr, "\t(%" PRIu32 " done)\n", ui);
     56 		indexers_makecube(coord->i, ui, &c);
     57 		for (t = 0; t < NTRANS; t++) {
     58 			copy_cube(&c, &mvd);
     59 			apply_trans(t, &mvd);
     60 			coord->ttable[t][ui] = indexers_getind(coord->i, &mvd);
     61 		}
     62 	}
     63 	fprintf(stderr, "\t(%" PRIu32 " done)\n", coord->max);
     64 }
     65 
     66 static void
     67 gen_coord_sym(Coordinate *coord)
     68 {
     69 	coord_value_t i, in, ui, uj, uu, nr;
     70 	int j;
     71 	Move m;
     72 	Trans t;
     73 
     74 	fprintf(stderr, "%s: generating SYM coordinate\n", coord->name);
     75 
     76 	alloc_sd(coord, true);
     77 
     78 	fprintf(stderr, "%s: generating symdata\n", coord->name);
     79 	for (i = 0; i < coord->base[0]->max; i++)
     80 		coord->symclass[i] = coord->base[0]->max + 1;
     81 	for (i = 0, nr = 0; i < coord->base[0]->max; i++) {
     82 		if (coord->symclass[i] != coord->base[0]->max + 1)
     83 			continue;
     84 
     85 		coord->symrep[nr] = i;
     86 		coord->transtorep[i] = uf;
     87 		coord->selfsim[nr] = (coord_value_t)0;
     88 		for (j = 0; j < coord->tgrp->n; j++) {
     89 			t = coord->tgrp->t[j];
     90 			in = trans_coord(coord->base[0], t, i);
     91 			coord->symclass[in] = nr;
     92 			if (in == i)
     93 				coord->selfsim[nr] |= ((coord_value_t)1<<t);
     94 			else
     95 				coord->transtorep[in] = inverse_trans(t);
     96 		}
     97 		nr++;
     98 	}
     99 
    100 	coord->max = nr;
    101 
    102 	fprintf(stderr, "%s: number of classes is %" PRIu32 "\n",
    103 	    coord->name, coord->max);
    104 
    105 	/* Reallocating for maximum number of classes found */
    106 	/* TODO: remove, not needed anymore because not writing to file */
    107 	/*
    108 	coord->symrep = realloc(coord->symrep, coord->max*sizeof(coord_value_t));
    109 	coord->selfsim = realloc(coord->selfsim, coord->max*sizeof(coord_value_t));
    110 	*/
    111 
    112 	fprintf(stderr, "%s: generating mtable and ttrep_move\n", coord->name);
    113 	alloc_mtable(coord);
    114 	alloc_ttrep_move(coord);
    115 	for (ui = 0; ui < coord->max; ui++) {
    116 		if (ui % 100000 == 0)
    117 			fprintf(stderr, "\t(%" PRIu32 " done)\n", ui);
    118 		uu = coord->symrep[ui];
    119 		for (m = 0; m < NMOVES_HTM; m++) {
    120 			uj = move_coord(coord->base[0], m, uu, NULL);
    121 			coord->mtable[m][ui] = coord->symclass[uj];
    122 			coord->ttrep_move[m][ui] = coord->transtorep[uj];
    123 		}
    124 	}
    125 	fprintf(stderr, "\t(%" PRIu32 " done)\n", coord->max);
    126 }
    127 
    128 void
    129 gen_coord(Coordinate *coord)
    130 {
    131 	int i;
    132 
    133 	if (coord == NULL || coord->generated)
    134 		return;
    135 
    136 	fprintf(stderr, "%s: gen_coord started\n", coord->name);
    137 	for (i = 0; i < 2; i++) {
    138 		if (coord->base[i] != NULL) {
    139 			fprintf(stderr, "%s: generating base[%d] = %s\n",
    140 			    coord->name, i, coord->base[i]->name);
    141 			gen_coord(coord->base[i]);
    142 		}
    143 	}
    144 
    145 	switch (coord->type) {
    146 	case COMP_COORD:
    147 		if (coord->i[0] == NULL)
    148 			goto error_gc;
    149 		gen_coord_comp(coord);
    150 		break;
    151 	case SYM_COORD:
    152 		if (coord->base[0] == NULL || coord->tgrp == NULL)
    153 			goto error_gc;
    154 		gen_coord_sym(coord);
    155 		break;
    156 	case SYMCOMP_COORD:
    157 		if (coord->base[0] == NULL || coord->base[1] == NULL)
    158 			goto error_gc;
    159 		coord->max = coord->base[0]->max * coord->base[1]->max;
    160 		break;
    161 	default:
    162 		break;
    163 	}
    164 
    165 	coord->generated = true;
    166 	gen_ptable(coord);
    167 
    168 	fprintf(stderr, "%s: gen_coord completed\n", coord->name);
    169 
    170 	return;
    171 
    172 error_gc:
    173 	fprintf(stderr, "Error generating coordinates.\n");
    174 	exit(1);
    175 }
    176 
    177 static void
    178 gen_ptable(Coordinate *coord)
    179 {
    180 	bool compact;
    181 	int d, i;
    182 	coord_value_t oldn, sz;
    183 
    184 	alloc_ptable(coord, true);
    185 
    186 	/* For the first steps we proceed the same way for compact and not */
    187 	compact = coord->compact;
    188 	coord->compact = false;
    189 
    190 	fprintf(stderr, "%s: generating ptable\n", coord->name); 
    191 
    192 	sz = ptablesize(coord) * sizeof(entry_group_t);
    193 	memset(coord->ptable, ~(uint8_t)0, sz);
    194 	for (i = 0; i < 16; i++)
    195 		coord->count[i] = 0;
    196 
    197 	coord->updated = 0;
    198 	oldn = 0;
    199 	ptableupdate(coord, 0, 0);
    200 	gen_ptable_fixnasty(coord, 0, 0);
    201 	fprintf(stderr, "\tDepth %d done, generated %"
    202 		PRIu32 "\t(%" PRIu32 "/%" PRIu32 ")\n",
    203 		0, coord->updated - oldn, coord->updated, coord->max);
    204 	oldn = coord->updated;
    205 	coord->count[0] = coord->updated;
    206 	for (d = 0; d < 15 && coord->updated < coord->max; d++) {
    207 		gen_ptable_bfs(coord, d);
    208 		fprintf(stderr, "\tDepth %d done, generated %"
    209 			PRIu32 "\t(%" PRIu32 "/%" PRIu32 ")\n",
    210 			d+1, coord->updated-oldn, coord->updated, coord->max);
    211 		coord->count[d+1] = coord->updated - oldn;
    212 		oldn = coord->updated;
    213 	}
    214 	
    215 	gen_ptable_setbase(coord);
    216 
    217 	if (compact) {
    218 		fprintf(stderr, "%s: compressing ptable\n", coord->name);
    219 		gen_ptable_compress(coord);
    220 	}
    221 
    222 	fprintf(stderr, "%s: ptable generated\n", coord->name);
    223 }
    224 
    225 static void
    226 gen_ptable_bfs(Coordinate *coord, int d)
    227 {
    228 	coord_value_t i, ii;
    229 	int pval;
    230 	Move m;
    231 
    232 	for (i = 0; i < coord->max; i++) {
    233 		pval = ptableval(coord, i);
    234 		if (pval != d)
    235 			continue;
    236 		for (m = U; m <= B3; m++) {
    237 			if (!coord->moveset(m))
    238 				continue;
    239 			ii = move_coord(coord, m, i, NULL);
    240 			ptableupdate(coord, ii, d+1);
    241 			gen_ptable_fixnasty(coord, ii, d+1);
    242 		}
    243 	}
    244 }
    245 
    246 static void
    247 gen_ptable_fixnasty(Coordinate *coord, coord_value_t i, int d)
    248 {
    249 	coord_value_t ii, ss, M;
    250 	int j;
    251 	Trans t;
    252 
    253 	if (coord->type != SYMCOMP_COORD)
    254 		return;
    255 
    256 	M = coord->base[1]->max;
    257 	ss = coord->base[0]->selfsim[i/M];
    258 	for (j = 0; j < coord->base[0]->tgrp->n; j++) {
    259 		t = coord->base[0]->tgrp->t[j];
    260 		if (t == uf || !(ss & ((coord_value_t)1<<t)))
    261 			continue;
    262 		ii = trans_coord(coord, t, i);
    263 		ptableupdate(coord, ii, d);
    264 	}
    265 }
    266 
    267 static void
    268 gen_ptable_compress(Coordinate *coord)
    269 {
    270 	int val;
    271 	coord_value_t i, j;
    272 	entry_group_t mask, v;
    273 
    274 	fprintf(stderr, "Compressing table to 2 bits per entry\n");
    275 
    276 	for (i = 0; i < coord->max; i += ENTRIES_PER_GROUP_COMPACT) {
    277 		mask = (entry_group_t)0;
    278 		for (j = 0; j < ENTRIES_PER_GROUP_COMPACT; j++) {
    279 			if (i+j >= coord->max)
    280 				break;
    281 			val = ptableval(coord, i+j) - coord->ptablebase;
    282 			v = (entry_group_t)MIN(3, MAX(0, val));
    283 			mask |= v << (2*j);
    284 		}
    285 		coord->ptable[i/ENTRIES_PER_GROUP_COMPACT] = mask;
    286 	}
    287 
    288 	coord->compact = true;
    289 
    290 	/* TODO: remove, not necessary anymore */
    291 	/*
    292 	coord->ptable = realloc(coord->ptable,
    293 	    sizeof(entry_group_t)*ptablesize(coord));
    294 	*/
    295 }
    296 
    297 static void
    298 gen_ptable_setbase(Coordinate *coord)
    299 {
    300 	int i;
    301 	coord_value_t sum, newsum;
    302 
    303 	coord->ptablebase = 0;
    304 	sum = coord->count[0] + coord->count[1] + coord->count[2];
    305 	for (i = 3; i < 16; i++) {
    306 		newsum = sum + coord->count[i] - coord->count[i-3];
    307 		if (newsum > sum)
    308 			coord->ptablebase = i-3;
    309 		sum = newsum;
    310 	}
    311 }
    312 
    313 int
    314 main(void)
    315 {
    316 	int i;
    317 	size_t b;
    318 	FILE *file;
    319 
    320 	init_cube();
    321 
    322 	b = 0;
    323 	for (i = 0; coordinates[i] != NULL; i++) {
    324 		gen_coord(coordinates[i]);
    325 		b += write_coord(coordinates[i], &buf[b]);
    326 	}
    327 
    328 	if ((file = fopen("tables", "wb")) == NULL)
    329 		return 1;
    330 
    331 	if (fwrite(buf, 1, b, file) != b)
    332 		return 1;
    333 
    334 	fprintf(stderr, "Written %zu bytes\n", b);
    335 
    336 	return 0;
    337 }