Specify the software and configuration used to solve a project prioritization problem(). By default, the best available exact algorithm solver will be used.

Details

The following solvers can be used to find solutions for a project prioritization problem():

add_default_solver()

This solver uses the best software currently installed on the system.

add_gurobi_solver()

Gurobi is a state-of-the-art commercial optimization software with an R package interface. It is by far the fastest solver that can be used by this package, however, it is also the only solver that is not freely available. That said, licenses are available to academics at no cost. The gurobi package is distributed with the Gurobi software suite. This solver uses the gurobi package to solve problems.

add_rsymphony_solver()

SYMPHONY is an open-source integer programming solver that is part of the Computational Infrastructure for Operations Research (COIN-OR) project, an initiative to promote development of open-source tools for operations research (a field that includes linear programming). The Rsymphony package provides an interface to COIN-OR and is available on CRAN. This solver uses the Rsymphony package to solve problems.

add_lpsymphony_solver()

The lpsymphony package provides a different interface to the COIN-OR software suite. Unlike the Rsymhpony package, the lpsymphony package is distributed through Bioconductor. The lpsymphony package may be easier to install on Windows or Max OSX systems than the Rsymphony package.

add_lpsolveapi_solver()

lp_solve is an open-source integer programming solver. The lpSolveAPI package provides an interface to this solver and is available on CRAN. Although this solver is the slowest currently supported solver, it is also the only exact algorithm solver that can be installed on all operating systems without any manual installation steps.

add_heuristic_solver()

Generate solutions using a backwards heuristic algorithm. Although these types of algorithms have conventionally been used to solve project prioritization problems, they are extremely unlikely to identify optimal solutions and provide no guarantees concerning solution quality.

add_random_solver()

Generate solutions by randomly funding actions. This can be useful when evaluating the performance of a funding scheme---though it is strongly recommended to evaluate the performance of a funding scheme by comparing it to an optimal solution identified using exact algorithms (e.g. add_gurobi_solver(), add_rsymphony_solver()).

Examples

# load data
data(sim_projects, sim_features, sim_actions)

# build problem
p1 <- problem(sim_projects, sim_actions, sim_features,
             "name", "success", "name", "cost", "name") %>%
     add_max_richness_objective(budget = 200) %>%
     add_binary_decisions()

# build another problem, with the default solver
p2 <- p1 %>%
      add_default_solver()

# build another problem, with the gurobi solver
# \dontrun{
p3 <- p1 %>%
      add_gurobi_solver()
# }

# build another problem, with the Rsympony solver
# \dontrun{
p4 <- p1 %>%
      add_rsymphony_solver()
# }

# build another problem, with the lpsymphony solver
# \dontrun{
p5 <- p1 %>%
      add_lpsymphony_solver()
# }

# build another problem, with the lpSolveAPI solver
p6 <- p1 %>%
      add_lpsolveapi_solver()

# build another problem, with the heuristic solver
p7 <- p1 %>%
      add_heuristic_solver()

# build another problem, with the random solver
p8 <- p1 %>%
      add_random_solver()

# \dontrun{
# generate solutions using each of the solvers
s <- rbind(solve(p2), solve(p3), solve(p4), solve(p5), solve(p6), solve(p7),
           solve(p8))
