int write_file (struct wnn_file *wf, char *n) { FILE *fp; int mode = 3; struct wnn_file_head fh; #ifdef WRITE_CHECK char *tmp = NULL, *backup = NULL; check_backup (n); #endif if ((fp = fopen (n, "r")) != NULL) { /* Old File Exist */ if (input_file_header (fp, &fh) == -1) { wnn_errorno = WNN_NOT_A_FILE; fclose (fp); return (-1); } mode = must_write_file (wf, &(fh.file_uniq)); fclose (fp); if (mode == -1) return -1; } if (mode == 0) { return (0); /* Need Not Write */ } else if (mode == 1 || mode == 3) { /* 3 when the file is not the one to be read. */ #ifdef WRITE_CHECK backup = make_backup_file (n); if ((tmp = make_tmp_file (n, 0, &fp)) == NULL) { delete_tmp_file (backup); #else /* WRITE_CHECK */ if ((fp = fopen (n, "w+")) == NULL) { #endif /* WRITE_CHECK */ wnn_errorno = WNN_FILE_WRITE_ERROR; return (-1); } } else if (mode == 2) { #ifdef WRITE_CHECK backup = make_backup_file (n); if ((tmp = make_tmp_file (n, 1, &fp)) == NULL) { delete_tmp_file (backup); #else /* WRITE_CHECK */ if ((fp = fopen (n, "r+")) == NULL) { /* New File */ #endif /* WRITE_CHECK */ wnn_errorno = WNN_FILE_WRITE_ERROR; return (-1); } } if (write_file_real (wf, fp, mode) == -1) { fclose (fp); #ifdef WRITE_CHECK delete_tmp_file (tmp); delete_tmp_file (backup); #endif /* WRITE_CHECK */ return -1; } fclose (fp); #ifdef WRITE_CHECK move_tmp_to_org (tmp, n, 1); delete_tmp_file (backup); #endif /* WRITE_CHECK */ if ((mode == 1) || (mode == 2)) { clear_dirty_bit (wf); } return (0); } static int write_file_real (struct wnn_file *wf, FILE *fp, int mode /* 1 For All, 2 For only hindo */ ) { struct wnn_file_head fh; if (fp) rewind (fp); bcopy ((char *) &wf->f_uniq, (char *) &(fh.file_uniq), WNN_F_UNIQ_LEN); bcopy ((char *) &wf->f_uniq_org, (char *) &(fh.file_uniq_org), WNN_F_UNIQ_LEN); bcopy (wf->passwd, fh.file_passwd, WNN_PASSWD_LEN); fh.file_type = wf->file_type; if (output_file_header (fp, &fh) == -1) { wnn_errorno = WNN_FILE_WRITE_ERROR; goto ERROR_RET; } switch (fh.file_type) { case WNN_FT_DICT_FILE: { struct JT *jt2; struct JT *jt = (struct JT *) wf->area; if (little_endian () && jt->dirty) { if ((jt2 = copy_dict ((struct JT *) wf->area)) == NULL) goto ERROR_RET; revdic (jt2, 1); if (writedict (jt2, fp) == -1) goto ERROR_RET; jt2 = free_dict (jt2); } else { /* if(writedict(wf->area, fp) == -1)goto ERROR_RET; */ if (mode == 2) { if (write_hindo_of_dict (wf->area, fp) == -1) goto ERROR_RET; } else { if (writedict (wf->area, fp) == -1) goto ERROR_RET; } } } break; case WNN_FT_HINDO_FILE: if (writehindo (wf->area, fp) == -1) goto ERROR_RET; break; case WNN_FT_FUZOKUGO_FILE: wnn_errorno = NOT_SUPPORTED_OPERATION; goto ERROR_RET; } return (0); ERROR_RET: return (-1); } static int writedict (struct JT *jt1, FILE *fp) { if (output_header_jt (fp, jt1) == -1) return (-1); #ifdef WRITE_CHECK if ((vfwrite (jt1->comment, 2, jt1->maxcomment, fp) == -1) || (vfwrite (jt1->hinsi_list, 2, jt1->maxhinsi_list, fp) == -1) || (vfwrite (jt1->hindo, 1, jt1->maxserial, fp) == -1) || (vfwrite (jt1->hinsi, 2, jt1->maxserial, fp) == -1)) return (-1); #ifdef CONVERT_with_SiSheng if (jt1->syurui == CWNN_REV_DICT) /* for Chinese PinYin dic only */ if (vfwrite (jt1->sisheng, 2, jt1->maxserial, fp) == -1) return (-1); #endif /* CONVERT_with_SiSheng */ if ((vfwrite (jt1->kanji, 1, jt1->maxkanji, fp) == -1) || (vfwrite (jt1->table, sizeof (struct uind1), jt1->maxtable, fp) == -1) || (vfwrite (jt1->ri1[D_YOMI], sizeof (struct rind1), jt1->maxri1[D_YOMI], fp) == -1) || (vfwrite (jt1->ri1[D_KANJI], sizeof (struct rind1), jt1->maxri1[D_KANJI], fp) == -1) || (vfwrite (jt1->hontai, 1, jt1->maxhontai, fp) == -1) || (vfwrite (jt1->ri2, sizeof (struct rind2), jt1->maxri2, fp) == -1)) return (-1); #else /* WRITE_CHECK */ vfwrite (jt1->comment, 2, jt1->maxcomment, fp); vfwrite (jt1->hinsi_list, 2, jt1->maxhinsi_list, fp); vfwrite (jt1->hindo, 1, jt1->maxserial, fp); vfwrite (jt1->hinsi, 2, jt1->maxserial, fp); #ifdef CONVERT_with_SiSheng if (jt1->syurui == CWNN_REV_DICT) /* for Chinese PinYin dic only */ vfwrite (jt1->sisheng, 2, jt1->maxserial, fp); #endif /* CONVERT_with_SiSheng */ vfwrite (jt1->kanji, 1, jt1->maxkanji, fp); vfwrite (jt1->table, sizeof (struct uind1), jt1->maxtable, fp); vfwrite (jt1->ri1[D_YOMI], sizeof (struct rind1), jt1->maxri1[D_YOMI], fp); vfwrite (jt1->ri1[D_KANJI], sizeof (struct rind1), jt1->maxri1[D_KANJI], fp); vfwrite (jt1->hontai, 1, jt1->maxhontai, fp); vfwrite (jt1->ri2, sizeof (struct rind2), jt1->maxri2, fp); #endif /* WRITE_CHECK */ return (0); } static int write_hindo_of_dict (struct JT *jt1, FILE *fp) { if (output_header_jt (fp, jt1) == -1) return (-1); #ifdef WRITE_CHECK if ((vfwrite (jt1->comment, 2, jt1->maxcomment, fp) == -1) || (vfwrite (jt1->hindo, 1, jt1->maxserial, fp) == -1)) return (-1); #else /* WRITE_CHECK */ vfwrite (jt1->comment, 2, jt1->maxcomment, fp); vfwrite (jt1->hindo, 1, jt1->maxserial, fp); #endif /* WRITE_CHECK */ return (0); } int discardfile (struct wnn_file *wf) { #ifdef nodef FILE *fp; if (wf->localf == LOCAL) { if ((fp = fopen (wf->name, "r")) == NULL) { log_err ("discardfile:No file %s.", wf->name); return (-1); } fclose (fp); } #endif switch (wf->file_type) { case WNN_FT_DICT_FILE: wf->area = free_dict (wf->area); break; case WNN_FT_HINDO_FILE: wf->area = free_hindo (wf->area); break; case WNN_FT_FUZOKUGO_FILE: /* fzk_discard(wf->area); */ break; } return (0); }
int main (int argc, char *argv[]) { lrs_dic *P1,*P2; /* structure for holding current dictionary and indices */ lrs_dat *Q1,*Q2; /* structure for holding static problem data */ lrs_mp_vector output1; /* holds one line of output; ray,vertex,facet,linearity */ lrs_mp_vector output2; /* holds one line of output; ray,vertex,facet,linearity */ lrs_mp_matrix Lin; /* holds input linearities if any are found */ lrs_dic *P2orig; /* we will save player 2's dictionary in getabasis */ long col; /* output column index for dictionary */ long startcol = 0; long prune = FALSE; /* if TRUE, getnextbasis will prune tree and backtrack */ long numequilib=0; /* number of nash equilibria found */ long oldnum=0; /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ /* they default to stdin and stdout, but may be overidden by command line parms. */ if(argc <= 2 ) { printf("Usage: nash input1 input2 [outputfile] \n"); return 1; } /*************************************************** Step 0: Do some global initialization that should only be done once, no matter how many lrs_dat records are allocated. db ***************************************************/ if ( !lrs_init ("\n*nash:")) return 1; printf(AUTHOR); /*********************************************************************************/ /* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ /*********************************************************************************/ Q1 = lrs_alloc_dat ("LRS globals"); /* allocate and init structure for static problem data */ if (Q1 == NULL) return 1; Q1->nash=TRUE; if (!lrs_read_dat (Q1, argc, argv)) /* read first part of problem data to get dimensions */ return 1; /* and problem type: H- or V- input representation */ P1 = lrs_alloc_dic (Q1); /* allocate and initialize lrs_dic */ if (P1 == NULL) return 1; if (!lrs_read_dic (P1, Q1)) /* read remainder of input to setup P1 and Q1 */ return 1; output1 = lrs_alloc_mp_vector (Q1->n + Q1->m); /* output holds one line of output from dictionary */ fclose(lrs_ifp); /* allocate and init structure for player 2's problem data */ printf ("\n*Second input taken from file %s\n", argv[2]); Q2 = lrs_alloc_dat ("LRS globals"); if (Q2 == NULL) return 1; Q2->nash=TRUE; if (!lrs_read_dat (Q2, 2, argv)) /* read first part of problem data to get dimensions */ return 1; /* and problem type: H- or V- input representation */ if (Q2->nlinearity > 0) free(Q2->linearity); /* we will start again */ Q2->linearity = CALLOC ((Q2->m + 2), sizeof (long)); P2 = lrs_alloc_dic (Q2); /* allocate and initialize lrs_dic */ if (P2 == NULL) return 1; if (!lrs_read_dic (P2, Q2)) /* read remainder of input to setup P2 and Q2 */ return 1; output2 = lrs_alloc_mp_vector (Q1->n + Q1->m); /* output holds one line of output from dictionary */ P2orig = lrs_getdic(Q2); /* allocate and initialize lrs_dic */ if (P2orig == NULL) return 1; copy_dict(Q2,P2orig,P2); fprintf (lrs_ofp, "\n***** %ld %ld rational", Q1->n, Q2->n); /*********************************************************************************/ /* Step 2: Find a starting cobasis from default of specified order */ /* P1 is created to hold active dictionary data and may be cached */ /* Lin is created if necessary to hold linearity space */ /* Print linearity space if any, and retrieve output from first dict. */ /*********************************************************************************/ if (!lrs_getfirstbasis (&P1, Q1, &Lin, TRUE)) return 1; if (Q1->dualdeg) { printf("\n*Warning! Dual degenerate, ouput may be incomplete"); printf("\n*Recommendation: Add dualperturb option before maximize in first input file\n"); } if (Q1->unbounded) { printf("\n*Warning! Unbounded starting dictionary for p1, output may be incomplete"); printf("\n*Recommendation: Change/remove maximize option, or include bounds \n"); } /* Pivot to a starting dictionary */ /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ if (Q1->homogeneous && Q1->hull) startcol++; /* col zero not treated as redundant */ for (col = startcol; col < Q1->nredundcol; col++) /* print linearity space */ lrs_printoutput (Q1, Lin[col]); /* Array Lin[][] holds the coeffs. */ /*********************************************************************************/ /* Step 3: Terminate if lponly option set, otherwise initiate a reverse */ /* search from the starting dictionary. Get output for each new dict. */ /*********************************************************************************/ /* We initiate reverse search from this dictionary */ /* getting new dictionaries until the search is complete */ /* User can access each output line from output which is */ /* vertex/ray/facet from the lrs_mp_vector output */ /* prune is TRUE if tree should be pruned at current node */ do { prune=lrs_checkbound(P1,Q1); if (!prune && lrs_getsolution (P1, Q1, output1, col)) { oldnum=numequilib; nash2_main(argc,argv,P1,Q1,P2orig,Q2,&numequilib,output2); if (numequilib > oldnum || Q1->verbose) { if(Q1->verbose) prat(" \np2's obj value: ",P1->objnum,P1->objden); lrs_nashoutput (Q1, output1, 1L); fprintf (lrs_ofp, "\n"); } } } while (lrs_getnextbasis (&P1, Q1, prune)); fprintf(lrs_ofp,"\n*Number of equilibria found: %ld",numequilib); fprintf (lrs_ofp,"\n*Player 1: vertices=%ld bases=%ld pivots=%ld", Q1->count[1], Q1->count[2],Q1->count[3]); fprintf (lrs_ofp,"\n*Player 2: vertices=%ld bases=%ld pivots=%ld", Q2->count[1], Q2->count[2],Q2->count[3]); lrs_clear_mp_vector(output1, Q1->m + Q1->n); lrs_clear_mp_vector(output2, Q1->m + Q1->n); lrs_free_dic (P1,Q1); /* deallocate lrs_dic */ lrs_free_dat (Q1); /* deallocate lrs_dat */ /* 2006.10.10 not sure what is going on with three lines below - sometimes crashes */ /* Q2->Qhead = P2; */ /* reset this or you crash free_dic */ /* lrs_free_dic (P2,Q2); */ /* deallocate lrs_dic */ /* lrs_free_dat (Q2); */ /* deallocate lrs_dat */ lrs_close ("nash:"); return 0; }
/********* end of lrs_getfirstbasis ***************/ long getabasis2 (lrs_dic * P, lrs_dat * Q, lrs_dic * P2orig, long order[]) /* Pivot Ax<=b to standard form */ /*Try to find a starting basis by pivoting in the variables x[1]..x[d] */ /*If there are any input linearities, these appear first in order[] */ /* Steps: (a) Try to pivot out basic variables using order */ /* Stop if some linearity cannot be made to leave basis */ /* (b) Permanently remove the cobasic indices of linearities */ /* (c) If some decision variable cobasic, it is a linearity, */ /* and will be removed. */ { long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long *linearity = Q->linearity; long *redundcol = Q->redundcol; long m, d, nlinearity; long nredundcol = 0L; /* will be calculated here */ static long firsttime=TRUE; static long *linindex; m = P->m; d = P->d; nlinearity = Q->nlinearity; if(firsttime) { firsttime = FALSE; linindex = calloc ((m + d + 2), sizeof (long)); } else /* after first time we update the change in linearities from the last time, saving many pivots */ { for(i=1;i<=m+d;i++) linindex[i]=FALSE; if(Q->debug) fprintf(lrs_ofp,"\nlindex ="); for(i=0;i<nlinearity;i++) { linindex[d+linearity[i]]=TRUE; if(Q->debug) fprintf(lrs_ofp," %ld",d+linearity[i]); } for(i=1;i<=m;i++) { if(linindex[B[i]]) /* pivot out unwanted linearities */ { k=0; while(k<d && (linindex[C[k]] || zero (A[Row[i]][Col[k]]))) k++; if (k < d) { j=i; /* note this index changes in update, cannot use i!)*/ if(C[k] > B[j]) /* decrease i or we may skip a linearity */ i--; pivot (P, Q, j, k); update (P, Q, &j, &k); } else { /* this is not necessarily an error, eg. two identical rows/cols in payoff matrix */ if(! zero(A[Row[i]][0])) /* error condition */ { if(Q->debug || Q->verbose) { fprintf(lrs_ofp,"\n*Infeasible linearity i=%ld B[i]=%ld",i,B[i]); if (Q->debug) printA(P,Q); } return(FALSE); } if(Q->debug || Q->verbose) { fprintf(lrs_ofp,"\n*Couldn't remove linearity i=%ld B[i]=%ld",i,B[i]); } } } /* if linindex */ } /* for i ..*/ goto hotstart; } /* standard lrs processing is done on only the first call to getabasis2 */ if (Q->debug) { fprintf (lrs_ofp, "\ngetabasis from inequalities given in order"); for (i = 0; i < m; i++) fprintf (lrs_ofp, " %ld", order[i]); } for (j = 0; j < m; j++) { i = 0; while (i <= m && B[i] != d + order[j]) i++; /* find leaving basis index i */ if (j < nlinearity && i > m) /* cannot pivot linearity to cobasis */ { if (Q->debug) printA (P, Q); #ifndef LRS_QUIET fprintf (lrs_ofp, "\nCannot find linearity in the basis"); #endif return FALSE; } if (i <= m) { /* try to do a pivot */ k = 0; while (C[k] <= d && zero (A[Row[i]][Col[k]])) k++; if (C[k] <= d) { pivot (P, Q, i, k); update (P, Q, &i, &k); } else if (j < nlinearity) { /* cannot pivot linearity to cobasis */ if (zero (A[Row[i]][0])) { #ifndef LRS_QUIET fprintf (lrs_ofp, "\n*Input linearity in row %ld is redundant--skipped", order[j]); #endif linearity[j] = 0; } else { if (Q->debug) printA (P, Q); if (Q->verbose) fprintf (lrs_ofp, "\nInconsistent linearities"); return FALSE; } } /* end if j < nlinearity */ } /* end of if i <= m .... */ } /* end of for */ /* update linearity array to get rid of redundancies */ i = 0; k = 0; /* counters for linearities */ while (k < nlinearity) { while (k < nlinearity && linearity[k] == 0) k++; if (k < nlinearity) linearity[i++] = linearity[k++]; } nlinearity = i; /* column dependencies now can be recorded */ /* redundcol contains input column number 0..n-1 where redundancy is */ k = 0; while (k < d && C[k] <= d) { if (C[k] <= d) /* decision variable still in cobasis */ redundcol[nredundcol++] = C[k] - Q->hull; /* adjust for hull indices */ k++; } /* now we know how many decision variables remain in problem */ Q->nredundcol = nredundcol; Q->lastdv = d - nredundcol; /* if not first time we continue from here after loading dictionary */ hotstart: if (Q->debug) { fprintf (lrs_ofp, "\nend of first phase of getabasis2: "); fprintf (lrs_ofp, "lastdv=%ld nredundcol=%ld", Q->lastdv, Q->nredundcol); fprintf (lrs_ofp, "\nredundant cobases:"); for (i = 0; i < nredundcol; i++) fprintf (lrs_ofp, " %ld", redundcol[i]); printA (P, Q); } /* here we save dictionary for use next time, *before* we resize */ copy_dict(Q,P2orig,P); /* Remove linearities from cobasis for rest of computation */ /* This is done in order so indexing is not screwed up */ for (i = 0; i < nlinearity; i++) { /* find cobasic index */ k = 0; while (k < d && C[k] != linearity[i] + d) k++; if (k >= d) { if(Q->debug || Q->verbose) { fprintf (lrs_ofp, "\nCould not remove cobasic index"); } /* not neccesarily an error as eg., could be repeated row/col in payoff */ } else { removecobasicindex (P, Q, k); d = P->d; } } if (Q->debug && nlinearity > 0) printA (P, Q); /* set index value for first slack variable */ /* Check feasability */ if (Q->givenstart) { i = Q->lastdv + 1; while (i <= m && !negative (A[Row[i]][0])) i++; if (i <= m) fprintf (lrs_ofp, "\n*Infeasible startingcobasis - will be modified"); } return TRUE; } /* end of getabasis2 */
long nash2_main (int argc, char *argv[], lrs_dic *P1, lrs_dat *Q1, lrs_dic *P2orig, lrs_dat *Q2, long *numequilib, lrs_mp_vector output) { lrs_dic *P2; /* This can get resized, cached etc. Loaded from P2orig */ lrs_mp_matrix Lin; /* holds input linearities if any are found */ long col; /* output column index for dictionary */ long startcol = 0; long prune = FALSE; /* if TRUE, getnextbasis will prune tree and backtrack */ long nlinearity; long *linearity; static long firstwarning=TRUE; /* FALSE if dual deg warning for Q2 already given */ static long firstunbounded=TRUE; /* FALSE if dual deg warning for Q2 already given */ long i,j; /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ /* they default to stdin and stdout, but may be overidden by command line parms. */ /*********************************************************************************/ /* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ /*********************************************************************************/ P2=lrs_getdic(Q2); copy_dict(Q2,P2,P2orig); /* Here we take the linearities generated by the current vertex of player 1*/ /* and append them to the linearity in player 2's input matrix */ /* next is the key magic linking player 1 and 2 */ /* be careful if you mess with this! */ linearity=Q2->linearity; nlinearity=0; for(i=Q1->lastdv+1;i <= P1->m; i++) { if (!zero(P1->A[P1->Row[i]][0])) { j = Q1->inequality[P1->B[i]-Q1->lastdv]; if (Q1->nlinearity ==0 || j < Q1->linearity[0]) linearity[nlinearity++]= j; } } /* add back in the linearity for probs summing to one */ if (Q1->nlinearity > 0) linearity[nlinearity++]= Q1->linearity[0]; /*sort linearities */ for (i = 1; i < nlinearity; i++) reorder (linearity, nlinearity); if(Q2->verbose) { fprintf(lrs_ofp,"\np2: linearities %ld",nlinearity); for (i=0;i < nlinearity; i++) fprintf(lrs_ofp," %ld",linearity[i]); } Q2->nlinearity = nlinearity; Q2->polytope = FALSE; /*********************************************************************************/ /* Step 2: Find a starting cobasis from default of specified order */ /* P2 is created to hold active dictionary data and may be cached */ /* Lin is created if necessary to hold linearity space */ /* Print linearity space if any, and retrieve output from first dict. */ /*********************************************************************************/ if (!lrs_getfirstbasis2 (&P2, Q2, P2orig, &Lin, TRUE)) goto sayonara; if (firstwarning && Q2->dualdeg) { firstwarning=FALSE; printf("\n*Warning! Dual degenerate, ouput may be incomplete"); printf("\n*Recommendation: Add dualperturb option before maximize in second input file\n"); } if (firstunbounded && Q2->unbounded) { firstunbounded=FALSE; printf("\n*Warning! Unbounded starting dictionary for p2, output may be incomplete"); printf("\n*Recommendation: Change/remove maximize option, or include bounds \n"); } /* Pivot to a starting dictionary */ /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ if (Q2->homogeneous && Q2->hull) startcol++; /* col zero not treated as redundant */ /* for (col = startcol; col < Q2->nredundcol; col++)*/ /* print linearity space */ /*lrs_printoutput (Q2, Lin[col]);*/ /* Array Lin[][] holds the coeffs. */ /*********************************************************************************/ /* Step 3: Terminate if lponly option set, otherwise initiate a reverse */ /* search from the starting dictionary. Get output for each new dict. */ /*********************************************************************************/ /* We initiate reverse search from this dictionary */ /* getting new dictionaries until the search is complete */ /* User can access each output line from output which is */ /* vertex/ray/facet from the lrs_mp_vector output */ /* prune is TRUE if tree should be pruned at current node */ do { prune=lrs_checkbound(P2,Q2); col=0; if (!prune && lrs_getsolution (P2, Q2, output, col)) { if (Q2->verbose) prat(" \np1's obj value: ",P2->objnum,P2->objden); if (lrs_nashoutput (Q2, output, 2L)) (*numequilib)++; } } while (lrs_getnextbasis (&P2, Q2, prune)); sayonara: lrs_free_dic(P2,Q2); return 0; }