Hide navigation sidebar
Hide table of contents sidebar
Back to top
Toggle table of contents sidebar

# diet.R

    # Copyright 2025, Gurobi Optimization, LLC
    #
    # Solve the classic diet model, showing how to add constraints
    # to an existing model.

    library(Matrix)
    library(gurobi)

    # display results
    printSolution <- function(model, res, nCategories, nFoods) {
      if (res$status == 'OPTIMAL') {
        cat('\nCost: ',res$objval,'\nBuy:\n')
        for (j in nCategories + 1:nFoods) {
          if (res$x[j] > 1e-4) {
            cat(format(model$varnames[j],justify='left',width=10),':',
                format(res$x[j],justify='right',width=10,nsmall=2),'\n')
          }
        }
        cat('\nNutrition:\n')
        for (j in 1:nCategories) {
          cat(format(model$varnames[j],justify='left',width=10),':',
              format(res$x[j],justify='right',width=10,nsmall=2),'\n')
        }
      } else {
        cat('No solution\n')
      }
    }

    # define primitive data
    Categories      <- c('calories', 'protein', 'fat', 'sodium')
    nCategories     <- length(Categories)
    minNutrition    <- c(     1800 ,       91 ,    0 ,       0 )
    maxNutrition    <- c(     2200 ,      Inf ,   65 ,    1779 )

    Foods           <- c('hamburger', 'chicken', 'hot dog', 'fries', 'macaroni',
                         'pizza', 'salad', 'milk', 'ice cream')
    nFoods          <- length(Foods)
    cost            <- c(2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59)
    nutritionValues <- c( 410, 24, 26 ,  730,
                          420, 32, 10 , 1190,
                          560, 20, 32 , 1800,
                          380,  4, 19 ,  270,
                          320, 12, 10 ,  930,
                          320, 15, 12 ,  820,
                          320, 31, 12 , 1230,
                          100,  8, 2.5,  125,
                          330,  8, 10 ,  180 )
    # Build model
    model     <- list()
    model$A   <- spMatrix(nCategories, nCategories + nFoods,
                   i = c(mapply(rep,1:4,1+nFoods)),
                   j = c(1, (nCategories+1):(nCategories+nFoods),
                         2, (nCategories+1):(nCategories+nFoods),
                         3, (nCategories+1):(nCategories+nFoods),
                         4, (nCategories+1):(nCategories+nFoods) ),
                   x = c(-1.0, nutritionValues[1 + nCategories*(0:(nFoods-1))],
                         -1.0, nutritionValues[2 + nCategories*(0:(nFoods-1))],
                         -1.0, nutritionValues[3 + nCategories*(0:(nFoods-1))],
                         -1.0, nutritionValues[4 + nCategories*(0:(nFoods-1))] ))
    model$obj         <- c(rep(0, nCategories), cost)
    model$lb          <- c(minNutrition, rep(0, nFoods))
    model$ub          <- c(maxNutrition, rep(Inf, nFoods))
    model$varnames    <- c(Categories, Foods)
    model$rhs         <- rep(0,nCategories)
    model$sense       <- rep('=',nCategories)
    model$constrnames <- Categories
    model$modelname   <- 'diet'
    model$modelsense  <- 'min'

    # Optimize
    res <- gurobi(model)
    printSolution(model, res, nCategories, nFoods)

    # Adding constraint: at most 6 servings of dairy
    # this is the matrix part of the constraint
    B <- spMatrix(1, nCategories + nFoods,
                  i = rep(1,2),
                  j = (nCategories+c(8,9)),
                  x = rep(1,2))
    # append B to A
    model$A           <- rbind(model$A,       B)
    # extend row-related vectors
    model$constrnames <- c(model$constrnames, 'limit_dairy')
    model$rhs         <- c(model$rhs,         6)
    model$sense       <- c(model$sense,       '<')

    # Optimize
    res <- gurobi(model)
    printSolution(model, res, nCategories, nFoods)

    # Clear space
    rm(res, model)

Help and Feedback

Press `/` or click to search this documentation | Gurobi website | Gurobi community forum
Go to other Gurobi documentation | Gurobi download | Contact support