#> Gurobi Optimizer version 9.5.2 build v9.5.2rc0 (linux64)
#> Thread count: 4 physical cores, 8 logical processors, using up to 1 threads
#> Optimize a model with 47 rows, 47 columns and 102 nonzeros
#> Model fingerprint: 0x193cb636
#> Variable types: 0 continuous, 42 integer (42 binary)
#> Semi-Variable types: 5 continuous, 0 integer
#> Coefficient statistics:
#>   Matrix range     [9e-02, 1e+02]
#>   Objective range  [1e+00, 1e+00]
#>   Bounds range     [1e+00, 1e+00]
#>   RHS range        [1e+00, 2e+02]
#> Found heuristic solution: objective 1.4456093
#> Presolve removed 16 rows and 12 columns
#> Presolve time: 0.00s
#> Presolved: 31 rows, 35 columns, 65 nonzeros
#> Variable types: 0 continuous, 35 integer (35 binary)
#> Root relaxation presolved: 31 rows, 35 columns, 65 nonzeros
#> 
#> 
#> Root relaxation: objective 2.190381e+00, 11 iterations, 0.00 seconds (0.00 work units)
#> 
#>     Nodes    |    Current Node    |     Objective Bounds      |     Work
#>  Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time
#> 
#> *    0     0               0       2.1903807    2.19038  0.00%     -    0s
#> 
#> Explored 1 nodes (11 simplex iterations) in 0.00 seconds (0.00 work units)
#> Thread count was 1 (of 8 available processors)
#> 
#> Solution count 1: 2.19038 
#> 
#> Optimal solution found (tolerance 0.00e+00)
#> Best objective 2.190380737245e+00, best bound 2.190380737245e+00, gap 0.0000%
#> Gurobi Optimizer version 9.5.2 build v9.5.2rc0 (linux64)
#> Thread count: 4 physical cores, 8 logical processors, using up to 1 threads
#> Optimize a model with 47 rows, 47 columns and 102 nonzeros
#> Model fingerprint: 0x193cb636
#> Variable types: 0 continuous, 42 integer (42 binary)
#> Semi-Variable types: 5 continuous, 0 integer
#> Coefficient statistics:
#>   Matrix range     [9e-02, 1e+02]
#>   Objective range  [1e+00, 1e+00]
#>   Bounds range     [1e+00, 1e+00]
#>   RHS range        [1e+00, 2e+02]
#> Found heuristic solution: objective 1.4456093
#> Presolve removed 16 rows and 12 columns
#> Presolve time: 0.00s
#> Presolved: 31 rows, 35 columns, 65 nonzeros
#> Variable types: 0 continuous, 35 integer (35 binary)
#> Root relaxation presolved: 31 rows, 35 columns, 65 nonzeros
#> 
#> 
#> Root relaxation: objective 2.190381e+00, 11 iterations, 0.00 seconds (0.00 work units)
#> 
#>     Nodes    |    Current Node    |     Objective Bounds      |     Work
#>  Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time
#> 
#> *    0     0               0       2.1903807    2.19038  0.00%     -    0s
#> 
#> Explored 1 nodes (11 simplex iterations) in 0.00 seconds (0.00 work units)
#> Thread count was 1 (of 8 available processors)
#> 
#> Solution count 1: 2.19038 
#> 
#> Optimal solution found (tolerance 0.00e+00)
#> Best objective 2.190380737245e+00, best bound 2.190380737245e+00, gap 0.0000%
#> 
#> Model name:  'project prioritization problem' - run #1    
#> Objective:   Maximize(R0)
#>  
#> SUBMITTED
#> Model size:       47 constraints,      47 variables,          102 non-zeros.
#> Sets:                                   0 GUB,                  0 SOS.
#>  
#> Using DUAL simplex for phase 1 and PRIMAL simplex for phase 2.
#> The primal and dual simplex pricing strategy set to 'Devex'.
#>  
#> 
#> Relaxed solution       2.21077983146 after         34 iter is B&B base.
#>  
#> Feasible solution      1.91490153549 after         43 iter,         8 nodes (gap 9.2%)
#> Improved solution       2.0146497578 after         47 iter,        11 nodes (gap 6.1%)
#> Improved solution      2.19038073724 after         59 iter,        20 nodes (gap 0.6%)
#>  
#> Optimal solution       2.19038073724 after         59 iter,        20 nodes (gap 0.6%).
#> 
#> Excellent numeric accuracy ||*|| = 1.11022e-16
#> 
#>  MEMO: lp_solve version 5.5.2.0 for 64 bit OS, with 64 bit LPSREAL variables.
#>       In the total iteration count 59, 16 (27.1%) were bound flips.
#>       There were 11 refactorizations, 0 triggered by time and 1 by density.
#>        ... on average 3.9 major pivots per refactorization.
#>       The largest [LUSOL v2.2.1.0] fact(B) had 104 NZ entries, 1.0x largest basis.
#>       The maximum B&B level was 6, 0.1x MIP order, 4 at the optimal solution.
#>       The constraint matrix inf-norm is 103.226, with a dynamic range of 1193.9.
#>       Time to load data was 0.000 seconds, presolve used 0.000 seconds,
#>        ... 0.000 seconds in simplex solver, in total 0.000 seconds.
s$solver <- c("default", "gurobi", "Rsymphony", "lpsymphony", "lpSolveAPI",
              "heuristic", "random")

# print solutions
print(as.data.frame(s))
#>   solution                    status      obj     cost F1_action F2_action
#> 1        1                   OPTIMAL 2.190381 195.3907         1         1
#> 2        1                   OPTIMAL 2.190381 195.3907         1         1
#> 3        1 TM_OPTIMAL_SOLUTION_FOUND 2.190381 195.3907         1         1
#> 4        1 TM_OPTIMAL_SOLUTION_FOUND 2.190381 195.3907         1         1
#> 5        1    optimal solution found 2.190381 195.3907         1         1
#> 6        1                      <NA> 2.190381 195.3907         1         1
#> 7        1                      <NA> 2.190381 195.3907         1         1
#>   F3_action F4_action F5_action baseline_action F1_project F2_project
#> 1         0         0         0               1          1          1
#> 2         0         0         0               1          1          1
#> 3         0         0         0               1          1          1
#> 4         0         0         0               1          1          1
#> 5         0         0         0               1          1          1
#> 6         0         0         0               1          1          1
#> 7         0         0         0               1          1          1
#>   F3_project F4_project F5_project baseline_project        F1        F2
#> 1          0          0          0                1 0.8080322 0.8649623
#> 2          0          0          0                1 0.8080322 0.8649623
#> 3          0          0          0                1 0.8080322 0.8649623
#> 4          0          0          0                1 0.8080322 0.8649623
#> 5          0          0          0                1 0.8080322 0.8649623
#> 6          0          0          0                1 0.8080322 0.8649623
#> 7          0          0          0                1 0.8080322 0.8649623
#>          F3        F4        F5     solver
#> 1 0.0864612 0.2489246 0.1820005    default
#> 2 0.0864612 0.2489246 0.1820005     gurobi
#> 3 0.0864612 0.2489246 0.1820005  Rsymphony
#> 4 0.0864612 0.2489246 0.1820005 lpsymphony
#> 5 0.0864612 0.2489246 0.1820005 lpSolveAPI
#> 6 0.0864612 0.2489246 0.1820005  heuristic
#> 7 0.0864612 0.2489246 0.1820005     random
# }