static int cpx_prepare_solve(lp_desc* lpd, struct lp_meth *meth, struct lp_sol *sol, double timeout) { #ifdef HAS_MIQP_CALLBACKBUG /* too much trouble to support MIQP with older XPRESS with this bug; the MIQP method is `not recommended' for use in these versions by DASH in anycase */ switch (lpd->prob_type) { case PROBLEM_MIQP: case PROBLEM_FIXEDQ: case PROBLEM_RELAXEDQ: Fprintf(Current_Error, "Eplex error: quadratic MIP not supported for this solver because it is unstable.\n"); ec_flush(Current_Error); return -1; } #endif CallN(XPRSsetintcontrol(lpd->lp, XPRS_SOLUTIONFILE, 0)); /* set up call-back to get solution state at each integer solution */ if (IsMIPProb(lpd->prob_type)) { CallN(XPRSsetcbintsol(lpd->lp, _get_xpress_sol, (void *)sol)); } if (timeout >= 0.0) { /* 0 is no timeout, negative for desired semantics */ int timeout_i; timeout = ceil(timeout); /* avoid round to zero and overflow */ timeout_i = timeout > INT_MAX ? INT_MAX : (int)timeout; Log1(XPRSsetintcontrol(lpd->lp, XPRS_MAXTIME, %d), -timeout_i); XPRSsetintcontrol(lpd->lp, XPRS_MAXTIME, -timeout_i); }
/* ============================ */ int main(int argc, char * argv[]){ /* variaveis auxiliares */ int i,j; char opcoes[2]=""; /* variaveis para montar o LP no solver */ int *mrwind, *mgcols; char *qgtype; double *rhs, *obj, *dlb, *dub, melhor_limitante_dual; char probname[] = "mochila"; /* Verifica estratégia a adotar de acordo com a linha de comando */ if ( (argc<2) || (argc>3) ) { showUsage(); exit(-1); } if ( (strlen(argv[1]) != 2) ){ printf("Primeiro parâmetro tem tamanho menor que 2. \n"); showUsage(); exit(-1); } else{ sprintf(opcoes,"%c",argv[1][0]); if ( (strcmp(opcoes,"0")) && (strcmp(opcoes,"1")) ){ printf("Primeiro parâmetro dever ter apenas \"0\"s e \"1\"s !\n"); showUsage(); exit(-1); } else HEURISTICA_PRIMAL=(strcmp(opcoes,"0")); sprintf(opcoes,"%c",argv[1][1]); if ( (strcmp(opcoes,"0")) && (strcmp(opcoes,"1")) ){ printf("Primeiro parâmetro dever ter apenas \"0\"s e \"1\"s !\n"); showUsage(); exit(-1); } else BRANCH_AND_CUT=(strcmp(opcoes,"0")); } if (argc>=3) MAX_NODE_DEPTH_FOR_SEP=atoi(argv[2]); /* inicializa valores de variaveis globais */ totcuts=0; itersep=0; zstar=XPRS_MINUSINFINITY; /* le dados de entrada do problema da Mochila 0-1.*/ scanf("%d %d",&n,&W); c=(double *)malloc(n*sizeof(double)); w=(int *)malloc(n*sizeof(int)); for(i=0;i<n;i++) scanf("%lf",&c[i]); for(i=0;i<n;i++) scanf("%d",&w[i]); /* aloca espaco para os arrays que serão usados pelo XPRESS na carga do problema. * Ler no manual do XPRESS a documentação sobre a rotina XPRSloadglobal. */ /* arrays com informações sobre as variáveis */ qgtype = malloc(n*sizeof(char)); obj=(double *)malloc(n*sizeof(double)); dlb=(double *)malloc(n*sizeof(double)); dub=(double *)malloc(n*sizeof(double)); mgcols=(int *)malloc(n*sizeof(int)); /* arrays com informações sobre as restrições (só tem uma !)*/ qrtype = malloc(sizeof(char)); rhs=(double *)malloc(sizeof(double)); mstart=(int *)malloc((n+1)*sizeof(int)); mrwind=(int *)malloc(n*sizeof(int)); dmatval=(double *)malloc(n*sizeof(double)); /* carga dos vetores */ for(i=0;i<n;i++){ obj[i]=c[i]; /* custos das variáveis */ dlb[i]=0.0; /* limite inferior das variáveis */ dub[i]=1.0; /* limite superior das variáveis */ mgcols[i]=i; /* todas variáveis são globais (veja manual para explicação) */ qgtype[i]='B'; /* todas variáveis são binárias */ mrwind[i]=0; /* todas variáveis ocorrem na primeira restrição */ mstart[i]=i; /* (veja manual para explicação) */ dmatval[i]=w[i]; /* coeficiente da variável na restrição 1 */ } rhs[0]=(double) W; qrtype[0]='L'; mstart[n]=n; /* incializacão do XPRESS */ xpress_ret=XPRSinit(""); if (xpress_ret) errormsg("Main: Erro de inicializacao do XPRESS.\n",__LINE__,xpress_ret); /* "cria" o problema */ xpress_ret=XPRScreateprob(&prob); if (xpress_ret) errormsg("Main: Erro na initializacao do problema",__LINE__,xpress_ret); /* ======================================================================== */ /* Atribui valores a vários parametros de controle do XPRESS */ /* ======================================================================== */ /* limita o tempo de execucao */ xpress_ret=XPRSsetintcontrol(prob,XPRS_MAXTIME,MAX_CPU_TIME); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_MAXTIME.\n",__LINE__,xpress_ret); /* aloca espaço extra de linhas para inserção de cortes. CUIDADO: Isto tem que ser feito ANTES (!) de carregar o problema ! */ xpress_ret=XPRSsetintcontrol(prob,XPRS_EXTRAROWS,MAX_NUM_CORTES+1); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_EXTRAROWS.\n",__LINE__,xpress_ret); /* aloca espaço extra de elementos não nulos para inserção de cortes. CUIDADO: Isto tem que ser feito ANTES (!) de carregar o problema ! */ xpress_ret=XPRSsetintcontrol(prob,XPRS_EXTRAELEMS,n*n); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_EXTRAELEMS.",__LINE__,xpress_ret); /*=====================================================================================*/ /* RELEASE NOTE: The controls CPKEEPALLCUTS, CPMAXCUTS and CPMAXELEMS have been removed*/ /* limita o número máximo de cortes que poderão ser inseridos xpress_ret=XPRSsetintcontrol(prob,XPRS_CPMAXCUTS,MAX_NUM_CORTES); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_CPMAXCUTS.\n",__LINE__,xpress_ret);*/ /* limita o número máximo de elementos não-nulos nos cortes que poderão ser inseridos xpress_ret=XPRSsetintcontrol(prob,XPRS_CPMAXELEMS,MAX_NUM_CORTES*n); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_CPMAXELEMS.",__LINE__,xpress_ret);*/ /*=====================================================================================*/ /* carga do modelo*/ xpress_ret=XPRSloadglobal(prob, probname, n, 1, qrtype, rhs, NULL, obj, mstart, NULL, mrwind, dmatval, dlb, dub, n, 0, qgtype, mgcols, NULL, NULL, NULL, NULL, NULL); if (xpress_ret) errormsg("Main: Erro na carga do modelo.",__LINE__,xpress_ret); /* libera memoria dos vetores usado na carga do LP */ free(qrtype); free(rhs); free(obj); free(mstart); free(mrwind); free(dmatval); free(dlb); free(dub); free(qgtype); free(mgcols); /* salva um arquivo ".lp" com o LP original */ xpress_ret=XPRSwriteprob(prob,"LP","l"); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSwriteprob.\n",__LINE__,xpress_ret); /* Desabilita o PRESOLVE: o problema da mochila é muito fácil para o XPRESS */ xpress_ret=XPRSsetintcontrol(prob,XPRS_PRESOLVE,0); if (xpress_ret) errormsg("Main: Erro ao desabilitar o presolve.",__LINE__,xpress_ret); /* impressão para conferência */ if (HEURISTICA_PRIMAL) printf("*** Heurística Primal será usada\n"); if (BRANCH_AND_CUT) { printf("*** Algoritmo de branch-and-cut.\n"); /* aloca espaco para as estruturas que serao usadas para * armazenar os cortes encontrados na separacao. Para evitar * perda de tempo, estas estruturas sao alocadas uma unica vez. * Para isso, o tamanho das mesmas deve ser o maior possivel * para comportar os dados obtidos por *qualquer* uma das * rotinas de separacao. No caso a rotina de separação poderá * gerar até um "cover ineuqality" por vez. Ler no manual a * descrição da rotina XPRSaddcuts */ qrtype=(char *)malloc(sizeof(char)); mtype=(int *) malloc(sizeof(int)); drhs=(double *)malloc(sizeof(double)); mstart=(int *)malloc((n+1)*sizeof(int)); mcols=(int *)malloc(n*sizeof(int)); /* cada corte tera no maximo n nao-zeros */ dmatval=(double *)malloc(n*sizeof(double)); /* callback indicando que sera feita separacao de cortes em cada nó da arvore de B&B */ xpress_ret=XPRSsetcbcutmgr(prob,Cortes,NULL); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSsetcbcutmgr.\n",__LINE__,xpress_ret); /*=====================================================================================*/ /* RELEASE NOTE: The controls CPKEEPALLCUTS, CPMAXCUTS and CPMAXELEMS have been removed*/ /* Diz ao XPRESS que quer manter cortes no pool xpress_ret=XPRSsetintcontrol(prob,XPRS_CPKEEPALLCUTS,0); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_CPKEEPALLCUTS.\n",__LINE__,xpress_ret); */ /*=====================================================================================*/ } else { printf("*** Algoritmo de branch-and-bound puro.\n"); qrtype=NULL; mtype=NULL; drhs=NULL; mstart=NULL; mcols=NULL; dmatval=NULL; if (HEURISTICA_PRIMAL) { /* callback indicando que sera feita separacao de cortes em cada nó da arvore de B&B. Mas, neste caso, a rotina nao faz corte, limitando-se apenas a executar a heuristica primal. */ xpress_ret=XPRSsetcbcutmgr(prob,Cortes,NULL); if (xpress_ret) errormsg("Main: rotina XPRSsetcbcutmgr.\n",__LINE__,xpress_ret); } } /* Desabilita a separacao de cortes do XPRESS. Mochila é muito fácil para o XPRESS */ xpress_ret=XPRSsetintcontrol(prob,XPRS_CUTSTRATEGY,0); if (xpress_ret) errormsg("Main: Erro ao tentar setar o XPRS_CUTSTRATEGY.\n",__LINE__,xpress_ret); /* callback para salvar a melhor solucao inteira encontrada */ xpress_ret=XPRSsetcbintsol(prob,SalvaMelhorSol,NULL); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSsetcbintsol.\n",__LINE__,xpress_ret); /* aloca espaco para o vetor "x" que contera as solucoes das * relaxacoes e de "xstar" que armazenara a melhor solucao inteira * encontrada. */ x=(double *)malloc(n*sizeof(double)); xstar=(double *)malloc(n*sizeof(double)); /* resolve o problema */ xpress_ret=XPRSmaxim(prob,"g"); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSmaxim.\n",__LINE__,xpress_ret); /* imprime a solucao otima ou a melhor solucao encontrada (se achou) e o seu valor */ xpress_ret=XPRSgetintattrib(prob,XPRS_MIPSTATUS,&xpress_status); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSgetintatrib.\n",__LINE__,xpress_ret); if ( (xpress_status==XPRS_MIP_OPTIMAL) || (xpress_status==XPRS_MIP_SOLUTION) || (zstar > XPRS_MINUSINFINITY ) ){ XPRSgetintattrib(prob,XPRS_MIPSOLNODE,&NODE_BEST_INTEGER_SOL); printf("\n"); printf("- Valor da solucao otima =%12.6f \n",(double)(zstar)); printf("- Variaveis otimas: (nó=%d)\n",NODE_BEST_INTEGER_SOL); if ( zstar == XPRS_MINUSINFINITY ) { xpress_ret=XPRSgetsol(prob,xstar,NULL,NULL,NULL); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSgetsol\n",__LINE__,xpress_ret); } ImprimeSol(xstar); } else printf("Main: programa terminou sem achar solucao inteira !\n"); /* impressao de estatisticas */ printf("********************\n"); printf("Estatisticas finais:\n"); printf("********************\n"); printf(".total de cortes inseridos ........ = %d\n",totcuts); printf(".valor da FO da primeira relaxação. = %.6f\n",objval_relax); printf(".valor da FO no nó raiz ........... = %.6f\n",objval_node1); xpress_ret=XPRSgetintattrib(prob,XPRS_NODES,&totnodes); if (xpress_ret) errormsg("Main: Erro na chamada da rotina XPRSgetintatrib.\n",__LINE__,xpress_ret); printf(".total de nós explorados .......... = %d\n",totnodes); printf(".nó da melhor solucao inteira ..... = %d\n",NODE_BEST_INTEGER_SOL); printf(".valor da melhor solucao inteira .. = %d\n",(int)(zstar+0.5)); /* somar 0.5 evita erros de arredondamento */ /* verifica o valor do melhor_limitante_dual */ xpress_ret=XPRSgetdblattrib(prob,XPRS_BESTBOUND,&melhor_limitante_dual); if (xpress_ret) errormsg("Main: Erro na chamada de XPRSgetdblattrib.\n",__LINE__,xpress_ret); if (melhor_limitante_dual < zstar+EPSILON) melhor_limitante_dual=zstar; printf(".melhor limitante dual ............ = %.6f\n",melhor_limitante_dual); /* libera a memoria usada pelo problema */ /* xpress_ret=XPRSdestroyprob(prob); if (xpress_ret) errormsg("Main: Erro na liberacao da memoria usada pelo problema.\n",__LINE__,xpress_ret); */ /* libera toda memoria usada no programa */ if (qrtype) free(qrtype); if (mtype) free(mtype); if (drhs) free(drhs); if (mstart) free(mstart); if (mcols) free(mcols); if (dmatval) free(dmatval); if (x) free(x); if (xstar) free(xstar); xpress_ret=XPRSfree(); if (xpress_ret) errormsg("Main: Erro na liberacao de memoria final.\n",__LINE__,xpress_ret); printf("========================================\n"); return 0; }