Dist m4ri 0.0.1.alpha
Computing distance of a classical or quantum CSS code
Loading...
Searching...
No Matches
util_io.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <ctype.h>
3#include <errno.h>
4#include <string.h>
5#include "util_io.h"
6
8 .debug=3,
9 .method=0,
10 .classical=-1,
11 .steps=1000,
12 .css=1,
13 .smax=5,
14 .wmax=0,
15 .dmin=0,
16 .dmax=0,
17 .wmin=1,
18 .noscan=0,
19 .fdem=NULL,
20 .pmin=0.0,
21 .start=-1,
22 .cbeg=-1,
23 .cend=-1,
24 .seed=0,
25 .dist=0,
26 .dist_max=0,
27 .dist_min=0,
28 .max_row_wgt_H =0,
29 .max_col_wgt_H =0,
30 .n0=0,
31 .nvar=0,
32 .nchk=0,
33 .maxC=0,
34 .dW=0,
35 .finC=NULL,
36 .outC=NULL,
37 .codewords=NULL,
38 .num_cws=0,
39 .min_w=INT_MAX,
40 .finH=NULL,
41 .finG=NULL,
42 .finL=NULL,
43 .fin="",
44 .spaH=NULL,
45 .spaG=NULL,
46 .spaL=NULL,
47 .threads=0,
48 .dexp=0,
49 .timeout=60.0
50};
51
52params_t * const p = &prm;
53
54void var_init(int argc, char **argv, params_t * const p){
55 int dbg=0;
56 int swit=0;
57 double prob=0.0;
58 long long int dbg_ll=0;
59
60 if(argc <= 1)
61 ERROR("no command-line arguments given, " BRIEF_HELP,argv[0]);
62
63 for (int i=1; i<argc;i++) /* scan arguments for help message */
64 if((strcmp(argv[i],"--help")==0)||(strcmp(argv[i],"-h")==0)){
65 printf( USAGE,argv[0],argv[0]);
66 exit (-1);
67 }
68
69 int debug_set=0;
70
71 for(int i=1; i<argc; i++){
72 if(sscanf(argv[i],"debug=%d",& dbg)==1){
73 if(debug_set && p->debug != dbg){
74 ERROR("debug parameter specified multiple times with conflicting values (%d vs %d)\n", p->debug, dbg);
75 }
76 p->debug = dbg;
77 debug_set = 1;
78 if(p->debug&4)
79 fprintf(stderr, "# read %s, debug=%d octal=%o\n",argv[i],p->debug,p->debug);
80 }
81 else if (sscanf(argv[i],"css=%d",&dbg)==1){
82 p->css=dbg;
83 if (p->debug&4)
84 fprintf(stderr, "# read %s, css=%d\n",argv[i],p->css);
85 }
86 else if (0==strncmp(argv[i],"finH=",5)){
87 if(strlen(argv[i])>5)
88 p->finH = argv[i]+5;
89 else
90 p->finH = argv[++i];
91 if (p->debug&4)
92 fprintf(stderr, "# read %s, finH=%s; setting finH=\"\"\n",argv[i],p->finH);
93 p->fin="";
94 }
95 else if (0==strncmp(argv[i],"finL=",5)){
96 if(strlen(argv[i])>5)
97 p->finL = argv[i]+5;
98 else
99 p->finL = argv[++i];
100 if (p->debug&4)
101 fprintf(stderr, "# read %s, finL=%s; setting finL=\"\"\n",argv[i],p->finL);
102 p->fin="";
103 }
104 else if (0==strncmp(argv[i],"finG=",5)){
105 if(strlen(argv[i])>5)
106 p->finG = argv[i]+5;
107 else
108 p->finG = argv[++i];
109 if (p->debug&4)
110 fprintf(stderr, "# read %s, finG=%s; setting finG=\"\"\n",argv[i],p->finG);
111 p->fin="";
112 }
113 else if (0==strncmp(argv[i],"fin=",4)){
114 if(p->finH)
115 ERROR("arg[%d]='%s' in conflict with finH=%s\n",i,argv[i],p->finH);
116 if(p->finG)
117 ERROR("arg[%d]='%s' in conflict with finG=%s\n",i,argv[i],p->finG);
118 if(p->finL)
119 ERROR("arg[%d]='%s' in conflict with finL=%s\n",i,argv[i],p->finL);
120 if (strlen(argv[i])>4)
121 p->fin = argv[i]+4;
122 else{
123 if (i+1 < argc)
124 p->fin = argv[i+1];
125 else
126 ERROR("argv[%d]='%s', empty string for 'fin'\n",i,argv[i]);
127 }
128 }
129 else if (sscanf(argv[i],"method=%d",&dbg)==1){
130 p->method=dbg;
131 if (p->debug&4)
132 fprintf(stderr, "# read %s, method=%d\n",argv[i],p->method);
133 if( (p->method<=0) || (p->method>3))
134 ERROR("Unsupported method %d",p->method);
135 }
136 else if (sscanf(argv[i],"smax=%d",&dbg)==1){
137 p->smax=dbg;
138 if (p->debug&4)
139 fprintf(stderr, "# read %s, smax=%d\n",argv[i],p->smax);
140 }
141 else if (sscanf(argv[i],"wmax=%d",&dbg)==1){
142 p->wmax=dbg;
143 if (p->debug&4)
144 fprintf(stderr, "# read %s, wmax=%d\n",argv[i],p->wmax);
145 }
146 else if (sscanf(argv[i],"dmin=%d",&dbg)==1){
147 p->dmin=dbg;
148 if (p->debug&4)
149 fprintf(stderr, "# read %s, dmin=%d\n",argv[i],p->dmin);
150 }
151 else if (sscanf(argv[i],"dmax=%d",&dbg)==1){
152 p->dmax=dbg;
153 if (p->debug&4)
154 fprintf(stderr, "# read %s, dmax=%d\n",argv[i],p->dmax);
155 }
156 else if (sscanf(argv[i],"start=%d",&dbg)==1){
157 p->start=dbg;
158 if (p->debug&4)
159 fprintf(stderr, "# read %s, start=%d\n",argv[i],p->start);
160 }
161 else if (sscanf(argv[i],"cbeg=%d",&dbg)==1){
162 p->cbeg=dbg;
163 if (p->debug&4)
164 fprintf(stderr, "# read %s, cbeg=%d\n",argv[i],p->cbeg);
165 }
166 else if (sscanf(argv[i],"cend=%d",&dbg)==1){
167 p->cend=dbg;
168 if (p->debug&4)
169 fprintf(stderr, "# read %s, cend=%d\n",argv[i],p->cend);
170 }
171 else if (sscanf(argv[i],"wmin=%d",&dbg)==1){
172 p->wmin=dbg;
173 if (p->debug&4)
174 fprintf(stderr, "# read %s, wmin=%d\n",argv[i],p->wmin);
175 }
176 else if (sscanf(argv[i],"steps=%d",&dbg)==1){
177 p->steps=dbg;
178 if (p->debug&4)
179 fprintf(stderr, "# read %s, steps=%d\n",argv[i],p->steps);
180 }
181 else if (sscanf(argv[i],"seed=%d",&dbg)==1){
182 p->seed=dbg;
183 if (p->debug&4)
184 fprintf(stderr, "# read %s, seed=%d\n",argv[i],p->seed);
185 }
186 else if (sscanf(argv[i],"noscan=%d",&dbg)==1){
187 p->noscan=dbg;
188 if (p->debug&4)
189 fprintf(stderr, "# read %s, noscan=%d\n",argv[i],p->noscan);
190 }
191 else if (0==strncmp(argv[i],"fdem=",5)){
192 if(strlen(argv[i])>5)
193 p->fdem = argv[i]+5;
194 else
195 p->fdem = argv[++i];
196 if (p->debug&4)
197 fprintf(stderr, "# read %s, fdem=%s\n",argv[i],p->fdem);
198 }
199 else if (sscanf(argv[i],"pmin=%lg",&prob)==1){
200 p->pmin=prob;
201 if (p->debug&4)
202 fprintf(stderr, "# read %s, pmin=%g\n",argv[i],p->pmin);
203 }
204 else if (0==strncmp(argv[i],"finC=",5)){
205 if(strlen(argv[i])>5)
206 p->finC = argv[i]+5;
207 else
208 p->finC = argv[++i];
209 if (p->debug&4)
210 fprintf(stderr, "# read %s, finC=%s\n",argv[i],p->finC);
211 }
212 else if (0==strncmp(argv[i],"outC=",5)){
213 if(strlen(argv[i])>5)
214 p->outC = argv[i]+5;
215 else
216 p->outC = argv[++i];
217 if (p->debug&4)
218 fprintf(stderr, "# read %s, outC=%s\n",argv[i],p->outC);
219 }
220 else if (sscanf(argv[i],"maxC=%lld",&dbg_ll)==1){
221 p->maxC=dbg_ll;
222 if (p->debug&4)
223 fprintf(stderr, "# read %s, maxC=%lld\n",argv[i],p->maxC);
224 }
225 else if (sscanf(argv[i],"dW=%d",&dbg)==1){
226 p->dW=dbg;
227 if (p->debug&4)
228 fprintf(stderr, "# read %s, dW=%d\n",argv[i],p->dW);
229 }
230 else if (sscanf(argv[i],"classical=%d",&dbg)==1){
231 p->classical=dbg;
232 if (p->debug&4)
233 fprintf(stderr, "# read %s, classical=%d\n",argv[i],p->classical);
234 }
235 else if (sscanf(argv[i],"threads=%d",&dbg)==1){
236 p->threads=dbg;
237 if (p->debug&4)
238 fprintf(stderr, "# read %s, threads=%d\n",argv[i],p->threads);
239 }
240 else if (sscanf(argv[i],"dexp=%d",&dbg)==1){
241 p->dexp=dbg;
242 if (p->debug&4)
243 fprintf(stderr, "# read %s, dexp=%d\n",argv[i],p->dexp);
244 }
245 else if (sscanf(argv[i],"dest=%d",&dbg)==1){
246 p->dexp=dbg;
247 if (p->debug&4)
248 fprintf(stderr, "# read %s, dest=%d (alias for dexp)\n",argv[i],p->dexp);
249 }
250 else if (sscanf(argv[i],"timeout=%lf",&prob)==1){
251 p->timeout=prob;
252 if (p->debug&4)
253 fprintf(stderr, "# read %s, timeout=%g\n",argv[i],p->timeout);
254 }
255 else{ /* unrecognized option */
256 fprintf(stderr, "# unrecognized parameter \"%s\" at position %d\n",argv[i],i);
257 ERROR("try \"%s -h\" for options",argv[0]);
258 }
259 } /* end parameter scan cycle */
260
261 if (p->noscan && p->method != 2) {
262 ERROR("noscan=1 only works with method=2");
263 }
264
265 if (!p->fdem && strlen(p->fin) == 0 && !p->finH && !p->finG && !p->finL) {
266 p->fin = "../examples/try";
267 }
268
269 if (p->fdem) {
270 if (p->finH || p->finG || p->finL || strlen(p->fin) > 0) {
271 ERROR("Cannot specify matrix files (fin, finH, finG, finL) along with fdem");
272 }
273 }
274 if (p->pmin != 0.0 && !p->fdem) {
275 ERROR("pmin can only be used when fdem is specified");
276 }
277
278 if (p->dmin < 0) {
279 ERROR("parameter dmin=%d cannot be negative\n", p->dmin);
280 }
281 if (p->dmax < 0) {
282 ERROR("parameter dmax=%d cannot be negative\n", p->dmax);
283 }
284 if (p->dmin > 0 && p->dmax > 0 && p->dmin > p->dmax) {
285 ERROR("parameter dmin=%d cannot be larger than dmax=%d\n", p->dmin, p->dmax);
286 }
287 if (p->wmax > 0 && p->dmin > p->wmax) {
288 ERROR("parameter dmin=%d cannot be larger than wmax=%d\n", p->dmin, p->wmax);
289 }
290
291 if (p->wmax > 0 && p->wmin > p->wmax) {
292 ERROR("parameter wmin=%d cannot be larger than wmax=%d\n", p->wmin, p->wmax);
293 }
294 if (p->start >= 0) {
295 if (p->cbeg >= 0 || p->cend >= 0) {
296 ERROR("Cannot specify start along with cbeg or cend\n");
297 }
298 p->cbeg = p->start;
299 p->cend = p->start;
300 }
301
302 if (p->method == 1) {
303 if (p->cbeg >= 0 || p->cend >= 0) {
304 ERROR("Parameters start, cbeg, and cend only work with CC method (method=2 or method=3)\n");
305 }
306 }
307
308 if (p->cbeg >= 0 && p->cend >= 0 && p->cbeg > p->cend) {
309 ERROR("cbeg=%d cannot be larger than cend=%d\n", p->cbeg, p->cend);
310 }
311 if (p->noscan && p->smax > 0) {
312 fprintf(stderr, "# WARNING: smax=%d disabled (set to 0) because noscan=1 skips small cluster weights\n", p->smax);
313 p->smax = 0;
314 } else if (p->dmin > 1 && p->smax > 0) {
315 fprintf(stderr, "# WARNING: smax=%d disabled (set to 0) because dmin=%d skips small cluster weights\n", p->smax, p->dmin);
316 p->smax = 0;
317 }
318
319 if (p->method == 2) {
320 if (p->steps != 1000) {
321 fprintf(stderr, "# WARNING: steps=%d is ignored for CC method\n", p->steps);
322 }
323 }
324
325 if(p->method &1 ){ /* RW */
326 if (p->steps<=0)
327 ERROR("parameter steps=%d should be positive for RW method=%d", p->steps,p->method);
328 }
329
330
331
332 if((strlen(p->fin)!=0) && (!p->finH)){
333 int len = strlen(p->fin);
334 char *s = (char *) malloc((len+6)*sizeof(char));
335 if(!s)
336 ERROR("memory allocation");
337 sprintf(s,"%s%s",p->fin,swit>0?"X.mtx":"Z.mtx");
338 p->finG=s;
339 s = (char *) malloc((len+6)*sizeof(char));
340 if(!s)
341 ERROR("memory allocation");
342 sprintf(s,"%s%s",p->fin,swit>0?"Z.mtx":"X.mtx");
343 p->finH=s;
344 if (p->debug & 2)
345 fprintf(stderr, "# read 'fin=%s'; " //"since switch=%d "
346 "assigning \n# finH=%s\n# finG=%s\n",
347 p->fin,// swit,
348 p->finH,p->finG);
349 }
350
351 if (p->fdem) {
352 read_dem_file(p->fdem, &(p->spaH), &(p->spaL), p->pmin, p->debug);
353 if (p->classical == -1) p->classical = 0;
354 p->nvar = p->spaH->cols;
355 p->n0 = p->nvar;
356 p->nchk = p->spaL->rows;
357 } else {
358 if (p->finH){
359 p->spaH=csr_mm_read(p->finH,p->spaH,0);
360 if(p->debug&1)
361 fprintf(stderr, "# read H <- file '%s'\n",p->finH);
362 if(p->debug&32){
363 if((p->spaH->cols<150)||(p->debug&2048))
364 csr_print(p->spaH,"H");
365 }
366 }
367 else
368 ERROR("need to specify H=Hx input file name; use fin=[str] or finH=[str]\n");
369
370 if((p->finG) && (p->finL))
371 ERROR("either G=Hz or L=Lx matrix should be specified but not both! finG='%s' finL='%s'\n",
372 p->finG, p->finL);
373
374 if(p->finG){
375 if (p->classical == -1) p->classical = 0;
376 p->spaG=csr_mm_read(p->finG,p->spaG,0);
377 if(p->debug&1)
378 fprintf(stderr, "# read G <- file '%s'\n",p->finG);
380 ERROR("rows of H and G matrices are not orthogonal");
381 if(p->debug&32){
382 if((p->spaG->cols<150)||(p->debug&2048))
383 csr_print(p->spaG,"G");
384 }
385 }
386 else if (p->finL){
387 if (p->classical == -1) p->classical = 0;
388 p->spaL=csr_mm_read(p->finL,p->spaL,0);
389 if(p->debug&1)
390 fprintf(stderr, "# read L <- file '%s'\n",p->finL);
391 if(p->debug&32){
392 if((p->spaL->cols<150)||(p->debug&2048))
393 csr_print(p->spaL,"L");
394 }
395 p->nchk = p->spaL->rows;
396 }
397 else{
398 if (p->classical == -1) p->classical = 1;
399 p->spaG=NULL;
400 }
401 }
402
403 if(p->method & 2){ /* CC */
404 if ((p->wmax<=0) && ((p->method & 1 )==0)) {
405 if (p->timeout <= 0.0) {
406 ERROR("either parameter wmax>0 or timeout>0 should be specified for CC method=%d", p->method);
407 }
408 p->wmax = MAX_W - 1;
409 }
410 if(p->wmax>=MAX_W)
411 ERROR("increase MAX_W=%d defined in 'util_io.h'",MAX_W);
412 for(int i=0; i<MAX_W; i++)
413 p->swei[i]=p->spaH->rows +1;
414 }
415
416 if (p->seed<=0){
417 p->seed = time(NULL) - 1000 * p->seed + 10*getpid();
418 if(p->debug&4)
419 fprintf(stderr, "# initializing rng from time(NULL), seed=%d\n",p->seed);
420 }
421 else if(p->debug&4)
422 fprintf(stderr, "# initializing rng from seed=%d\n",p->seed);
423
424 srand(p->seed);
425
426 rci_t n = (p->spaH)-> cols;
427 if ((!p->classical) && ((p->spaG) && (n != (p->spaG) -> cols)))
428 ERROR("Column count mismatch in H and G matrices: %d != %d",
429 (p->spaH)-> cols, (p->spaG)->cols);
430 p->nvar = n;
431 p->n0 = n;
432 if (p->css!=1)
433 ERROR("Non-CSS codes are currently not supported, css=%d",p->css);
434
435 if (p->cbeg >= p->nvar) {
436 ERROR("cbeg=%d cannot be larger than nvar-1=%d\n", p->cbeg, p->nvar-1);
437 }
438 if (p->cend >= p->nvar) {
439 ERROR("cend=%d cannot be larger than nvar-1=%d\n", p->cend, p->nvar-1);
440 }
441
442 if((p->spaG) && (p->spaL==NULL)){
446 p->nchk = p->spaL->rows;
447 }
448
449 if (p->classical) {
450 if (p->finL != NULL || p->finG != NULL) {
451 ERROR("Conflict: classical=1 specified, but finL or finG was also provided.");
452 }
453 if (p->spaL != NULL) {
454 if (p->debug & 1) {
455 fprintf(stderr, "# Warning: classical=1 specified, discarding L matrix (logical operators)\n");
456 }
457 p->spaL = csr_free(p->spaL);
458 }
459 } else {
460 if (p->spaL == NULL) {
461 ERROR("L matrix (logical operators) is required for quantum code (classical=0).\n"
462 "Provide finL, fdem, or finG to construct it. Alternatively, set classical=1 to find the distance of the stabilizer code as a classical code.");
463 }
464 }
465
466 if ((p->method <= 0) || (p->method > 3)){
467 printf("invalid method=%d specified\n", p->method);
468 ERROR(BRIEF_HELP,argv[0]);
469 }
470
471}
472
473void var_kill(params_t * const p){
474 if(p->spaL)
475 csr_free(p->spaL);
476 if(p->spaH)
477 csr_free(p->spaH);
478 if(p->spaG)
479 csr_free(p->spaG);
480 if (strlen(p->fin) != 0) {
481 if (p->finH) {
482 free(p->finH);
483 p->finH = NULL;
484 }
485 if (p->finG) {
486 free(p->finG);
487 p->finG = NULL;
488 }
489 }
490
491 cw_vec_t *cw, *tmp;
492 HASH_ITER(hh, p->codewords, cw, tmp) {
493 HASH_DEL(p->codewords, cw);
494 free(cw);
495 }
496}
497
498typedef struct {
499 char **lines;
500 int size;
503
504static dem_program_t *read_dem_to_program(const char *fnam) {
505 FILE *f = fopen(fnam, "r");
506 if (f == NULL) {
507 printf("FILE I/O ERROR: %s\n", strerror(errno));
508 ERROR("can't open the (DEM) file %s for reading\n", fnam);
509 }
510
511 dem_program_t *prog = malloc(sizeof(dem_program_t));
512 prog->size = 0;
513 prog->capacity = 100;
514 prog->lines = malloc(prog->capacity * sizeof(char *));
515
516 char *buf = NULL;
517 size_t bufsiz = 0;
518 ssize_t linelen;
519
520 while ((linelen = getline(&buf, &bufsiz, f)) >= 0) {
521 if (linelen > 0 && buf[linelen - 1] == '\n') {
522 buf[linelen - 1] = '\0';
523 }
524 if (prog->size >= prog->capacity) {
525 prog->capacity *= 2;
526 prog->lines = realloc(prog->lines, prog->capacity * sizeof(char *));
527 }
528 prog->lines[prog->size++] = strdup(buf);
529 }
530 if (buf) free(buf);
531 fclose(f);
532 return prog;
533}
534
535static void free_dem_program(dem_program_t *prog) {
536 for (int i = 0; i < prog->size; i++) {
537 free(prog->lines[i]);
538 }
539 free(prog->lines);
540 free(prog);
541}
542
543static void parse_instructions(dem_program_t *prog, int *p_line_idx,
544 int *p_iD, int_pair **p_inH, int *p_maxH, int *p_r,
545 int *p_iL, int_pair **p_inL, int *p_maxL, int *p_k,
546 int *p_n, double pmin, int *p_detector_shift, int debug) {
547 while (*p_line_idx < prog->size) {
548 char *line = prog->lines[*p_line_idx];
549 (*p_line_idx)++;
550
551 char *c = line;
552 while (isspace(*c)) c++;
553
554 if (*c == '\0' || *c == '#') continue;
555
556 if (*c == '}') {
557 return;
558 }
559
560 int num = 0;
561 int val = 0;
562 double prob = 0.0;
563
564 // Parse repeat
565 if (sscanf(c, "repeat %d { %n", &val, &num) == 1) {
566 int start_idx = *p_line_idx;
567 int temp_idx = start_idx;
568 for (int r = 0; r < val; r++) {
569 temp_idx = start_idx;
570 parse_instructions(prog, &temp_idx,
571 p_iD, p_inH, p_maxH, p_r,
572 p_iL, p_inL, p_maxL, p_k,
573 p_n, pmin, p_detector_shift, debug);
574 }
575 if (val > 0) {
576 *p_line_idx = temp_idx;
577 } else {
578 int depth = 1;
579 while (*p_line_idx < prog->size && depth > 0) {
580 char *s = prog->lines[*p_line_idx];
581 (*p_line_idx)++;
582 while (isspace(*s)) s++;
583 if (strncmp(s, "repeat", 6) == 0 && strchr(s, '{')) depth++;
584 if (*s == '}') depth--;
585 }
586 }
587 continue;
588 }
589
590 // Parse shift_detectors
591 int shift_val = 0;
592 if (sscanf(c, "shift_detectors ( %*[^)] ) %d %n", &shift_val, &num) == 1) {
593 *p_detector_shift += shift_val;
594 continue;
595 } else if (sscanf(c, "shift_detectors %d %n", &shift_val, &num) == 1) {
596 *p_detector_shift += shift_val;
597 continue;
598 }
599
600 // Parse error
601 if (sscanf(c, "error( %lg ) %n", &prob, &num) == 1) {
602 if ((prob <= 0) || (prob >= 1))
603 ERROR("probability should be in (0,1) exclusive p=%g\n"
604 "line %d: '%s'\n", prob, *p_line_idx, line);
605 c += num;
606
607 if (prob < pmin) {
608 continue;
609 }
610
611 while (1) {
612 while (isspace(c[0])) c++;
613 if (c[0] == '\0' || c[0] == '#' || c[0] == '\n') break;
614
615 num = 0;
616 if (sscanf(c, "D%d%n", &val, &num) == 1) {
617 c += num;
618 assert(val >= 0);
619 int shifted_val = val + *p_detector_shift;
620 if (shifted_val >= *p_r)
621 *p_r = shifted_val + 1;
622 if (*p_iD >= *p_maxH) {
623 *p_maxH = 2 * (*p_maxH);
624 *p_inH = realloc(*p_inH, (*p_maxH) * sizeof(**p_inH));
625 }
626 (*p_inH)[*p_iD].a = shifted_val;
627 (*p_inH)[*p_iD].b = *p_n;
628 (*p_iD)++;
629 } else if (sscanf(c, "L%d%n", &val, &num) == 1) {
630 c += num;
631 assert(val >= 0);
632 if (val >= *p_k)
633 *p_k = val + 1;
634 if (*p_iL >= *p_maxL) {
635 *p_maxL = 2 * (*p_maxL);
636 *p_inL = realloc(*p_inL, (*p_maxL) * sizeof(**p_inL));
637 }
638 (*p_inL)[*p_iL].a = val;
639 (*p_inL)[*p_iL].b = *p_n;
640 (*p_iL)++;
641 } else if (c[0] == '^') {
642 c++;
643 } else {
644 ERROR("unrecognized entry %s in error line %d: '%s'\n", c, *p_line_idx, line);
645 }
646 }
647 (*p_n)++;
648 continue;
649 }
650
651 if (strncmp(c, "detector", 8) == 0) {
652 continue;
653 }
654
655 if (strncmp(c, "logical_observable", 18) == 0) {
656 continue;
657 }
658
659 ERROR("unrecognized DEM entry in line %d: '%s'\n", *p_line_idx, line);
660 }
661}
662
663void read_dem_file(char *fnam, csr_t **p_spaH, csr_t **p_spaL, double pmin, int debug){
664 dem_program_t *prog = read_dem_to_program(fnam);
665
666 int maxH=100, maxL=100;
667 int_pair * inH = malloc(maxH*sizeof(int_pair));
668 int_pair * inL = malloc(maxL*sizeof(int_pair));
669 if ((!inH)||(!inL))
670 ERROR("memory allocation failed\n");
671
672 int r=-1, k=-1, n=0;
673 int iD=0, iL=0;
674 int detector_shift = 0;
675 int line_idx = 0;
676
677 parse_instructions(prog, &line_idx,
678 &iD, &inH, &maxH, &r,
679 &iL, &inL, &maxL, &k,
680 &n, pmin, &detector_shift, debug);
681
682 if (line_idx < prog->size) {
683 ERROR("Unmatched '}' in DEM file %s at line %d\n", fnam, line_idx);
684 }
685
686 if(debug & 1)
687 fprintf(stderr, "# read DEM %s: rows_H=%d rows_L=%d cols=%d; nz_H=%d nz_L=%d\n",fnam,r,k,n,iD,iL);
688 if((r<=0)||(k<=0)||(n<=0))
689 ERROR("invalid DEM file %s: rows_H=%d rows_L=%d cols=%d; nz_H=%d nz_L=%d\n",
690 fnam,r,k,n,iD,iL);
691
692 *p_spaH = csr_from_pairs(*p_spaH, iD, inH, r, n);
693 *p_spaL = csr_from_pairs(*p_spaL, iL, inL, k, n);
694
695 free(inH);
696 free(inL);
697 free_dem_program(prog);
698}
699
700FILE * nzlist_w_new(const char fnam[], const char comment[]){
701 FILE *f=fopen(fnam,"w");
702 if(!f){
703 fprintf(stderr, "FILE I/O ERROR: %s\n", strerror(errno));
704 ERROR("can't open file %s for writing",fnam);
705 }
706 fprintf(f,"%%%% NZLIST\n");
707 if(comment)
708 fprintf(f,"%% %s\n",comment);
709 return f;
710}
711
712int nzlist_w_append(FILE *f, const cw_vec_t * const vec){
713 assert(vec && vec->weight >0 );
714 assert(f!=NULL);
715 const int w=vec->weight;
716 if(fprintf(f,"%d ",w)<=0)
717 ERROR("can't write to `NZLIST` file");
718 for(int i=0; i < w; i++)
719 if(fprintf(f," %d%s", 1 + vec->arr[i], i+1 < w ? "" :"\n")<=0)
720 ERROR("can't write to `NZLIST` file");
721 return 0;
722}
723
724FILE * nzlist_r_open(const char fnam[], long long int *lineno){
725 FILE *f=fopen(fnam,"r");
726 if(!f)
727 return(NULL);
728 *lineno=1;
729 int c=fgetc(f);
730 while(c=='%'){
731 do{
732 c=fgetc(f);
733 if(feof(f))
734 return NULL;
735 }
736 while(c!='\n');
737 (*lineno)++;
738 c=fgetc(f);
739 }
740 ungetc(c,f);
741 return f;
742}
743
744cw_vec_t * nzlist_r_one(FILE *f, cw_vec_t * vec, const char fnam[], long long int *lineno){
745 assert(f!=NULL);
746 if ( ferror (f)|| feof(f) )
747 return NULL;
748 int w;
749
750 int c=fgetc(f);
751 while(c=='%'){
752 do{
753 c=fgetc(f);
754 if(feof(f))
755 return NULL;
756 }
757 while(c!='\n');
758 (*lineno)++;
759 c=fgetc(f);
760 }
761 ungetc(c,f);
762
763 if(fscanf(f," %d",&w) != 1){
764 if (feof(f)) return NULL;
765 fprintf(stderr, "%s:%lld: invalid NZLIST entry\n", fnam, *lineno);
766 ERROR("expected an integer");
767 }
768 if ((vec!=NULL) && (vec->weight<w)){
769 free(vec);
770 vec=NULL;
771 }
772 if(vec==NULL){
773 vec = calloc(sizeof(cw_vec_t)+w*sizeof(int), sizeof(char));
774 if(!vec)
775 ERROR("memory allocation");
776 }
777 vec->weight = w;
778 vec->cnt = 1;
779 for(int i=0; i<w; i++){
780 if(fscanf(f," %d ",vec->arr + i) != 1){
781 fprintf(stderr, "%s:%lld: invalid entry of weight w=%d\n",fnam, *lineno, w);
782 ERROR("expected an integer i=%d of %d",i,w);
783 }
784 vec->arr[i]--;
785 }
786
787 for(int i=1; i<w; i++){
788 if((vec->arr[i-1] < 0) || (vec->arr[i-1] >= vec->arr[i])){
789 fprintf(stderr, "%s:%lld: invalid entry of weight w=%d\n",fnam, *lineno, w);
790 ERROR("expected strictly increasing positive entries");
791 }
792 }
793 (*lineno)++;
794 return vec;
795}
796
797cw_vec_t * codeword_add_maybe(params_t * const p, const int arr[], int weight) {
798 if (p->maxC && p->num_cws >= p->maxC) {
799 return p->codewords;
800 }
801 // Check if weight is within the current limit: min_w + dW (or min_w if dW < 0)
802 int max_allowed_w = (p->min_w == INT_MAX) ? INT_MAX : ((p->dW >= 0) ? (p->min_w + p->dW) : p->min_w);
803 if (weight > max_allowed_w) {
804 return p->codewords;
805 }
806
807 const size_t keylen = weight * sizeof(int);
808 cw_vec_t *pvec = NULL;
809 HASH_FIND(hh, p->codewords, arr, keylen, pvec);
810 if (!pvec) {
811 cw_vec_t *entry = malloc(sizeof(cw_vec_t) + keylen);
812 if (!entry) ERROR("memory allocation");
813 entry->weight = weight;
814 entry->cnt = 1;
815 for (int i = 0; i < weight; i++) {
816 entry->arr[i] = arr[i];
817 }
818 HASH_ADD(hh, p->codewords, arr, keylen, entry);
819 p->num_cws++;
820
821 // Update min_w and prune heavier codewords
822 if (weight < p->min_w) {
823 p->min_w = weight;
824 int prune_w = (p->dW >= 0) ? (p->min_w + p->dW) : p->min_w;
825 cw_vec_t *cw, *tmp;
826 HASH_ITER(hh, p->codewords, cw, tmp) {
827 if (cw->weight > prune_w) {
828 HASH_DEL(p->codewords, cw);
829 free(cw);
830 p->num_cws--;
831 }
832 }
833 }
834 } else {
835 pvec->cnt++;
836 }
837 return p->codewords;
838}
839
840long long int nzlist_read(const char fnam[], params_t *p){
841 long long int count = 0, lineno;
842 long long int skipped_invalid = 0;
843 assert(fnam);
844 FILE * f=nzlist_r_open(fnam, &lineno);
845 if(!f){
846 if ((p->outC ==NULL) || (strcmp(fnam,p->outC)!=0)){
847 fprintf(stderr, "codeword input file I/O ERROR: %s, outC=%s\n", strerror(errno),p->outC);
848 ERROR("can't open file %s for reading",fnam);
849 }
850 else
851 return 0;
852 }
853 cw_vec_t *entry=NULL;
854 while((entry=nzlist_r_one(f,NULL, fnam, &lineno))){
855 if((p->maxC) && (p->num_cws >= p->maxC)) {
856 free(entry);
857 break;
858 }
859 int valid = 1;
860 if (p->spaH) {
861 if (sparse_syndrome_non_zero(p->spaH, entry->weight, entry->arr)) {
862 valid = 0;
863 }
864 }
865 if (valid && p->spaL) {
866 if (!sparse_syndrome_non_zero(p->spaL, entry->weight, entry->arr)) {
867 valid = 0;
868 }
869 }
870 if (!valid) {
871 skipped_invalid++;
872 free(entry);
873 continue;
874 }
875 if((p->wmax==0) ||((p->wmax) && (entry->weight <= p->wmax))){
876 long long int old_num = p->num_cws;
877 p->codewords = codeword_add_maybe(p, entry->arr, entry->weight);
878 if (p->num_cws > old_num) {
879 count++;
880 }
881 }
882 free(entry);
883 }
884 fclose(f);
885 if (skipped_invalid > 0) {
886 fprintf(stderr, "# Warning: skipped %lld invalid codewords (not orthogonal to H or orthogonal to L)\n", skipped_invalid);
887 }
888 if(p->debug&1)
889 fprintf(stderr, "# read %lld codewords from %s, total %lld\n",count, fnam, p->num_cws);
890 return count;
891}
892
893long long int nzlist_write(const char fnam[], const char comment[], params_t *p){
894 long long int count=0;
895 assert(fnam);
896 FILE * f = nzlist_w_new(fnam, comment);
897 cw_vec_t *pvec;
898
899 for(pvec = p->codewords; pvec != NULL; pvec = (cw_vec_t *)(pvec->hh.next)){
900 count ++;
901 nzlist_w_append(f,pvec);
902 }
903 fclose(f);
904 return count;
905}
int arr[0]
Definition util_hash.h:40
int cnt
Definition util_hash.h:39
UT_hash_handle hh
Definition util_hash.h:37
int weight
Definition util_hash.h:38
void * next
Definition uthash.h:1129
int rows
Definition util_m4ri.h:111
int cols
Definition util_m4ri.h:112
char ** lines
Definition util_io.c:499
double timeout
Definition util_io.h:82
char * finC
Definition util_io.h:66
long long int maxC
Definition util_io.h:64
int dmin
Definition util_io.h:42
int dexp
Definition util_io.h:81
int n0
Definition util_io.h:61
char * finH
Definition util_io.h:73
int nchk
Definition util_io.h:63
int noscan
Definition util_io.h:48
csr_t * spaL
Definition util_io.h:79
char * outC
Definition util_io.h:67
csr_t * spaG
Definition util_io.h:78
csr_t * spaH
Definition util_io.h:77
int min_w
Definition util_io.h:70
int cbeg
Definition util_io.h:58
int smax
Definition util_io.h:37
int nvar
Definition util_io.h:62
int method
Definition util_io.h:35
int wmax
Definition util_io.h:41
int dmax
Definition util_io.h:43
int wmin
Definition util_io.h:44
char * finG
Definition util_io.h:74
char * finL
Definition util_io.h:75
double pmin
Definition util_io.h:72
char * fin
Definition util_io.h:76
int cend
Definition util_io.h:59
int steps
Definition util_io.h:36
int dW
Definition util_io.h:65
int start
Definition util_io.h:57
int debug
Definition util_io.h:32
char * fdem
Definition util_io.h:71
long long int num_cws
Definition util_io.h:69
int threads
Definition util_io.h:80
int classical
Definition util_io.h:33
int css
Definition util_io.h:34
cw_vec_t * codewords
Definition util_io.h:68
int seed
Definition util_io.h:49
int swei[MAX_W]
int max_row_wt; /* WARNING: this is defined in util_io.h as static const int *‍/
Definition util_io.h:56
#define HASH_DEL(head, delptr)
Definition uthash.h:507
#define HASH_ITER(hh, head, el, tmp)
Definition uthash.h:1060
#define HASH_ADD(hh, head, fieldname, keylen_in, add)
Definition uthash.h:427
#define HASH_FIND(hh, head, keyptr, keylen, out)
Definition uthash.h:165
void read_dem_file(char *fnam, csr_t **p_spaH, csr_t **p_spaL, double pmin, int debug)
Read a Detector Error Model (DEM) file and construct H and L matrices.
Definition util_io.c:663
int nzlist_w_append(FILE *f, const cw_vec_t *const vec)
Definition util_io.c:712
FILE * nzlist_w_new(const char fnam[], const char comment[])
Definition util_io.c:700
void var_kill(params_t *const p)
Clean up and free memory allocated in the params_t structure.
Definition util_io.c:473
FILE * nzlist_r_open(const char fnam[], long long int *lineno)
Definition util_io.c:724
params_t *const p
Definition util_io.c:52
long long int nzlist_read(const char fnam[], params_t *p)
Read codewords from a .nz list file and add them to the codeword hash.
Definition util_io.c:840
cw_vec_t * nzlist_r_one(FILE *f, cw_vec_t *vec, const char fnam[], long long int *lineno)
Definition util_io.c:744
cw_vec_t * codeword_add_maybe(params_t *const p, const int arr[], int weight)
Add a candidate codeword to the hash table if it meets weight limits.
Definition util_io.c:797
long long int nzlist_write(const char fnam[], const char comment[], params_t *p)
Write the found codewords from the hash table to a .nz file.
Definition util_io.c:893
params_t prm
Definition util_io.c:7
void var_init(int argc, char **argv, params_t *const p)
Initialize parameters and load matrices from command line arguments.
Definition util_io.c:54
#define BRIEF_HELP
Definition util_io.h:227
#define USAGE
Definition util_io.h:165
#define MAX_W
Definition util_io.h:28
int csr_csr_mul_non_zero(const csr_t *const A, const csr_t *const B)
Check if the product of two sparse matrices A * B^T is non-zero.
Definition util_m4ri.c:309
csr_t * csr_from_pairs(csr_t *mat, const int nz, int_pair *const prs, const int nrows, const int ncols)
Construct a CSR sparse matrix from an array of coordinate pairs.
Definition util_m4ri.c:535
csr_t * csr_mm_read(char *fin, csr_t *mat, int transpose)
Read a sparse matrix from a Matrix Market (.mtx) file into CSR format.
Definition util_m4ri.c:593
csr_t * Lx_for_CSS_code(const csr_t *const Hx, const csr_t *const Hz)
Compute logical generator matrix Lx for a CSS code.
Definition util_m4ri.c:872
void csr_print(const csr_t *const smat, const char str[])
Print a CSR matrix with a label string (formatted output).
Definition util_m4ri.c:576
csr_t * csr_free(csr_t *p)
Free memory allocated for a CSR sparse matrix.
Definition util_m4ri.c:459
#define ERROR(fmt,...)
Definition util_m4ri.h:13