Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-13, macos-latest]
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8"]

env:
Expand All @@ -34,7 +34,7 @@ jobs:
if: ${{ (matrix.os == 'macos-13') || (matrix.os == 'macos-latest') }}
- name: Build
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGENERALIZEDASSIGNMENTSOLVER_USE_CLP=ON
cmake --build build --config Release --parallel
cmake --install build --config Release --prefix install
- name: Run tests
Expand All @@ -46,7 +46,7 @@ jobs:
git checkout master
- name: Build
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGENERALIZEDASSIGNMENTSOLVER_USE_CLP=ON
cmake --build build --config Release --parallel
cmake --install build --config Release --prefix install
- name: Run tests
Expand Down
15 changes: 12 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
cmake_minimum_required(VERSION 3.15.0)
cmake_minimum_required(VERSION 3.28.0)

project(GeneralizedAssignmentSolver LANGUAGES CXX)

option(GENERALIZEDASSIGNMENTSOLVER_USE_CBC "Use CBC" ON)
# Build options.
option(GENERALIZEDASSIGNMENTSOLVER_BUILD_MAIN "Build main" ON)
option(GENERALIZEDASSIGNMENTSOLVER_BUILD_TEST "Build the unit tests" ON)

# Solver options.
option(GENERALIZEDASSIGNMENTSOLVER_USE_CLP "Use CLP" OFF)
option(GENERALIZEDASSIGNMENTSOLVER_USE_CBC "Use CBC" OFF)
option(GENERALIZEDASSIGNMENTSOLVER_USE_HIGHS "Use HIGHS" OFF)
option(GENERALIZEDASSIGNMENTSOLVER_USE_GUROBI "Use Gurobi" OFF)
option(GENERALIZEDASSIGNMENTSOLVER_USE_CPLEX "Use CPLEX" OFF)
option(GENERALIZEDASSIGNMENTSOLVER_USE_KNITRO "Use Knitro" OFF)
Expand All @@ -22,4 +29,6 @@ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Add sub-directories.
add_subdirectory(extern)
add_subdirectory(src)
add_subdirectory(test)
if(PACKINGSOLVER_BUILD_TEST)
add_subdirectory(test)
endif()
63 changes: 20 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

A solver for the generalized assignment problem.

This problem is interesting because many different optimization methods can and have been applied to solve it (Branch-and-cut, Branch-and-price, Branch-and-relax, Local search, Constraint programming, Column generation heuristics...). Thus, the main goal of this repository is for me to have reference implementations for classical algorithms and optimization solvers.

The variant handled here is the variant:
* with a minimization objective (items have costs)
* where all items have to be assigned
Expand All @@ -14,58 +12,37 @@ It is possible to solve the variant where not all items have to be assigned by a

## Implemented algorithms

### Lower bounds

- Linear relaxation
- solved with CLP `-a linrelax-clp`
- solved with Gurobi `-a "milp-gurobi --only-linear-relaxation"`
- solved with Cplex `-a "milp-cplex --only-linear-relaxation"`

- Lagrangian relaxation of knapsack constraints. The value of this relaxation is the same as the value of the linear relaxation. However, it might be cheaper to compute, especially on large instances.
- solved with volume method `-a lagrelax-knapsack-volume`
- solved with L-BFGS method `-a lagrelax-knapsack-lbfgs`

- Lagrangian relaxation of assignment constraints
- solved with volume method `-a lagrelax-assignment-volume`
- solved with L-BFGS method `-a lagrelax-assignment-lbfgs`

- Column generation `-a "column-generation --linear-programming-solver clp"` `-a "column-generation --linear-programming-solver cplex"`

### Upper bounds

- Polynomial algorithms from "Generalized Assignment Problems" (Martello et al., 1992), options `--desirability cij` `--desirability wij` `--desirability cij*wij` `--desirability -pij/wij` `--desirability wij/ti`:
- Basic greedy `-a "greedy --desirability wij"`
- Greedy with regret measure `-a "greedy-regret --desirability wij"`
- MTHG, basic greedy (+ n shifts) `-a "mthg --desirability wij"`
- MTHG, greedy with regret measure (+ n shifts) `-a "mthg-regret --desirability wij"`
- Basic greedy `--algorithm "greedy --desirability wij"`
- Greedy with regret measure `--algorithm "greedy-regret --desirability wij"`
- MTHG, basic greedy (+ n shifts) `--algorithm "mthg --desirability wij"`
- MTHG, greedy with regret measure (+ n shifts) `--algorithm "mthg-regret --desirability wij"`

