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);
    }
Example #2
0
/* ============================ */
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;
}