Dist m4ri 0.0.1.alpha
Computing distance of a classical or quantum CSS code
Loading...
Searching...
No Matches
dist_rw.c
Go to the documentation of this file.
1
17// #include <m4ri/config.h>
18#include <inttypes.h>
19#include <strings.h>
20#include <stdlib.h>
21#include <time.h>
22#include <m4ri/m4ri.h>
23
24#include "mmio.h"
25#include "util_m4ri.h"
26#include "util_io.h"
27#include "dist_m4ri.h"
28
29
37int do_RW_dist(params_t * const p){
38 const csr_t * const spaH0 = p->spaH;
39 const csr_t * const spaL0 = p->spaL;
40 const int steps = p->steps;
41 const int wmin = p->wmin;
42 const int wmax = p->wmax;
43 const int classical = p->classical;
44 const int debug = p->debug;
46 const int nvar = spaH0->cols;
47 if(((!classical)&&(spaL0==NULL)) ||
48 ((classical)&&(spaL0!=NULL))){
49 printf("L0 %s NULL classical=%d\n",spaL0==NULL ? "=" : "!=", classical);
50 ERROR("L0 should be non-NULL only for classical code!\n");
51 }
52
53 int minW = nvar + 1;
54 if (p->dmax > 0 && p->dmax < minW) {
55 minW = p->dmax;
56 }
57 if (p->min_w != INT_MAX && p->min_w < minW) {
58 minW = p->min_w;
59 }
60
61 if(debug&2)
62 printf("# running do_RW_dist() with steps=%d wmin=%d wmax=%d classical=%d nvar=%d\n",
63 steps, wmin, wmax, classical, nvar);
64
65 mzd_t * mH = mzd_from_csr(NULL, spaH0);
66 mzd_t *mHT = NULL;
68 rci_t *ee = malloc(nvar*sizeof(rci_t));
69
70 if((!mH) || (!ee))
71 ERROR("memory allocation failed!\n");
72
74 mzp_t * perm=mzp_init(nvar);
75 mzp_t * pivs=mzp_init(nvar);
76 mzp_t * pivs_srtd=mzp_init(nvar);
77 mzp_t * skip_pivs=mzp_init(nvar);
78 if((!pivs) || (!perm))
79 ERROR("memory allocation failed!\n");
80
81 for (int ii=0; ii< steps; ii++){
82 pivs=mzp_rand(pivs);
83 mzp_set_ui(perm,1);
84 perm=perm_p_trans(perm,pivs,0);
87 int rank=0;
88 for(int i=0; i< nvar; i++){
89 int col=perm->values[i];
90 int ret=gauss_one(mH, col, rank);
91 if(ret)
92 pivs->values[rank++]=col;
93 }
94
96 pivs_srtd = mzp_copy(pivs_srtd,pivs);
97 qsort(pivs_srtd->values, rank, sizeof(pivs->values[0]), cmp_rci_t);
98 int end=-1, num=0;
99 for(int i=0; i < rank; i++){
100 int beg = end + 1;
101 end = pivs_srtd->values[i];
102 for(int j = beg; j < end; j++)
103 skip_pivs->values[num++] = j;
104 }
105 for(int j = end + 1 ; j < nvar; j++)
106 skip_pivs->values[num++] = j;
107
108#ifndef NDEBUG
109 if (num + rank != nvar)
110 ERROR("mismatch: rank=%d and num=%d do not add to nvar=%d\n",rank,num,nvar);
111#endif
112 skip_pivs->length = num;
113
114#ifndef NEW
115# define NEW 1
116#endif
117#if (NEW==1)
119 mHT = mzd_transpose(mHT,mH);
120#endif
127 int k = nvar - rank;
128 for (int ir=0; ir< k; ir++){
129 int cnt=0;
130 const int col = ee[cnt++] = skip_pivs->values[ir];
131 int limit = nvar + 1;
132 int cur_d = (minW <= nvar) ? minW : 0;
133 if (cur_d > 0) {
134 if ((p->outC || p->maxC || p->dW > 0) && p->dW >= 0) {
135 limit = minint(limit, cur_d + p->dW + 1);
136 } else {
137 limit = minint(limit, cur_d);
138 }
139 }
140#if (NEW==0)
141 for(int ix=0; ix<rank; ix++){
142 if(mzd_read_bit(mH,ix,col))
143 ee[cnt++] = pivs->values[ix];
144 if (cnt >= limit)
145 break;
146 }
147#elif (NEW==2)
153 rci_t ic=col, ix=0;
154 while (ix < rank){
155 int res = mzd_find_pivot(mH, ix, col, &ix, &ic);
156 if((res)&&(ic==col)){
157 ee[cnt++] = pivs->values[ix++];
158 // printf("cnt=%d j=%d\n",cnt,ix);
159 if (cnt >= limit)
160 break;
161 }
162 else
163 break;
164 }
165#else
166 word * rawrow = mzd_row(mHT,col);
167 rci_t j=-1;
168 while(cnt < limit){
169 j=nextelement(rawrow,mHT->width,j);
170 if(j==-1) // empty line after simplification
171 break;
172 ee[cnt++] = pivs->values[j++];
173 }
174#endif /* NEW */
175 if (cnt < limit){
177 qsort(ee, cnt, sizeof(rci_t), cmp_rci_t);
178#ifndef NDEBUG
180 if(sparse_syndrome_non_zero(spaH0, cnt, ee)){
181 printf("# cw of weight %d: [",cnt);
182 for(int i=0; i<cnt;i++)
183 printf("%d%s",ee[i],i+1==cnt?" ":"]\n");
184 ERROR("this should not happen: cw not orthogonal to H");
185 }
186#endif /* NDEBUG */
187
189 int nz;
190 if (classical)
191 nz=1;
192 else
193 nz = sparse_syndrome_non_zero(spaL0, cnt, ee);
194 if(nz){
197 p->codewords = codeword_add_maybe(p, ee, cnt);
198 if(debug&16){
199 printf("# step=%d row=%d minW=%d found cw of W=%d: [",ii,ir,minW,cnt);
200 const int max = ((cnt<25) || (debug&2048)) ? cnt : 25 ;
201 for(int i=0; i< max; i++)
202 printf("%d%s", ee[i], i+1!=max?" ": (cnt==max ? "]\n" : "...]\n"));
203 }
204 if (cnt < minW) {
205 minW = cnt;
206 }
207 if (p->maxC && p->num_cws >= p->maxC) {
208 goto alldone;
209 }
210 if (minW <= wmin){
211 minW = - minW;
212 goto alldone;
213 }
214 }
215 }
216 }
217 if(debug&8){
218 if(ii%1000==999)
219 printf("# round=%d of %d minW=%d\n", ii+1, steps, minW);
220 }
221
222 }
224 alldone:
227 if(skip_pivs)
228 mzp_free(skip_pivs);
229 if(pivs_srtd)
230 mzp_free(pivs_srtd);
231 mzp_free(perm);
232 mzp_free(pivs);
233 free(ee);
234 if(mHT)
235 mzd_free(mHT);
236 mzd_free(mH);
237
238 if (minW < 0) {
239 return minW;
240 }
241 if (p->min_w == INT_MAX) {
242 return 0;
243 }
244 if (wmax > 0 && p->min_w > wmax) {
245 return 0;
246 }
247 return p->min_w;
248}
249
250
251#ifdef STANDALONE
252
253int do_CC_dist(params_t * const p);
254
255
256int main(int argc, char **argv){
257 params_t * const p = &prm;
258
259 var_init(argc,argv,p);
260
261 if (p->finC) {
262 nzlist_read(p->finC, p);
263 }
264
265 // const int n=p->nvar;
266
267 if (prm.method & 1){ /* RW method */
268
270
271 if (prm.debug&1){
272 if (prm.dist_max != 0)
273 printf("### RW upper bound on the distance: %d\n",prm.dist_max);
274 else
275 printf("### RW: no upper bound found up to wmax = %d\n", prm.wmax);
276 if(prm.dist_max <0)
277 printf("### negative distance due to wmin=%d set (early termination)\n",prm.wmin);
278 else if (prm.dist_max ==0)
279 printf("### no codewords of weight <= %d found\n",prm.wmax);
280 }
281 if (prm.dist_max < 0) {
282 if(prm.debug) {
283 if (prm.method == 1)
284 printf("RW algorithm upper bound for the distance d=%d\n", prm.dist_max);
285 else
286 printf("RW algorithm upper bound for the distance d=%d (early termination due to wmin=%d)\n", prm.dist_max, prm.wmin);
287 }
288 printf("%d\n",prm.dist_max);
290 goto end_all;
291 }
292 if (prm.method==1){
293 if(prm.debug) {
294 if (prm.dist_max > 0)
295 printf("RW algorithm upper bound for the distance d=%d\n", prm.dist_max);
296 else
297 printf("RW algorithm: no upper bound found up to wmax = %d\n", prm.wmax);
298 }
299 printf("%d\n",prm.dist_max);
300 }
301 else{
302 if (prm.wmax==0) {
303 if (prm.dist_max == 0) {
304 ERROR("RW found no codewords, cannot run CC with wmax=0. Please specify wmax > 0.\n");
305 }
306 prm.wmax=abs(prm.dist_max)-1;
307 }
308 else if (prm.dist_max != 0) {
309 prm.wmax=minint(prm.wmax, abs(prm.dist_max)-1);
310 }
311 if (prm.wmax == 0) {
312 prm.dist_min = 1;
313 prm.dist_max = 1;
314 if (prm.debug & 1) {
315 printf("success (distance is 1) d=1\n");
316 }
317 printf("1\n");
318 goto end_all;
319 }
320 }
321 }
322
323 if (prm.method & 2){ /* cluster method */
324 int dmin=do_CC_dist(p);
325
326 if (dmin>0){
327 if (prm.debug&1)
328 printf("### Cluster (actual min-weight codeword found): d=%d\n",dmin);
329 printf("%d\n",dmin);
330 prm.dist_min = dmin; /* actual distance found */
331 prm.dist_max = dmin;
332 goto end_all;
333 }
334 else if (dmin<0){
335 if (prm.debug&1)
336 printf("### Cluster dmin=%d (no codewords of weight up to %d)\n",dmin,-dmin);
337 if (-dmin==abs(prm.dist_max)-1){
338 prm.dist_min=abs(prm.dist_max); /* OK */
339 if (prm.debug&1)
340 printf("success (two distance bounds coincide) d=%d\n",prm.dist_min);
341 printf("%d\n",prm.dist_min);
342 goto end_all;
343 }
344 else{
345 prm.dist_min=-dmin;
346 if(prm.debug){
348 printf("# distance in the interval (inclusive) %d to %d\n", prm.dist_min,prm.dist_max);
349 else
350 printf("# cluster algorithm failed to find a codeword up to wmax=%d\n",-dmin);
351 }
352 printf("%d\n",dmin);
353 }
354 }
355 else
356 ERROR("unexpected dmin=0\n");
357 }
358 end_all:
359 if (p->outC) {
360 char comment[256];
361 sprintf(comment, "generated by dist_m4ri");
362 nzlist_write(p->outC, comment, p);
363 }
364 if (p->debug & 32) {
365 cw_vec_t *cw;
366 for(cw = p->codewords; cw != NULL; cw = (cw_vec_t *)(cw->hh.next)){
367 printf("# cw: [ ");
368 for(int i=0; i<cw->weight; i++) printf("%d ", 1 + cw->arr[i]);
369 printf("] cnt=%d\n", cw->cnt);
370 }
371 }
372 var_kill(p);
373
374 return 0;
375 }
376
377#endif /* STANDALONE */
int do_CC_dist(params_t *const p)
Definition dist_cc.c:159
int main(int argc, char **argv)
Definition dist_m4ri.c:894
int do_RW_dist(params_t *const p)
distance of a classical or quantum CSS code
Definition dist_rw.c:37
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 cols
Definition util_m4ri.h:112
char * finC
Definition util_io.h:66
long long int maxC
Definition util_io.h:64
int dist_max
Definition util_io.h:51
csr_t * spaL
Definition util_io.h:79
char * outC
Definition util_io.h:67
csr_t * spaH
Definition util_io.h:77
int min_w
Definition util_io.h:70
int dist_min
Definition util_io.h:52
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
int steps
Definition util_io.h:36
int dW
Definition util_io.h:65
int debug
Definition util_io.h:32
long long int num_cws
Definition util_io.h:69
int classical
Definition util_io.h:33
cw_vec_t * codewords
Definition util_io.h:68
void var_kill(params_t *const p)
Clean up and free memory allocated in the params_t structure.
Definition util_io.c:473
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 * 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
mzd_t * mzd_from_csr(mzd_t *dst, const csr_t *p)
Convert a CSR sparse matrix to an MZD dense matrix.
Definition util_m4ri.c:156
mzp_t * perm_p_trans(mzp_t *q, const mzp_t *p, const rci_t start)
Apply transposed pivot permutation p to permutation q in-place.
Definition util_m4ri.c:442
#define ERROR(fmt,...)
Definition util_m4ri.h:13