- Local search algorithm implemented with [fontanf/localsearchsolver](https://github.com/fontanf/localsearchsolver) `-a "local-search --threads 3"`
- Mixed-Integer Linear Program `--algorithm milp --solver highs`

- Tree search algorithms based on the Dantzig-Wolfe reformulation branching scheme (i.e. column generation heuristics) implemented with [fontanf/columngenerationsolver](https://github.com/fontanf/columngenerationsolver):
- Greedy `-a "column-generation-heuristic-greedy --linear-programming-solver cplex"`
- Limited discrepency search `-a "column-generation-heuristic-limited-discrepancy-search --linear-programming-solver cplex"`
<!--- Constraint programming-->
<!-- - with Gecode `--algorithm constraint-programming-gecode`-->

- Others heuristics:
- Random feasible solution found with a Local search `-a random`
- Local search with LocalSolver `-a localsolver`
<!--- Lagrangian relaxation-->
<!-- - of knapsack constraints. The value of this relaxation is the same as the value of the linear relaxation. However, it might be cheaper to compute, especially on large instances.-->
<!-- - solved with volume method `--algorithm lagrangian-relaxation-knapsack-volume`-->
<!-- - solved with L-BFGS method `--algorithm lagrangian-relaxation-knapsack-lbfgs`-->
<!-- - of assignment constraints-->
<!-- - solved with volume method `--algorithm lagrangian-relaxation-assignment-volume`-->
<!-- - solved with L-BFGS method `--algorithm lagrangian-relaxation-assignment-lbfgs`-->

### Exact algorithms
- Local search algorithm implemented with [fontanf/localsearchsolver](https://github.com/fontanf/localsearchsolver) `--algorithm "local-search --threads 3"`

- Mixed-Integer Linear Programs
- with CBC `-a milp-cbc`
- with CPLEX `-a milp-cplex`
- with Gurobi `-a milp-gurobi`
- with Knitro `-a milp-knitro`

- Constraint programming
- with Gecode `-a constraint-programming-gecode`
- with CPLEX `-a constraint-programming-cplex`
- Tree search algorithms based on the Dantzig-Wolfe reformulation branching scheme (i.e. column generation heuristics) implemented with [fontanf/columngenerationsolver](https://github.com/fontanf/columngenerationsolver):
- Column generation `--algorithm column-generation --linear-programming-solver highs`
- Greedy `--algorithm column-generation-heuristic-greedy --linear-programming-solver highs`
- Limited discrepency search `--algorithm column-generation-heuristic-limited-discrepancy-search --linear-programming-solver highs`

## Usage (command line)

Compile:
```shell
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGENERALIZEDASSIGNMENTSOLVER_USE_HIGHS=ON
cmake --build build --config Release --parallel
cmake --install build --config Release --prefix install
```
Expand Down
17 changes: 13 additions & 4 deletions extern/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ FetchContent_MakeAvailable(Boost)
FetchContent_Declare(
optimizationtools
GIT_REPOSITORY https://github.com/fontanf/optimizationtools.git
GIT_TAG a0973a7dfa64b9d305f75879c80d252e714ce2cf
GIT_TAG e8c379203792fcad764cce239986b325619475fd
#SOURCE_DIR "${PROJECT_SOURCE_DIR}/../optimizationtools/"
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(optimizationtools)
Expand All @@ -24,28 +24,37 @@ FetchContent_MakeAvailable(optimizationtools)
if(GENERALIZEDASSIGNMENTSOLVER_USE_CBC)
set(MATHOPTSOLVERSCMAKE_USE_CBC ON)
endif()
if(GENERALIZEDASSIGNMENTSOLVER_USE_CLP)
set(MATHOPTSOLVERSCMAKE_USE_CLP ON)
endif()
if(GENERALIZEDASSIGNMENTSOLVER_USE_HIGHS)
set(MATHOPTSOLVERSCMAKE_USE_HIGHS ON)
endif()
if(GENERALIZEDASSIGNMENTSOLVER_USE_CPLEX)
set(MATHOPTSOLVERSCMAKE_USE_CPLEX ON)
endif()
FetchContent_Declare(
mathoptsolverscmake
GIT_REPOSITORY https://github.com/fontanf/mathoptsolverscmake.git
GIT_TAG 4472814a28a40f4d861ccd757e140835c3a31bd0
GIT_TAG f03fa63814eae3a253675ed14dd618a8a0d19a11
#SOURCE_DIR "${PROJECT_SOURCE_DIR}/../mathoptsolverscmake/"
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(mathoptsolverscmake)

# Fetch fontanf/columngenerationsolver.
if(GENERALIZEDASSIGNMENTSOLVER_USE_CBC)
if(GENERALIZEDASSIGNMENTSOLVER_USE_CLP)
set(COLUMNGENERATIONSOLVER_USE_CLP ON)
endif()
if(GENERALIZEDASSIGNMENTSOLVER_USE_HIGHS)
set(COLUMNGENERATIONSOLVER_USE_HIGHS ON)
endif()
if(GENERALIZEDASSIGNMENTSOLVER_USE_CPLEX)
set(COLUMNGENERATIONSOLVER_USE_CPLEX ON)
endif()
FetchContent_Declare(
columngenerationsolver
GIT_REPOSITORY https://github.com/fontanf/columngenerationsolver.git
GIT_TAG 17af477eb1ff576ce09b3d9a9c3369bdc7463c62
GIT_TAG 556971624c92c23c961371ce5721ff9eb920a874
#SOURCE_DIR "${PROJECT_SOURCE_DIR}/../columngenerationsolver/"
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(columngenerationsolver)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,19 @@

#include "generalizedassignmentsolver/solution.hpp"

#include <coin/OsiCbcSolverInterface.hpp>
#include "mathoptsolverscmake/milp.hpp"

namespace generalizedassignmentsolver
{

struct CoinLP
struct MilpParameters: Parameters
{
CoinLP(const Instance& instance);
/** Solver. */
mathoptsolverscmake::SolverName solver = mathoptsolverscmake::SolverName::Highs;

std::vector<double> column_lower_bounds;
std::vector<double> column_upper_bounds;
std::vector<double> objective;

std::vector<double> row_lower_bounds;
std::vector<double> row_upper_bounds;
CoinPackedMatrix matrix;
};

}

#include <coin/CbcModel.hpp>

namespace generalizedassignmentsolver
{

struct MilpCbcParameters: Parameters
{
/** Maximum number of nodes. */
Counter maximum_number_of_nodes = -1;

/** Stop at first improvement. */
bool stop_at_first_improvement = false;

/** Initial solution. */
const Solution* initial_solution = NULL;

Expand All @@ -47,7 +27,6 @@ struct MilpCbcParameters: Parameters
int width = format_width();
os
<< std::setw(width) << std::left << "Maximum number of nodes: " << maximum_number_of_nodes << std::endl
<< std::setw(width) << std::left << "Stop at first improvement: " << maximum_number_of_nodes << std::endl
<< std::setw(width) << std::left << "Has initial solution: " << (initial_solution != nullptr) << std::endl
;
}
Expand All @@ -57,16 +36,15 @@ struct MilpCbcParameters: Parameters
nlohmann::json json = Parameters::to_json();
json.merge_patch({
{"MaximumNumberOfNodes", maximum_number_of_nodes},
{"StopAtFirstImprovement", stop_at_first_improvement},
{"HasInitialSolution", (initial_solution != nullptr)},
});
return json;
}
};

struct MilpCbcOutput: Output
struct MilpOutput: Output
{
MilpCbcOutput(
MilpOutput(
const Instance& instance):
Output(instance) { }

Expand All @@ -93,8 +71,9 @@ struct MilpCbcOutput: Output
}
};

const MilpCbcOutput milp_cbc(
MilpOutput milp(
const Instance& instance,
const MilpCbcParameters& parameters = {});
const Solution* initial_solution = nullptr,
const MilpParameters& parameters = {});

}
33 changes: 0 additions & 33 deletions include/generalizedassignmentsolver/algorithms/milp_cplex.hpp

This file was deleted.

34 changes: 0 additions & 34 deletions include/generalizedassignmentsolver/algorithms/milp_gurobi.hpp

This file was deleted.

18 changes: 0 additions & 18 deletions include/generalizedassignmentsolver/algorithms/random.hpp

This file was deleted.

Loading
Loading