batchmode_c.c


/* Copyright 2024, Gurobi Optimization, LLC */

/* This example reads a MIP model from a file, solves it in batch mode,
 * and prints the JSON solution string. */

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#if defined (WIN32) || defined (WIN64)
#include <Windows.h>
#define sleep(n) Sleep(1000*n)
#else
#include <unistd.h>
#endif
#include "gurobi_c.h"

/* setup gurobi environment */
int setupbatchconnection(GRBenv **envP)
{
  int     error = 0;
  GRBenv *env   = NULL;

  /* setup a batch environment */
  error = GRBemptyenv(envP);
  if (error) goto QUIT;
  env = *envP;
  error = GRBsetintparam(env, "CSBatchMode", 1);
  if (error) goto QUIT;
  error = GRBsetstrparam(env, "LogFile", "batchmode.log");
  if (error) goto QUIT;
  error = GRBsetstrparam(env, "CSManager", "http://localhost:61080");
  if (error) goto QUIT;
  error = GRBsetstrparam(env, "UserName", "gurobi");
  if (error) goto QUIT;
  error = GRBsetstrparam(env, "ServerPassword", "pass");
  if (error) goto QUIT;
  error = GRBstartenv(env);
  if (error) goto QUIT;

QUIT:

  if (error) {
    printf("Failed to setup environment, error code %d\n", error);
  } else {
    printf("Successfully created environment\n");
  }
  return error;
}

/* display batch-error code if any */
void batcherrorinfo(GRBbatch *batch)
{
  int error = 0;
  int errorCode;
  char *errorMsg;
  char *BatchID;

  if (!batch) goto QUIT;

  /* query the last error code */
  error = GRBgetbatchintattr(batch, "BatchErrorCode", &errorCode);
  if (error || !errorCode) goto QUIT;

  /* query the last error message */
  error = GRBgetbatchstrattr(batch, "BatchErrorMessage", &errorMsg);
  if (error) goto QUIT;

  error = GRBgetbatchstrattr(batch, "BatchID", &BatchID);
  if (error) goto QUIT;

  printf("Batch ID %s Error Code %d (%s)\n", BatchID, errorCode, errorMsg);

QUIT:

  return;
}

/* create a batch request for given problem file */
int newbatchrequest(const char *filename,
		    char       *BatchID)
{
  int       error = 0;
  GRBenv   *env   = NULL;
  GRBenv   *menv  = NULL;
  GRBmodel *model = NULL;
  char tag[128];
  int cols, j;

  /* setup a batch connection */
  error = setupbatchconnection(&env);
  if (error) goto QUIT;

  /* read a model */
  error = GRBreadmodel(env, filename, &model);
  if (error) goto QUIT;

  /* set some params */
  menv = GRBgetenv(model);
  error = GRBsetdblparam(menv, "MIPGap", 0.01);
  if (error) goto QUIT;
  /* for extra detailed information on JSON solution string */
  error = GRBsetintparam(menv, "JSONSolDetail", 1);
  if (error) goto QUIT;

  /* setup some tags, we need tags to be able to query results later on */
  error = GRBgetintattr(model, "NumVars", &cols);
  if (error) goto QUIT;

  if (cols > 10) cols = 10;
  for (j = 0; j < cols; j++) {
    sprintf(tag, "MyUniqueVariableID%d",j);
    error = GRBsetstrattrelement(model, "VTag", j, tag);
  }

  /* submit batch request to the Manager */
  error = GRBoptimizebatch(model, BatchID);
  if (error) goto QUIT;

QUIT:

  if (error) {
    printf("Failed to submit a new batch request, error code %d\n", error);
  } else {
    printf("Successfully submitted new batch request %s\n", BatchID);
  }
  GRBfreemodel(model);
  GRBfreeenv(env);
  return error;
}

/* wait for final bstatus */
int waitforfinalstatus(const char *BatchID)
{
  int       error = 0;
  GRBenv   *env   = NULL;
  GRBbatch *batch = NULL;
  time_t start, current;
  int bstatus;

  /* setup a batch connection */
  error = setupbatchconnection(&env);
  if (error) goto QUIT;

  /* create batch-object */
  error = GRBgetbatch(env, BatchID, &batch);
  if (error) goto QUIT;

  /* query bstatus, and wait for completed */
  error = GRBgetbatchintattr(batch, "BatchStatus",  &bstatus);
  if (error) goto QUIT;
  start = time(NULL);

  while (bstatus == GRB_BATCH_SUBMITTED) {

    /* abort if taking too long */
    current = time(NULL);
    if (current - start >= 3600) {
      /* request to abort the batch */
      error = GRBabortbatch(batch);
      if (error) goto QUIT;
    }

    /* do not bombard the server */
    sleep(1u);

    /* update local attributes */
    error = GRBupdatebatch(batch);
    if (error) goto QUIT;

    /* query bstatus */
    error = GRBgetbatchintattr(batch, "BatchStatus",  &bstatus);
    if (error) goto QUIT;

    /* deal with failed bstatus */
    if (bstatus == GRB_BATCH_FAILED) {
      /* retry the batch request */
      error = GRBretrybatch(batch);
      if (error) goto QUIT;
      bstatus = GRB_BATCH_SUBMITTED;
    }
  }


QUIT:

  if (error) {
    printf("Failed to wait for final bstatus, error code %d\n", error);
  } else {
    printf("Final Batch Status %d\n", bstatus);
  }
  batcherrorinfo(batch);
  /* release local resources */
  GRBfreebatch(batch);
  GRBfreeenv(env);
  return error;
}

