⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 certsolve.c

📁 IML package provides efficient routines to solve nonsingular systems of linear equations, certifie
💻 C
📖 第 1 页 / 共 5 页
字号:
		  printf("checking lower n-r rows fails, repeat!\n");#endif		  continue; 		}	    }	  { XFREE(Pt); XFREE(rpt); }	  for (i = 0; i < n; i++) { mpz_clear(mp_b1[i]); } { XFREE(mp_b1); }	  { XFREE(basiscmb[0]); XFREE(basiscmb[1]); XFREE(basiscmb); }#if HAVE_VERBOSE_MODE && HAVE_TIME_H	  tt = (double)(clock()-ti)/CLOCKS_PER_SEC;	  printf("Solution Checking Time: %f\n", tt);#endif	  /* recover the solution vector and the certificate vector */	  if (r < m) 	    {	      /* system has more than one solution, the first case */	      /* compute Qy */	      for (i = r; i > 0; i--)		if (rp[i] != i) { mpz_swap(mp_N[i-1], mp_N[rp[i]-1]); }	      	      /* set last n-r entries in z be 0 and compute zP */	      if (certflag == 1)		{		  for (i = r; i < n; i++) { mpz_set_ui(mp_NZ[i], 0); }		  for (i = r; i > 0; i--)		    if (P[i] != i) { mpz_swap(mp_NZ[i-1], mp_NZ[P[i]-1]); }		}	      { XFREE(P); XFREE(rp); }	      return 1;	    }	  else	    { 	      /* system has a unique solution, the second case */	      { XFREE(P); XFREE(rp); }	      return 2; 	    }	}      else 	{	  if ((r == m) && (certflag == 0))	    {	      { XFREE(basiscmb[0]); XFREE(basiscmb[1]); XFREE(basiscmb); }	      { XFREE(P); XFREE(rp); XFREE(Pt); XFREE(rpt); }	      return 3;	    }	  P[r+1] = idx+1;      /* update P for permutation of row r+1 */	  /* compute u = A_21.A_11^(-1) */	  mpz_init(mp_Du);	  mp_Nu = XMALLOC(mpz_t, r);	  for (i = 0; i < r; i++) { mpz_init(mp_Nu[i]); }	  A11RNS = XMALLOC(Double *, basislen);	  for (i = 0; i < basislen; i++)	    {	      A11RNS[i] = XMALLOC(Double, r*r);	      for (j = 0; j < r; j++)		for (l = 0; l < r; l++)		  A11RNS[i][j*r+l] = \		    (Double)mpz_fdiv_ui(mp_A[Pt[j]*m+rpt[l]], basis[i]);	    }	  mp_A21 = XMALLOC(mpz_t, r);	  for (i = 0; i < r; i++)	    mpz_init_set(mp_A21[i], mp_A[Pt[idx]*m+rpt[i]]);	  nonsingSolvRNSMM(LeftSolu, r, 1, basislen, basis, A11RNS, mp_A21, \			   mp_Nu, mp_Du);	  	  for (i = 0; i < basislen; i++)  { XFREE(A11RNS[i]); } 	  for (i = 0; i < r; i++) { mpz_clear(mp_A21[i]); }	  { XFREE(mp_A21); XFREE(A11RNS); }	  if (r < m)	    {	      /* compare u.A_12 with A_22 */	      A12RNS = XMALLOC(Double *, basislen);	      for (i = 0; i < basislen; i++)		{		  A12RNS[i] = XMALLOC(Double, r*(m-r));		  for (j = 0; j < r; j++)		    for (l = 0; l < m-r; l++)		      A12RNS[i][j*(m-r)+l] = \			(Double)mpz_fdiv_ui(mp_A[Pt[j]*m+rpt[r+l]], basis[i]);		}	      mp_A22 = XMALLOC(mpz_t, m-r);	      for (i = 0; i < m-r; i++)		mpz_init_set(mp_A22[i], mp_A[Pt[idx]*m+rpt[r+i]]);	      cmp = LVecSMatMulCmp(LeftMul, basislen, r, m-r, basis, A12RNS, \				   mp_Du, mp_Nu, mp_A22);	      for (i = 0; i < basislen; i++) { XFREE(A12RNS[i]); } 	      for (i = 0; i < m-r; i++) { mpz_clear(mp_A22[i]); }	      { XFREE(A12RNS); XFREE(mp_A22); }	      /* comparison fails, restart */	      if (cmp == 0) 		{ 		  mpz_clear(mp_Du);		  for (i = 0; i < r; i++) { mpz_clear(mp_Nu[i]); }		  { XFREE(P); XFREE(rp); XFREE(Pt); XFREE(rpt); XFREE(mp_Nu); }#if HAVE_VERBOSE_MODE && HAVE_TIME_H		  printf("checking no solution case fails, repeat!\n");#endif		  continue;		}	    }	  if (certflag == 1)	    {	      /* set q = (u, -1, 0, ..., 0), which is store in mp_NZ */	      mpz_set(mp_DZ, mp_Du); 	      for (i = 0; i < r; i++) { mpz_set(mp_NZ[i], mp_Nu[i]); }	      mpz_set(mp_NZ[r], mp_Du);	      mpz_neg(mp_NZ[r], mp_NZ[r]);	      for (i = r+1; i < n; i++) { mpz_set_ui(mp_NZ[i], 0); }	      /* compute qP */	      for (i = r+1; i > 0; i--)		if (P[i] != i) { mpz_swap(mp_NZ[i-1], mp_NZ[P[i]-1]); }	    }	  mpz_clear(mp_Du);	  { XFREE(basiscmb[0]); XFREE(basiscmb[1]); XFREE(basiscmb); }	  for (i = 0; i < r; i++) { mpz_clear(mp_Nu[i]); } { XFREE(mp_Nu); }	  { XFREE(P); XFREE(rp); XFREE(Pt); XFREE(rpt); }	  /* system has no solution, the third case */	  return 3;	}    }}/* * * Calling Sequence: *   1/2/3 <-- certSolveRedMP(certflag, nullcol, n, m, mp_A, mp_b, mp_N, mp_D,  *                            mp_NZ, mp_DZ) *  * Summary: *   Certified solve a system of linear equations and reduce the solution *   size, where the left hand side input matrix is represented by signed  *   mpz_t integers *  * Description: *   Let the system of linear equations be Av = b, where A is a n x m matrix, *   and b is a n x 1 vector. There are three possibilities: * *   1. The system has more than one rational solution *   2. The system has a unique rational solution *   3. The system has no solution * *   In the first case, there exist a solution vector v with minimal *   denominator and a rational certificate vector z to certify that the  *   denominator of solution v is really the minimal denominator. * *   The 1 x n certificate vector z satisfies that z.A is an integer vector  *   and z.b has the same denominator as the solution vector v. *   In this case, the function will output the solution with minimal  *   denominator and optional certificate vector z (if certflag = 1).  * *   Note: if choose not to compute the certificate vector z, the solution  *     will not garantee, but with high probability, to be the minimal  *     denominator solution, and the function will run faster. * *   Lattice reduction will be used to reduce the solution size. Parameter  *   nullcol designates the dimension of kernal basis we use to reduce the  *   solution size as well as the dimension of nullspace we use to compute  *   the minimal denominator. The heuristic results show that the solution  *   size will be reduced by factor 1/nullcol.  * *   To find the minimum denominator as fast as possible, nullcol cannot be *   too small. We use NULLSPACE_COLUMN as the minimal value of nullcol. That *   is, if the input nullcol is less than NULLSPACE_COLUMN, NULLSPACE_COLUMN *   will be used instead. However, if the input nullcol becomes larger, the *   function will be slower. Meanwhile, it does not make sense to make  *   nullcol greater than the dimension of nullspace of the input system.  * *   As a result, the parameter nullcol will not take effect unless  *   NULLSPACE_COLUMN < nullcol < dimnullspace is satisfied, where  *   dimnullspace is the dimension of nullspace of the input system.  If the *   above condition is not satisfied, the boundary value NULLSPACE_COLUMN or   *   dimnullspace will be used. * *   In the second case, the function will only compute the unique solution  *   and the contents in the space for certificate vector make no sense. * *   In the third case, there exists a certificate vector q to certify that *   the system has no solution. The 1 x n vector q satisfies q.A = 0 but  *   q.b <> 0. In this case, the function will output this certificate vector *   q and store it into the same space for certificate z. The value of  *   certflag also controls whether to output q or not.  *   *   Note: if the function returns 3, then the system determinately does not  *     exist solution, no matter whether to output certificate q or not. *   In the first case, there exist a solution vector v with minimal *   denominator and a rational certificate vector z to certify that the  *   denominator of solution v is the minimal denominator. *  * Input: *   certflag: 1/0, flag to indicate whether or not to compute the certificate  *             vector z or q.  *           - If certflag = 1, compute the certificate. *           - If certflag = 0, not compute the certificate. *    nullcol: long, dimension of nullspace and kernel basis of conditioned *             system,  *             if nullcol < NULLSPACE_COLUMN, use NULLSPACE_COLUMN instead *          n: long, row dimension of the system *          m: long, column dimension of the system *       mp_A: 1-dim mpz_t array length n*m, representation of n x m matrix A *       mp_b: 1-dim mpz_t array length n, representation of n x 1 vector b *   * Return: *   1: the first case, system has more than one solution *   2: the second case, system has a unique solution *   3: the third case, system has no solution *  * Output: *   mp_N: 1-dim mpz_t array length m,  *       - numerator vector of the solution with minimal denominator  *         in the first case *       - numerator vector of the unique solution in the second case *       - make no sense in the third case *   mp_D: mpz_t, *       - minimal denominator of the solutions in the first case *       - denominator of the unique solution in the second case *       - make no sense in the third case * * The following will only be computed when certflag = 1 *   mp_NZ: 1-dim mpz_t array length n,  *        - numerator vector of the certificate z in the first case *        - make no sense in the second case *        - numerator vector of the certificate q in the third case *   mp_DZ: mpz_t,  *        - denominator of the certificate z if in the first case *        - make no sense in the second case *        - denominator of the certificate q in the third case * * Note:  *   - The space of (mp_N, mp_D) is needed to be preallocated, and entries in *     mp_N and integer mp_D are needed to be initiated as any integer values. *   - If certflag is specified to be 1, then also needs to preallocate space *     for (mp_NZ, mp_DZ), and initiate integer mp_DZ and entries in mp_NZ to  *     be any integer values.  *     Otherwise, set mp_NZ = NULL, and mp_DZ = any integer * */longcertSolveRedMP (const long certflag, const long nullcol, const long n, \		const long m, mpz_t *mp_A, mpz_t *mp_b, \		mpz_t *mp_N, mpz_t mp_D, mpz_t *mp_NZ, mpz_t mp_DZ){  long i, j, l, r, r1, t, idx, cmp, ver, basislen=1;  FiniteField qh, p, d=1;  long *P, *rp, *Pt, *rpt;  FiniteField *basis, **basiscmb;  Double *DA, *Db, *Dc, **CRNS, **C1RNS, **A11RNS, **A12RNS;  mpz_t mp_maxInter, mp_bd, mp_alpha, mp_beta, mp_Du;  mpz_t *mp_b1, *mp_A21, *mp_A22, *mp_Nu;  double tt;#if HAVE_TIME_H  clock_t ti;#endif  mpz_init(mp_alpha);   maxMagnMP(mp_A, n, m, m, mp_alpha);  if (!mpz_sgn(mp_alpha))    {      /* in case A is a zero matrix, check vector b */      mpz_init(mp_beta);      maxMagnMP(mp_b, n, 1, 1, mp_beta);      if (!mpz_sgn(mp_beta))	{	  /* if b is also a zero matrix, set N = 0, D = 1, NZ = 0, DZ = 1 */	  for (i = 0; i < m; i++) { mpz_set_ui(mp_N[i], 0); }	  mpz_set_ui(mp_D, 1);	  if (certflag == 1)	    {	      for (i = 0; i < n; i++) { mpz_set_ui(mp_NZ[i], 0); }	      mpz_set_ui(mp_DZ, 1);	    }	  { mpz_clear(mp_alpha); mpz_clear(mp_beta); }	  return 1;	}      else	{	  /* compute certificate q, q.A = 0, q.b <> 0 in this case */	  if (certflag == 1) 	    {	      for (i = 0; i < n; i++) { mpz_set_ui(mp_NZ[i], 0); }	      mpz_set_ui(mp_DZ, 1);	      for (i = 0; i < n; i++)		if (mpz_sgn(mp_b[i]) != 0) 		  { mpz_set_ui(mp_NZ[i], 1);  break; }	    }	  /* if b has non-zero entries, no solution */	  mpz_clear(mp_alpha); mpz_clear(mp_beta);	  return 3;	}    }  /* generate RNS basis */  mpz_init_set_ui(mp_maxInter, 1);  mpz_addmul_ui(mp_maxInter, mp_alpha, 2);  qh = RNSbound(m);  basiscmb = findRNS(qh, mp_maxInter, &basislen);    basis = basiscmb[0];  { mpz_clear(mp_maxInter); mpz_clear(mp_alpha); }  while (1)    {      p = RandPrime(15, 22); /* choose p randomly, 2^15 < p < 2^22 */#if HAVE_VERBOSE_MODE && HAVE_TIME_H      ti = clock();      printf("prime: %ld\n", p);#endif            /* call RowEchelonTransform to reduce DA = A mod p, and obtain rank r */      DA = XMALLOC(Double, n*m);      for (i = 0; i < n*m; i++) { DA[i] = (Double)mpz_fdiv_ui(mp_A[i], p); }      P = XMALLOC(long, n+1);      for (i = 0; i < n+1; i++) { P[i] = i; }      rp = XCALLOC(long, n+1);      RowEchelonTransform(p, DA, n, m, 1, 1, 0, 0, P, rp, &d);      r = rp[0];      /* if rank is 0, then p is a bad prime, restart */      if (r == 0) 	{ #if HAVE_VERBOSE_MODE && HAVE_TIME_H	  printf("rank deficient in decomposition, repeat!\n"); #endif	  { XFREE(DA); XFREE(P); XFREE(rp); }	  continue; 	}      /* compute Pt, rpt satisfying that row Pt[i], column rpt[j] of A will be 	 changed to row i, column j respectively after the decomposition */      Pt = revseq(r, n, P);      rpt = revseq(r, m, rp);      /* decomposite <A|b> mod p */      Db = XMALLOC(Double, n);      for (i = 0; i < n; i++) 	Db[i] = (Double)mpz_fdiv_ui(mp_b[Pt[i]], p);      Dc = XMALLOC(Double, n);      for (i = r; i < n; i++) { Dc[i] = Db[i]; }      /* compute first r rows of Dc by DA[1..r, 1..r].Db[1..r] */      cblas_dgemv(CblasRowMajor, CblasNoTrans, r, r, 1.0, DA, m, Db, 1, 0.0, \		  Dc, 1);      /* compute last n-r rows of Dc by DA[r+1..n, 1..r].Db[1..r]+Db[r+1..n] */      if (r < n)	cblas_dgemv(CblasRowMajor, CblasNoTrans, n-r, r, 1.0, DA+r*m, m, \		    Db, 1, 1.0, Dc+r, 1);      Dmod(p, Dc, n, 1, 1);      idx = r-1;      while ((++idx < n) && (Dc[idx] == 0)) ;      { XFREE(DA); XFREE(Db); XFREE(Dc); }#if HAVE_VERBOSE_MODE && HAVE_TIME_H      tt = (double)(clock()-ti)/CLOCKS_PER_SEC;      printf("Decomposition Time: %f\n", tt);#endif      /* rank of A mod p == rank of <A|b> mod p */      if (idx == n)  	{#if HAVE_VERBOSE_MODE && HAVE_TIME_H	  ti = clock();#endif	  /* compute mp_b1 = P.b */	  mp_b1 = XMALLOC(mpz_t, n);	  for (i = 0; i < n; i++) { mpz_init_set(mp_b1[i], mp_b[Pt[i]]); }	  /* CRNS[i] = [A_11, A_12] mod basis[i] */	  CRNS = XMALLOC(Double *, basislen);	  for (i = 0; i < basislen; i++)	    {	      CRNS[i] = XMALLOC(Double, r*m);	      for (j = 0; j < r; j++) 		for (l = 0; l < m; l++)		  CRNS[i][j*m+l] = (Double)mpz_fdiv_ui(mp_A[Pt[j]*m+rpt[l]], \						       basis[i]); 	    }	  /* full column rank, the solution is unique */	  if (r == m)	    nonsingSolvRNSMM(RightSolu, r, 1, basislen, basis, CRNS, mp_b1, \			     mp_N, mp_D);	  else	    {	      /* not in full column rank, compute minimal denominator solution

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -