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

📄 glpnet02.c

📁 著名的大规模线性规划求解器源码GLPK.C语言版本,可以修剪.内有详细帮助文档.
💻 C
字号:
/* glpnet02.c (permutations to block triangular form) *//************************************************************************  This code is part of GLPK (GNU Linear Programming Kit).**  This code is the result of translation of the Fortran subroutines*  MC13D and MC13E associated with the following paper:**  I.S.Duff, J.K.Reid, Algorithm 529: Permutations to block triangular*  form, ACM Trans. on Math. Softw. 4 (1978), 189-192.**  Use of ACM Algorithms is subject to the ACM Software Copyright and*  License Agreement. See <http://www.acm.org/publications/policies>.**  The translation was made by Andrew Makhorin <mao@mai2.rcnet.ru>.**  GLPK is free software: you can redistribute it and/or modify it*  under the terms of the GNU General Public License as published by*  the Free Software Foundation, either version 3 of the License, or*  (at your option) any later version.**  GLPK is distributed in the hope that it will be useful, but WITHOUT*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public*  License for more details.**  You should have received a copy of the GNU General Public License*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.***********************************************************************/#include "glpnet.h"/************************************************************************  NAME**  mc13d - permutations to block triangular form**  SYNOPSIS**  #include "glpnet.h"*  int mc13d(int n, const int icn[], const int ip[], const int lenr[],*     int ior[], int ib[], int lowl[], int numb[], int prev[]);**  DESCRIPTION**  Given the column numbers of the nonzeros in each row of the sparse*  matrix, the routine mc13d finds a symmetric permutation that makes*  the matrix block lower triangular.**  INPUT PARAMETERS**  n     order of the matrix.**  icn   array containing the column indices of the non-zeros. Those*        belonging to a single row must be contiguous but the ordering*        of column indices within each row is unimportant and wasted*        space between rows is permitted.**  ip    ip[i], i = 1,2,...,n, is the position in array icn of the*        first column index of a non-zero in row i.**  lenr  lenr[i], i = 1,2,...,n, is the number of non-zeros in row i.**  OUTPUT PARAMETERS**  ior   ior[i], i = 1,2,...,n, gives the position on the original*        ordering of the row or column which is in position i in the*        permuted form.**  ib    ib[i], i = 1,2,...,num, is the row number in the permuted*        matrix of the beginning of block i, 1 <= num <= n.**  WORKING ARRAYS**  arp   working array of length [1+n], where arp[0] is not used.*        arp[i] is one less than the number of unsearched edges leaving*        node i. At the end of the algorithm it is set to a permutation*        which puts the matrix in block lower triangular form.**  ib    working array of length [1+n], where ib[0] is not used.*        ib[i] is the position in the ordering of the start of the ith*        block. ib[n+1-i] holds the node number of the ith node on the*        stack.**  lowl  working array of length [1+n], where lowl[0] is not used.*        lowl[i] is the smallest stack position of any node to which a*        path from node i has been found. It is set to n+1 when node i*        is removed from the stack.**  numb  working array of length [1+n], where numb[0] is not used.*        numb[i] is the position of node i in the stack if it is on it,*        is the permuted order of node i for those nodes whose final*        position has been found and is otherwise zero.**  prev  working array of length [1+n], where prev[0] is not used.*        prev[i] is the node at the end of the path when node i was*        placed on the stack.**  RETURNS**  The routine mc13d returns num, the number of blocks found. */int mc13d(int n, const int icn[], const int ip[], const int lenr[],      int ior[], int ib[], int lowl[], int numb[], int prev[]){     int *arp = ior;      int dummy, i, i1, i2, icnt, ii, isn, ist, ist1, iv, iw, j, lcnt,         nnm1, num, stp;      /* icnt is the number of nodes whose positions in final ordering         have been found. */      icnt = 0;      /* num is the number of blocks that have been found. */      num = 0;      nnm1 = n + n - 1;      /* Initialization of arrays. */      for (j = 1; j <= n; j++)      {  numb[j] = 0;         arp[j] = lenr[j] - 1;      }      for (isn = 1; isn <= n; isn++)      {  /* Look for a starting node. */         if (numb[isn] != 0) continue;         iv = isn;         /* ist is the number of nodes on the stack ... it is the stack            pointer. */         ist = 1;         /* Put node iv at beginning of stack. */         lowl[iv] = numb[iv] = 1;         ib[n] = iv;         /* The body of this loop puts a new node on the stack or            backtracks. */         for (dummy = 1; dummy <= nnm1; dummy++)         {  i1 = arp[iv];            /* Have all edges leaving node iv been searched? */            if (i1 >= 0)            {  i2 = ip[iv] + lenr[iv] - 1;               i1 = i2 - i1;               /* Look at edges leaving node iv until one enters a new                  node or all edges are exhausted. */               for (ii = i1; ii <= i2; ii++)               {  iw = icn[ii];                  /* Has node iw been on stack already? */                  if (numb[iw] == 0) goto L70;                  /* Update value of lowl[iv] if necessary. */                  if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw];               }               /* There are no more edges leaving node iv. */               arp[iv] = -1;            }            /* Is node iv the root of a block? */            if (lowl[iv] < numb[iv]) goto L60;            /* Order nodes in a block. */            num++;            ist1 = n + 1 - ist;            lcnt = icnt + 1;            /* Peel block off the top of the stack starting at the top               and working down to the root of the block. */            for (stp = ist1; stp <= n; stp++)            {  iw = ib[stp];               lowl[iw] = n + 1;               numb[iw] = ++icnt;               if (iw == iv) break;            }            ist = n - stp;            ib[num] = lcnt;            /* Are there any nodes left on the stack? */            if (ist != 0) goto L60;            /* Have all the nodes been ordered? */            if (icnt < n) break;            goto L100;L60:        /* Backtrack to previous node on path. */            iw = iv;            iv = prev[iv];            /* Update value of lowl[iv] if necessary. */            if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw];            continue;L70:        /* Put new node on the stack. */            arp[iv] = i2 - ii - 1;            prev[iw] = iv;            iv = iw;            lowl[iv] = numb[iv] = ++ist;            ib[n+1-ist] = iv;         }      }L100: /* Put permutation in the required form. */      for (i = 1; i <= n; i++)         arp[numb[i]] = i;      return num;}/**********************************************************************/#if 0#include "glplib.h"void test(int n, int ipp);int main(void){     /* test program for routine mc13d */      test( 1,   0);      test( 2,   1);      test( 2,   2);      test( 3,   3);      test( 4,   4);      test( 5,  10);      test(10,  10);      test(10,  20);      test(20,  20);      test(20,  50);      test(50,  50);      test(50, 200);      return 0;}void fa01bs(int max, int *nrand);void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]);void test(int n, int ipp){     int ip[1+50], icn[1+1000], ior[1+50], ib[1+51], iw[1+150],         lenr[1+50];      char a[1+50][1+50], hold[1+100];      int i, ii, iblock, ij, index, j, jblock, jj, k9, num;      xprintf("\n\n\nMatrix is of order %d and has %d off-diagonal non-"         "zeros\n", n, ipp);      for (j = 1; j <= n; j++)      {  for (i = 1; i <= n; i++)            a[i][j] = 0;         a[j][j] = 1;      }      for (k9 = 1; k9 <= ipp; k9++)      {  /* these statements should be replaced by calls to your            favorite random number generator to place two pseudo-random            numbers between 1 and n in the variables i and j */         for (;;)         {  fa01bs(n, &i);            fa01bs(n, &j);            if (!a[i][j]) break;         }         a[i][j] = 1;      }      /* setup converts matrix a[i,j] to required sparsity-oriented         storage format */      setup(n, a, ip, icn, lenr);      num = mc13d(n, icn, ip, lenr, ior, ib, &iw[0], &iw[n], &iw[n+n]);      /* output reordered matrix with blocking to improve clarity */      xprintf("\nThe reordered matrix which has %d block%s is of the fo"         "rm\n", num, num == 1 ? "" : "s");      ib[num+1] = n + 1;      index = 100;      iblock = 1;      for (i = 1; i <= n; i++)      {  for (ij = 1; ij <= index; ij++)            hold[ij] = ' ';         if (i == ib[iblock])         {  xprintf("\n");            iblock++;         }         jblock = 1;         index = 0;         for (j = 1; j <= n; j++)         {  if (j == ib[jblock])            {  hold[++index] = ' ';               jblock++;            }            ii = ior[i];            jj = ior[j];            hold[++index] = (char)(a[ii][jj] ? 'X' : '0');         }         xprintf("%.*s\n", index, &hold[1]);      }      xprintf("\nThe starting point for each block is given by\n");      for (i = 1; i <= num; i++)      {  if ((i - 1) % 12 == 0) xprintf("\n");         xprintf(" %4d", ib[i]);      }      xprintf("\n");      return;}void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]){     int i, j, ind;      for (i = 1; i <= n; i++)         lenr[i] = 0;      ind = 1;      for (i = 1; i <= n; i++)      {  ip[i] = ind;         for (j = 1; j <= n; j++)         {  if (a[i][j])            {  lenr[i]++;               icn[ind++] = j;            }         }      }      return;}double g = 1431655765.0;double fa01as(int i){     /* random number generator */      g = fmod(g * 9228907.0, 4294967296.0);      if (i >= 0)         return g / 4294967296.0;      else         return 2.0 * g / 4294967296.0 - 1.0;}void fa01bs(int max, int *nrand){     *nrand = (int)(fa01as(1) * (double)max) + 1;      return;}#endif/* eof */

⌨️ 快捷键说明

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