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

📄 solve.c

📁 生成直角Steiner树的程序包
💻 C
📖 第 1 页 / 共 4 页
字号:
#include <string.h>#include "lpkit.h"#include "lpglob.h"#include "debug.h"/* Globals used by solver */static short JustInverted;static short Status;static short Doiter;static short DoInvert;static short Break_bb;/* Status values seen only internally to the solver... */#define	SWITCH_TO_PRIMAL		-1#define SINGULAR_BASIS			-2#define	LOST_PRIMAL_FEASIBILITY		-3static void ftran(lprec *lp, REAL *pcol){  int  i, j, k, r, *rowp;  REAL theta, *valuep;  for(i = 1; i <= lp->eta_size; i++) {    k = lp->eta_col_end[i] - 1;    r = lp->eta_row_nr[k];    theta = pcol[r];    if(theta != 0) {      j = lp->eta_col_end[i - 1];      /* CPU intensive loop, let's do pointer arithmetic */      for(rowp = lp->eta_row_nr + j, valuep = lp->eta_value + j;	  j < k;	  j++, rowp++, valuep++)	pcol[*rowp] += theta * *valuep;      pcol[r] *= lp->eta_value[k];    }  }  /* round small values to zero */  for(i = 0; i <= lp->rows; i++)    my_round(pcol[i], lp->epsel);} /* ftran */void btran(lprec *lp, REAL *row){  int  i, j, k, *rowp;  REAL f, *valuep;  for(i = lp->eta_size; i >= 1; i--) {    f = 0;    k = lp->eta_col_end[i] - 1;    j = lp->eta_col_end[i - 1];    for(rowp = lp->eta_row_nr + j, valuep = lp->eta_value + j;	j <= k;	j++, rowp++, valuep++)      f += row[*rowp] * *valuep;    my_round(f, lp->epsel);    row[lp->eta_row_nr[k]] = f;  }} /* btran */static void set_row_end(lprec *lp){  int i, j, row_nr;  int *num, *rownum;  MALLOC(num, lp->rows + 1);  MALLOC(rownum, lp->rows + 1);  for(i = 0; i <= lp->rows; i++) {    num[i] = 0;    rownum[i] = 0;  }  for(i = 0; i < lp->non_zeros; i++)    rownum[lp->mat[i].row_nr]++;  lp->row_end[0] = 0;  for(i = 1; i <= lp->rows; i++)    lp->row_end[i] = lp->row_end[i - 1] + rownum[i];  for(i = 1; i <= lp->columns; i++)    for(j = lp->col_end[i - 1]; j < lp->col_end[i]; j++) {      row_nr = lp->mat[j].row_nr;      if(row_nr != 0) {	num[row_nr]++;	lp->col_no[lp->row_end[row_nr - 1] + num[row_nr]] = i;      }    }  free(num);  free(rownum);  lp->row_end_valid = TRUE;}static short isvalid(lprec *lp){  int i, j, *rownum, *colnum;  if(!lp->row_end_valid) {    set_row_end(lp);  }  if(lp->valid)    return(TRUE);  CALLOC(rownum, lp->rows + 1);  CALLOC(colnum, lp->columns + 1);  for(i = 1 ; i <= lp->columns; i++)    for(j = lp->col_end[i - 1]; j < lp->col_end[i]; j++) {      colnum[i]++;      rownum[lp->mat[j].row_nr]++;    }  for(i = 1; i <= lp->columns; i++) {    if(lp->orig_lowbo[lp->rows + i] == lp->orig_upbo[lp->rows + i]) continue;    if(colnum[i] == 0) {      if(lp->names_used)        printf("%% Warning: Variable %s not used in any constraints\n",		lp->col_name[i]);      else        printf("%% Warning: Variable %d not used in any constraints\n",		i);    }  }  free(rownum);  free(colnum);  lp->valid = TRUE;  return(TRUE);}static void resize_eta(lprec *lp){  lp->eta_alloc *= 1.5;  REALLOC(lp->eta_value, lp->eta_alloc);  REALLOC(lp->eta_row_nr, lp->eta_alloc);  /* printf("%% resized eta to size %d\n", lp->eta_alloc); */} /* resize_eta */static void condensecol(lprec *lp,			int row_nr,			REAL *pcol){  int i, elnr;  elnr = lp->eta_col_end[lp->eta_size];  if(elnr + lp->rows + 2 >= lp->eta_alloc) /* maximum local growth of Eta */    resize_eta(lp);  for(i = 0; i <= lp->rows; i++)    if(i != row_nr && pcol[i] != 0) {      lp->eta_row_nr[elnr] = i;      lp->eta_value[elnr] = pcol[i];      elnr++;    }  lp->eta_row_nr[elnr] = row_nr;  lp->eta_value[elnr] = pcol[row_nr];  elnr++;  lp->eta_col_end[lp->eta_size + 1] = elnr;} /* condensecol */static void addetacol(lprec *lp){  int  i, j, k;  REAL theta;  j = lp->eta_col_end[lp->eta_size];  lp->eta_size++;  k = lp->eta_col_end[lp->eta_size] - 1;  theta = 1 / (REAL) lp->eta_value[k];  lp->eta_value[k] = theta;  for(i = j; i < k; i++)    lp->eta_value[i] *= -theta;  JustInverted = FALSE;} /* addetacol */static void setpivcol(lprec *lp,		      int   varin,		      REAL *pcol){  int  i, colnr;  for(i = 0; i <= lp->rows; i++)    pcol[i] = 0;  if(lp->lower[varin]) {    if(varin > lp->rows) {      colnr = varin - lp->rows;      for(i = lp->col_end[colnr - 1]; i < lp->col_end[colnr]; i++)	pcol[lp->mat[i].row_nr] = lp->mat[i].value;      pcol[0] -= Extrad;    }    else      pcol[varin] = 1;  }  else { /* !lower */    if(varin > lp->rows) {      colnr = varin - lp->rows;      for(i = lp->col_end[colnr - 1]; i < lp->col_end[colnr]; i++)	pcol[lp->mat[i].row_nr] = -lp->mat[i].value;      pcol[0] += Extrad;    }    else      pcol[varin] = -1;  }  ftran(lp, pcol);} /* setpivcol */static void minoriteration(lprec *lp,			   int colnr,			   int row_nr){  int  i, j, k, wk, varin, varout, elnr;  REAL piv = 0, theta;  varin = colnr + lp->rows;  elnr = lp->eta_col_end[lp->eta_size];  wk = elnr;  lp->eta_size++;  if(Extrad != 0) {    lp->eta_row_nr[elnr] = 0;    lp->eta_value[elnr] = -Extrad;    elnr++;    if(elnr >= lp->eta_alloc)      resize_eta(lp);  }  for(j = lp->col_end[colnr - 1] ; j < lp->col_end[colnr]; j++) {    k = lp->mat[j].row_nr;    if(k == 0 && Extrad != 0)      lp->eta_value[lp->eta_col_end[lp->eta_size - 1]] += lp->mat[j].value;    else if(k != row_nr) {      lp->eta_row_nr[elnr] = k;      lp->eta_value[elnr] = lp->mat[j].value;      elnr++;      if(elnr >= lp->eta_alloc)	resize_eta(lp);    }    else      piv = lp->mat[j].value;  }  lp->eta_row_nr[elnr] = row_nr;  lp->eta_value[elnr] = 1 / piv;  theta = lp->rhs[row_nr] / piv;  lp->rhs[row_nr] = theta;  for(i = wk; i < elnr; i++)    lp->rhs[lp->eta_row_nr[i]] -= theta * lp->eta_value[i];  varout = lp->bas[row_nr];  lp->bas[row_nr] = varin;  lp->basis[varout] = FALSE;  lp->basis[varin] = TRUE;  for(i = wk; i < elnr; i++)    lp->eta_value[i] /= -piv;  ++elnr;  if(elnr >= lp->eta_alloc)    resize_eta(lp);  lp->eta_col_end[lp->eta_size] = elnr;} /* minoriteration */static void rhsmincol(lprec *lp,		      REAL theta,		      int row_nr,		      int varin){  int  i, j, k, varout;  REAL f;  if(row_nr > lp->rows + 1) {    printf("%% Error: rhsmincol called with row_nr: %d, rows: %d\n",	    row_nr, lp->rows);    printf("%% This indicates numerical instability\n");    exit(EXIT_FAILURE);  }  j = lp->eta_col_end[lp->eta_size];  k = lp->eta_col_end[lp->eta_size + 1];  for(i = j; i < k; i++) {    f = lp->rhs[lp->eta_row_nr[i]] - theta * lp->eta_value[i];    my_round(f, lp->epsb);    lp->rhs[lp->eta_row_nr[i]] = f;  }  lp->rhs[row_nr] = theta;  varout = lp->bas[row_nr];  lp->bas[row_nr] = varin;  lp->basis[varout] = FALSE;  lp->basis[varin] = TRUE;} /* rhsmincol */short invert(lprec *lp){  int    i, j, v, wk, numit, varnr, row_nr, colnr, varin;  REAL   theta;  REAL   *pcol;  int	 singularities;  short  *frow;  short  *fcol;  int    *rownum, *col, *row;  int    *colnum;  if(lp->print_at_invert)    printf("%% Start Invert iter %d eta_size %d rhs[0] %g \n",	    lp->iter, lp->eta_size, (double) - lp->rhs[0]);  CALLOC(rownum, lp->rows + 1);  CALLOC(col, lp->rows + 1);  CALLOC(row, lp->rows + 1);  CALLOC(pcol, lp->rows + 1);  CALLOC(frow, lp->rows + 1);  CALLOC(fcol, lp->columns + 1);  CALLOC(colnum, lp->columns + 1);  for(i = 0; i <= lp->rows; i++)    frow[i] = TRUE;  for(i = 0; i < lp->columns; i++)    fcol[i] = FALSE;  for(i = 0; i < lp->rows; i++)    rownum[i] = 0;  for(i = 0; i <= lp->columns; i++)    colnum[i] = 0;  for(i = 0; i <= lp->rows; i++)    if(lp->bas[i] > lp->rows)      fcol[lp->bas[i] - lp->rows - 1] = TRUE;    else      frow[lp->bas[i]] = FALSE;  for(i = 1; i <= lp->rows; i++)    if(frow[i])      for(j = lp->row_end[i - 1] + 1; j <= lp->row_end[i]; j++) {	wk = lp->col_no[j];	if(fcol[wk - 1]) {	  colnum[wk]++;	  rownum[i - 1]++;	}      }  for(i = 1; i <= lp->rows; i++)    lp->bas[i] = i;  for(i = 1; i <= lp->rows; i++)    lp->basis[i] = TRUE;  for(i = 1; i <= lp->columns; i++)    lp->basis[i + lp->rows] = FALSE;  for(i = 0; i <= lp->rows; i++)    lp->rhs[i] = lp->rh[i];  for(i = 1; i <= lp->columns; i++) {    varnr = lp->rows + i;    if(!lp->lower[varnr]) {      theta = lp->upbo[varnr];      for(j = lp->col_end[i - 1]; j < lp->col_end[i]; j++)	lp->rhs[lp->mat[j].row_nr] -= theta * lp->mat[j].value;    }  }  for(i = 1; i <= lp->rows; i++)    if(!lp->lower[i])      lp->rhs[i] -= lp->upbo[i];  singularities = 0;  lp->eta_size = 0;  v = 0;  row_nr = 0;  lp->num_inv = 0;  numit = 0;  while(v < lp->rows) {    row_nr++;    if(row_nr > lp->rows)      row_nr = 1;    v++;    if(rownum[row_nr - 1] == 1)      if(frow[row_nr]) {	v = 0;	j = lp->row_end[row_nr - 1] + 1;	while(!(fcol[lp->col_no[j] - 1]))	  j++;	colnr = lp->col_no[j];	fcol[colnr - 1] = FALSE;	colnum[colnr] = 0;	for(j = lp->col_end[colnr - 1]; j < lp->col_end[colnr]; j++)	  if(frow[lp->mat[j].row_nr])	    rownum[lp->mat[j].row_nr - 1]--;	frow[row_nr] = FALSE;	minoriteration(lp, colnr, row_nr);      }  }  v = 0;  colnr = 0;  while(v < lp->columns) {    colnr++;    if(colnr > lp->columns)      colnr = 1;    v++;    if(colnum[colnr] == 1)      if(fcol[colnr - 1]) {	v = 0;	j = lp->col_end[colnr - 1] + 1;	while(!(frow[lp->mat[j - 1].row_nr]))	  j++;	row_nr = lp->mat[j - 1].row_nr;	frow[row_nr] = FALSE;	rownum[row_nr - 1] = 0;	for(j = lp->row_end[row_nr - 1] + 1; j <= lp->row_end[row_nr]; j++)	  if(fcol[lp->col_no[j] - 1])	    colnum[lp->col_no[j]]--;	fcol[colnr - 1] = FALSE;	numit++;	col[numit - 1] = colnr;	row[numit - 1] = row_nr;      }  }  for(j = 1; j <= lp->columns; j++)    if(fcol[j - 1]) {      fcol[j - 1] = FALSE;      setpivcol(lp, j + lp->rows, pcol);      row_nr = 1;      while((row_nr <= lp->rows) && (!(frow[row_nr] && pcol[row_nr])))	row_nr++;      /* if(row_nr == lp->rows + 1) */      if(row_nr > lp->rows) {	/* This column is singular!  Just skip it, leaving one of the */	/* slack variables basic in its place... */	printf("%% Column %d singular!\n", j);	++singularities;      }      else {	frow[row_nr] = FALSE;	condensecol(lp, row_nr, pcol);	theta = lp->rhs[row_nr] / (REAL) pcol[row_nr];	rhsmincol(lp, theta, row_nr, lp->rows + j);	addetacol(lp);      }    }  for(i = numit - 1; i >= 0; i--) {    colnr = col[i];    row_nr = row[i];    varin = colnr + lp->rows;    for(j = 0; j <= lp->rows; j++)      pcol[j] = 0;    for(j = lp->col_end[colnr - 1]; j < lp->col_end[colnr]; j++)      pcol[lp->mat[j].row_nr] = lp->mat[j].value;    pcol[0] -= Extrad;    condensecol(lp, row_nr, pcol);    theta = lp->rhs[row_nr] / (REAL) pcol[row_nr];    rhsmincol(lp, theta, row_nr, varin);    addetacol(lp);  }  for(i = 1; i <= lp->rows; i++)    my_round(lp->rhs[i], lp->epsb);  if(lp->print_at_invert)    printf("%% End Invert                eta_size %d rhs[0] %g\n",	    lp->eta_size, (double) - lp->rhs[0]);  JustInverted = TRUE;  DoInvert = FALSE;  free(rownum);  free(col);  free(row);  free(pcol);  free(frow);  free(fcol);  free(colnum);  return (singularities <= 0);} /* invert */static int colprim(lprec *lp,		   short minit,		   REAL   *drow){  int  varnr, i, j, colnr;  REAL f, dpiv;  dpiv = -lp->epsd;  colnr = 0;  if(!minit) {    for(i = 1; i <= lp->sum; i++)      drow[i] = 0;    drow[0] = 1;    btran(lp, drow);    for(i = 1; i <= lp->columns; i++) {      varnr = lp->rows + i;      if(!lp->basis[varnr])	if(lp->upbo[varnr] > 0) {	  f = 0;	  for(j = lp->col_end[i - 1]; j < lp->col_end[i]; j++)	    f += drow[lp->mat[j].row_nr] * lp->mat[j].value;	  drow[varnr] = f;	}    }    for(i = 1; i <= lp->sum; i++)      my_round(drow[i], lp->epsd);  }  for(i = 1; i <= lp->sum; i++)    if(!lp->basis[i])      if(lp->upbo[i] > 0) {	if(lp->lower[i])	  f = drow[i];	else	  f = -drow[i];	if(f < dpiv) {	  dpiv = f;	  colnr = i;	}      }  if(lp->trace) {    if(colnr > 0)

⌨️ 快捷键说明

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