/* final report on batch request */
int finalreport(const char *BatchID)
{
  int       error   = 0;
  GRBenv   *env     = NULL;
  GRBbatch *batch   = NULL;
  char     *jsonsol = NULL;
  int bstatus;

  /* setup a batch connection */
  error = setupbatchconnection(&env);
  if (error) goto QUIT;

  /* create batch object */
  error = GRBgetbatch(env, BatchID, &batch);
  if (error) goto QUIT;

  /* query bstatus, and wait for completed */
  error = GRBgetbatchintattr(batch, "BatchStatus",  &bstatus);
  if (error) goto QUIT;

  /* display depending on batch bstatus */
  switch (bstatus) {
    case GRB_BATCH_CREATED:
      printf("Batch is 'CREATED'\n");
      printf("maybe batch-creation process was killed?\n");
      break;
    case GRB_BATCH_SUBMITTED:
      printf("Batch is 'SUBMITTED'\n");
      printf("Some other user re-submitted this Batch object?\n");
      break;
    case GRB_BATCH_ABORTED:
      printf("Batch is 'ABORTED'\n");
      break;
    case GRB_BATCH_FAILED:
      printf("Batch is 'FAILED'\n");
      break;
    case GRB_BATCH_COMPLETED:

      /* print JSON solution into string */
      error = GRBgetbatchjsonsolution(batch, &jsonsol);
      if (error) goto QUIT;
      printf("JSON solution: %s\n", jsonsol);

      /* save solution into a file */
      error = GRBwritebatchjsonsolution(batch, "batch-sol.json.gz");
      if (error) goto QUIT;
      break;
    default:
      printf("This should not happen, probably points to a"
             " user-memory corruption problem\n");
      exit(EXIT_FAILURE);
      break;
  }

QUIT:

  if (error) {
    printf("Failed to perform final report, error code %d\n", error);
  } else {
    printf("Reporting done\n");
  }
  batcherrorinfo(batch);

  if (jsonsol)
    GRBfree(jsonsol);

  GRBfreebatch(batch);
  GRBfreeenv(env);
  return error;
}

/* remove batch ID from manager */
int discardbatch(const char *BatchID)
{
  int       error   = 0;
  GRBenv   *env     = NULL;
  GRBbatch *batch   = NULL;

  /* setup a batch connection */
  error = setupbatchconnection(&env);
  if (error) goto QUIT;

  /* create batch object */
  error = GRBgetbatch(env, BatchID, &batch);
  if (error) goto QUIT;

  /* discard the batch object in the manager */
  error = GRBdiscardbatch(batch);
  if (error) goto QUIT;

QUIT:

  batcherrorinfo(batch);
  GRBfreebatch(batch);
  GRBfreeenv(env);
  return error;
}

int
main(int    argc,
     char **argv)
{
  int error = 0;
  char BatchID[GRB_MAX_STRLEN+1];

  /* ensure enough parameters */
  if (argc < 2) {
    fprintf(stderr, "Usage: %s filename\n", argv[0]);
    goto QUIT;
  }

  /* create a new batch request */
  error = newbatchrequest(argv[1], BatchID);
  if (error) goto QUIT;

  /* wait for final bstatus */
  error = waitforfinalstatus(BatchID);
  if (error) goto QUIT;

  /* query final bstatus, and if completed, print JSON solution */
  error = finalreport(BatchID);
  if (error) goto QUIT;

  /* eliminate batch from the manager */
  error = discardbatch(BatchID);
  if (error) goto QUIT;

QUIT:

  return error;
}

Try Gurobi for Free

Choose the evaluation license that fits you best, and start working with our Expert Team for technical guidance and support.

Evaluation License
Get a free, full-featured license of the Gurobi Optimizer to experience the performance, support, benchmarking and tuning services we provide as part of our product offering.
Academic License
Gurobi supports the teaching and use of optimization within academic institutions. We offer free, full-featured copies of Gurobi for use in class, and for research.
Cloud Trial

Request free trial hours, so you can see how quickly and easily a model can be solved on the cloud.

Search