nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

gendata.h (6603B)


      1 STATIC size_t gendata_coord(const coord_t [static 1], unsigned char *);
      2 STATIC long long gendata_coord_dispatch(const char *, unsigned long long,
      3     unsigned char *);
      4 STATIC tableinfo_t genptable_coord(
      5     const coord_t [static 1], const unsigned char *, unsigned char *);
      6 STATIC bool switch_to_fromnew(uint64_t, uint64_t, uint64_t);
      7 STATIC uint64_t genptable_coord_fillneighbors(const coord_t [static 1],
      8     const unsigned char *, uint64_t, uint8_t, unsigned char *);
      9 STATIC uint64_t genptable_coord_fillfromnew(const coord_t [static 1],
     10     const unsigned char *, uint64_t, uint8_t, unsigned char *);
     11 STATIC uint8_t get_coord_pval(
     12     const coord_t [static 1], const unsigned char *, uint64_t);
     13 STATIC void set_coord_pval(
     14     const coord_t [static 1], unsigned char *, uint64_t, uint8_t);
     15 
     16 STATIC long long
     17 gendata_coord_dispatch(
     18 	const char *coordstr,
     19 	unsigned long long bufsize,
     20 	unsigned char *buf
     21 )
     22 {
     23 	coord_t *coord;
     24 
     25 	parse_coord_and_axis(coordstr, &coord, NULL);
     26 
     27 	if (coord == NULL) {
     28 		LOG("Error: could not parse coordinate '%s'\n", coordstr);
     29 		return NISSY_ERROR_INVALID_SOLVER;
     30 	}
     31 
     32 	return (int64_t)gendata_coord(coord, buf);
     33 }
     34 
     35 STATIC size_t
     36 gendata_coord(const coord_t coord[static 1], unsigned char *buf)
     37 {
     38 	uint64_t coord_dsize, tablesize, ninfo;
     39 	unsigned char *pruningbuf, *coord_data;
     40 	unsigned char *table;
     41 	tableinfo_t coord_data_info, pruning_info;
     42 
     43 	coord_data = buf == NULL ? NULL : buf + INFOSIZE;
     44 	coord_dsize = coord->gendata(coord_data);
     45 	if (coord_dsize == SIZE_MAX)
     46 		goto gendata_coord_error;
     47 
     48 	ninfo = coord_dsize == 0 ? 1 : 2;
     49 	tablesize = DIV_ROUND_UP(coord->max, 2);
     50 
     51 	if (buf == NULL)
     52 		goto gendata_coord_return_size;
     53 
     54 	if (ninfo == 2) {
     55 		coord_data_info = (tableinfo_t) {
     56 			.solver = "coord helper table for ",
     57 			.type = TABLETYPE_SPECIAL,
     58 			.infosize = INFOSIZE,
     59 			.fullsize = INFOSIZE + coord_dsize,
     60 			.hash = 0, /* TODO */
     61 			.next = INFOSIZE + coord_dsize,
     62 
     63 			/* Unknown / non-applicable values */
     64 			.entries = 0,
     65 			.classes = 0,
     66 			.bits = 0,
     67 			.base = 0,
     68 			.maxvalue = 0,
     69 		};
     70 
     71 		append_coord_name(coord, coord_data_info.solver);
     72 
     73 		writetableinfo(&coord_data_info, INFOSIZE + coord_dsize, buf);
     74 
     75 		pruningbuf = buf + INFOSIZE + coord_dsize;
     76 	} else {
     77 		pruningbuf = buf;
     78 	}
     79 
     80 	table = pruningbuf + INFOSIZE;
     81 	pruning_info = genptable_coord(coord, coord_data, table);
     82 	writetableinfo(&pruning_info, INFOSIZE + tablesize, pruningbuf);
     83 
     84 gendata_coord_return_size:
     85 	return ninfo * INFOSIZE + coord_dsize + tablesize;
     86 
     87 gendata_coord_error:
     88 	LOG("Unexpected error generating coordinate data\n");
     89 	return 0;
     90 }
     91 
     92 STATIC tableinfo_t
     93 genptable_coord(
     94 	const coord_t coord[static 1],
     95 	const unsigned char *data,
     96 	unsigned char *table
     97 )
     98 {
     99 	uint64_t tablesize, i, d, tot, t, nm;
    100 	tableinfo_t info;
    101 
    102 	tablesize = DIV_ROUND_UP(coord->max, 2);
    103 
    104 	memset(table, 0xFF, tablesize);
    105 
    106 	info = (tableinfo_t) {
    107 		.solver = "coordinate solver for ",
    108 		.type = TABLETYPE_PRUNING,
    109 		.infosize = INFOSIZE,
    110 		.fullsize = INFOSIZE + tablesize,
    111 		.hash = 0, /* TODO */
    112 		.entries = coord->max,
    113 		.classes = 0,
    114 		.bits = 4,
    115 		.base = 0,
    116 		.maxvalue = 0,
    117 		.next = 0
    118 	};
    119 
    120 	memset(info.distribution, 0, INFO_DISTRIBUTION_LEN * sizeof(uint64_t));
    121 	append_coord_name(coord, info.solver);
    122 
    123 	nm = popcount_u32(coord->moves_mask);
    124 	i = coord->coord(SOLVED_CUBE, data);
    125 	set_coord_pval(coord, table, i, 0);
    126 	info.distribution[0] = 1;
    127 	for (d = 1, tot = 1; tot < coord->max && d < 20; d++) {
    128 		t = 0;
    129 		if (switch_to_fromnew(tot, coord->max, nm)) {
    130 			for (i = 0; i < coord->max; i++)
    131 				if (get_coord_pval(coord, table, i) > d)
    132 					t += genptable_coord_fillfromnew(
    133 					    coord, data, i, d, table);
    134 		} else {
    135 			for (i = 0; i < coord->max; i++)
    136 				if (get_coord_pval(coord, table, i) == d-1)
    137 					t += genptable_coord_fillneighbors(
    138 					    coord, data, i, d, table);
    139 		}
    140 		tot += t;
    141 		info.distribution[d] = t;
    142 		LOG("[%s gendata] Depth %" PRIu64 ": found %" PRIu64 " (%"
    143 		    PRIu64 " of %" PRIu64 ")\n",
    144 		    coord->name, d, t, tot, coord->max);
    145 	}
    146 	info.maxvalue = d-1;
    147 
    148 	return info;
    149 }
    150 
    151 STATIC bool
    152 switch_to_fromnew(uint64_t done, uint64_t max, uint64_t nm)
    153 {
    154 	/*
    155 	Heuristic to determine if it is more conveniente to loop over
    156       	done coordinates and fill the new discovered, or to loop from new
    157 	coordinates and fill them if they have a done neighbor.
    158 	*/
    159 
    160 	double r = (double)done / (double)max;
    161 	return 1.0 - intpow(1.0-r, nm) > nm * (1.0-r);
    162 }
    163 
    164 STATIC uint64_t
    165 genptable_coord_fillneighbors(
    166 	const coord_t coord[static 1],
    167 	const unsigned char *data,
    168 	uint64_t i, 
    169 	uint8_t d,
    170 	unsigned char *table
    171 )
    172 {
    173 	bool isnasty;
    174 	uint8_t m;
    175 	uint64_t ii, j, t, tot;
    176 	cube_t c, moved;
    177 
    178 	c = coord->cube(i, data);
    179 	tot = 0;
    180 	for (m = 0; m < NMOVES; m++) {
    181 		if (!((UINT32_C(1) << (uint32_t)m) & coord->moves_mask))
    182 			continue;
    183 		moved = move(c, m);
    184 		ii = coord->coord(moved, data);
    185 		isnasty = coord->isnasty(ii, data);
    186 		for (t = 0; t < NTRANS && (t == 0 || isnasty); t++) {
    187 			if (!((UINT64_C(1) << t) & coord->trans_mask))
    188 				continue;
    189 
    190 			j = coord->coord(transform(moved, t), data);
    191 			if (get_coord_pval(coord, table, j) > d) {
    192 				set_coord_pval(coord, table, j, d);
    193 				tot++;
    194 			}
    195 		}
    196 	}
    197 
    198 	return tot;
    199 }
    200 
    201 STATIC uint64_t
    202 genptable_coord_fillfromnew(
    203 	const coord_t coord[static 1],
    204 	const unsigned char *data,
    205 	uint64_t i,
    206 	uint8_t d,
    207 	unsigned char *table
    208 )
    209 {
    210 	bool found;
    211 	uint8_t m;
    212 	uint64_t tot, t, ii, j, nsim, sim[NTRANS];
    213 	cube_t c;
    214 
    215 	tot = 0;
    216 	c = coord->cube(i, data);
    217 
    218 	for (t = 0, nsim = 0; t < NTRANS; t++) {
    219 		if (!((UINT64_C(1) << t) & coord->trans_mask))
    220 			continue;
    221 
    222 		ii = coord->coord(transform(c, t), data);
    223 		for (j = 0, found = false; j < nsim && !found; j++)
    224 			found = sim[j] == ii;
    225 		if (!found)
    226 			sim[nsim++] = ii;
    227 	}
    228 
    229 	for (j = 0, found = false; j < nsim && !found; j++) {
    230 		c = coord->cube(sim[j], data);
    231 		for (m = 0; m < NMOVES; m++) {
    232 			if (!((UINT32_C(1) << (uint32_t)m) & coord->moves_mask))
    233 				continue;
    234 			ii = coord->coord(move(c, m), data);
    235 			if (get_coord_pval(coord, table, ii) < d) {
    236 				found = true;
    237 				break;
    238 			}
    239 		}
    240 	}
    241 
    242 	tot = 0;
    243 	if (found) {
    244 		for (j = 0; j < nsim; j++) {
    245 			if (get_coord_pval(coord, table, sim[j]) > d) {
    246 				set_coord_pval(coord, table, sim[j], d);
    247 				tot++;
    248 			}
    249 		}
    250 	}
    251 
    252 	return tot;
    253 }
    254 
    255 STATIC uint8_t
    256 get_coord_pval(
    257 	const coord_t coord[static 1],
    258 	const unsigned char *table,
    259 	uint64_t i
    260 )
    261 {
    262 	return (table[COORD_INDEX(i)] & COORD_MASK(i)) >> COORD_SHIFT(i);
    263 }
    264 
    265 STATIC void
    266 set_coord_pval(
    267 	const coord_t coord[static 1],
    268 	unsigned char *table,
    269 	uint64_t i,
    270 	uint8_t val
    271 )
    272 {
    273 	table[COORD_INDEX(i)] = (table[COORD_INDEX(i)] & (~COORD_MASK(i)))
    274 	    | (val << COORD_SHIFT(i));
    275 }