From 93910d7f63ad77660ef13cca337ce6db2da8586d Mon Sep 17 00:00:00 2001 From: Rafael Martinelli Date: Thu, 2 Oct 2025 16:13:09 -0300 Subject: [PATCH] Enable preview deployments for documentation --- .github/workflows/Documenter.yml | 7 +++- docs/make.jl | 4 ++ docs/src/index.md | 64 ++++++++++---------------------- docs/src/instances.md | 36 ++++++++++++++++++ docs/src/reference.md | 28 ++++++++++++++ src/AssignmentProblems.jl | 8 ++++ src/Data.jl | 28 ++++++++++++++ src/Enums.jl | 16 +++++++- src/Loader.jl | 17 +++++++++ src/Util.jl | 10 +++++ 10 files changed, 171 insertions(+), 47 deletions(-) create mode 100644 docs/src/instances.md create mode 100644 docs/src/reference.md diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index 0f47554..921ab58 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -12,8 +12,11 @@ jobs: name: Documentation runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - uses: julia-actions/setup-julia@v1 + with: + version: '1' - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-docdeploy@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/docs/make.jl b/docs/make.jl index ce6db23..4bc01af 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -15,9 +15,13 @@ makedocs(; ), pages=[ "Home" => "index.md", + "Instance catalogue" => "instances.md", + "API reference" => "reference.md", ], ) deploydocs(; repo="github.com/rafaelmartinelli/AssignmentProblems.jl", + devbranch="main", + push_preview=true, ) diff --git a/docs/src/index.md b/docs/src/index.md index bf58211..ab37f49 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -4,61 +4,37 @@ CurrentModule = AssignmentProblems # AssignmentProblems.jl -AssignmentProblems reads data files in `gap` format for Generalized Assignmnent Problem (GAP) instances. +AssignmentProblems.jl is a lightweight utility for loading Generalized +Assignment Problem (GAP) instances. It ships with the classical benchmark +library and can parse custom files that follow the OR-Library format. -## Usage +## Installation -The main type used by the package is `AssignmentProblem`, defined as follows: +AssignmentProblems is not yet registered. Install it directly from GitHub +using Julia's package manager: ```julia -struct AssignmentProblem - name::String # Instance name - - capacities::Vector{Int64} # Agents' capacities - costs::Matrix{Int64} # Assigments costs (agents x jobs) - consumptions::Matrix{Int64} # Assigments consumptions (agents x jobs) - - lb::Int64 # Lower bound (typemin(Int64) if not known) - ub::Int64 # Upper bound (typemax(Int64) if not known) -end +pkg> add https://github.com/rafaelmartinelli/AssignmentProblems.jl ``` -The package also defines the functions `na` and `nj` returning the number of agents and jobs, respectively. - -Some classical GAP instances from the literature are preloaded. For example, to load GAP instance `a05100`: +## Quick start ```julia -data = loadAssignmentProblem(:a05100) -``` +julia> using AssignmentProblems -There is a second optional parameter to set the objective function used (default `:Min` or `:Max`). This is only used to populate lb and ub fields. +julia> problem = loadAssignmentProblem(:a05100) +GAP Data a05100 (5 agents, 100 jobs) [-Inf, Inf] -See the [full instance list](https://github.com/rafaelmartinelli/AssignmentProblems.jl/tree/main/data). - -AssignmentProblems also loads custom GAP instances (following [ORLib format](http://people.brunel.ac.uk/~mastjjb/jeb/orlib/gapinfo.html)): - -```julia -data = loadAssignmentProblem("/path/to/your/GAP/instance.txt") +julia> (na(problem), nj(problem)) +(5, 100) ``` -## Installation +Supply a file path instead of a symbol to read external instances, and pass +`:Max` as the optional second argument to work with maximisation bounds. -AssignmentProblems is *not* yet a registered Julia Package. -You can install AssignmentProblems through the Julia package manager. -Open Julia's interactive session (REPL) and type: +## Next steps -```julia -] add https://github.com/rafaelmartinelli/AssignmentProblems.jl -``` - -## Related links - -- [Mutsunori Yagiura's GAP Page](http://www.al.cm.is.nagoya-u.ac.jp/~yagiura/gap/) -- [ORLib's GAP page](http://people.brunel.ac.uk/~mastjjb/jeb/orlib/gapinfo.html) - -```@index -``` - -```@autodocs -Modules = [AssignmentProblems] -``` +- Learn more about the bundled benchmarks in the [Instance catalogue](@ref + instance-catalogue). +- Browse the exported types and functions in the [API reference](@ref + reference). diff --git a/docs/src/instances.md b/docs/src/instances.md new file mode 100644 index 0000000..3a5018b --- /dev/null +++ b/docs/src/instances.md @@ -0,0 +1,36 @@ +```@meta +CurrentModule = AssignmentProblems +``` + +# Instance catalogue + +```@id instance-catalogue +``` + +The package bundles the classical Generalized Assignment Problem benchmarks as +ZIP archives under the `data/` directory. Each file is exposed through the +[`Instance`](@ref) enumeration, enabling programmatic discovery and loading. + +## Listing the available instances + +Use the `instances` helper from Julia's `Base.Enums` to iterate over every +identifier: + +```@example +using AssignmentProblems +collect(instances(Instance))[1:5] +``` + +The enumeration is grouped according to the original literature (families `a` +through `e`). The suffix hints at the problem size, e.g. `a05100` stands for an +instance with 5 agents and 100 jobs. + +## Loading data files + +Every enumerated value corresponds to a ZIP archive. When you call +[`loadAssignmentProblem`](@ref) with an `Instance` symbol, the archive is read +and converted into an [`AssignmentProblem`](@ref). + +To work with files outside of the bundled catalogue, pass a file path instead. +The loader accepts raw text files as well as single-entry ZIP archives that +follow the OR-Library specification. diff --git a/docs/src/reference.md b/docs/src/reference.md new file mode 100644 index 0000000..fcbdce4 --- /dev/null +++ b/docs/src/reference.md @@ -0,0 +1,28 @@ +```@meta +CurrentModule = AssignmentProblems +``` + +# API reference + +```@id reference +``` + +```@contents +Pages = ["reference.md"] +Depth = 2 +``` + +## Types +```@docs +AssignmentProblem +Instance +Objective +``` + +## Functions +```@docs +loadAssignmentProblem +na +nj +loadBounds +``` diff --git a/src/AssignmentProblems.jl b/src/AssignmentProblems.jl index df371ae..a7c675d 100644 --- a/src/AssignmentProblems.jl +++ b/src/AssignmentProblems.jl @@ -1,3 +1,11 @@ +""" + AssignmentProblems + +Utilities for reading benchmark instances of the Generalized Assignment +Problem (GAP). The module exports helpers to access the bundled data set +collection, parse custom files that follow the OR-Library GAP format, and +inspect the resulting `AssignmentProblem` structures. +""" module AssignmentProblems export AssignmentProblem, loadAssignmentProblem diff --git a/src/Data.jl b/src/Data.jl index 5baecdc..8e8d42c 100644 --- a/src/Data.jl +++ b/src/Data.jl @@ -1,3 +1,20 @@ +""" + AssignmentProblem + +Container for a Generalized Assignment Problem (GAP) instance. + +# Fields +- `name::String`: Identifier for the instance, usually matching the source + file name. +- `capacities::Vector{Int64}`: Capacity available for each agent. +- `costs::Matrix{Int64}`: Assignment costs arranged as agents × jobs. +- `consumptions::Matrix{Int64}`: Resource consumption for each + agent/job combination. +- `lb::Int64`: Known lower bound for the configured objective direction, or + `typemin(Int64)` if no bound is published. +- `ub::Int64`: Known upper bound for the configured objective direction, or + `typemax(Int64)` if no bound is published. +""" struct AssignmentProblem name::String @@ -9,7 +26,18 @@ struct AssignmentProblem ub::Int64 end +""" + na(problem::AssignmentProblem) -> Int + +Return the number of agents encoded in `problem`. +""" na(data::AssignmentProblem) = length(data.capacities) + +""" + nj(problem::AssignmentProblem) -> Int + +Return the number of jobs encoded in `problem`. +""" nj(data::AssignmentProblem) = size(data.costs, 2) function Base.show(io::IO, data::AssignmentProblem) diff --git a/src/Enums.jl b/src/Enums.jl index d7e6841..0abb03d 100644 --- a/src/Enums.jl +++ b/src/Enums.jl @@ -1,3 +1,10 @@ +""" + Instance + +Enumeration of the Generalized Assignment Problem instances bundled with the +package. The values correspond to ZIP files under the `data/` directory and +can be iterated with `instances(Instance)`. +""" @enum Instance begin a05100 a05200 @@ -118,7 +125,14 @@ e801600 end +""" + Objective + +Enumeration of the objective directions supported by +[`loadAssignmentProblem`](@ref). Use `:Min` for minimisation or `:Max` for +maximisation. +""" @enum Objective begin Min Max -end \ No newline at end of file +end diff --git a/src/Loader.jl b/src/Loader.jl index d3f1357..a31740e 100644 --- a/src/Loader.jl +++ b/src/Loader.jl @@ -1,3 +1,20 @@ +""" + loadAssignmentProblem(instance::Symbol, objective::Symbol = :Min) + loadAssignmentProblem(file_name::String, objective::Symbol = :Min) + +Load a GAP instance and return it as an [`AssignmentProblem`](@ref). + +- When `instance` is provided, the function searches for a bundled ZIP file + under the package `data/` directory. The symbol must match one of the + values defined by [`Instance`](@ref). +- When `file_name` is provided, the file is read from disk. Both plain text + inputs and single-entry ZIP archives following the OR-Library layout are + supported. + +The `objective` argument controls which pre-computed bounds are attached to +the resulting object. Use `:Min` for minimisation (default) or `:Max` for +maximisation. +""" function loadAssignmentProblem(instance::Symbol, objective::Symbol = :Min) file_name = joinpath(data_path, string(instance) * ".zip") if !isfile(file_name) diff --git a/src/Util.jl b/src/Util.jl index 8b9d735..26cb98b 100644 --- a/src/Util.jl +++ b/src/Util.jl @@ -1,3 +1,13 @@ +""" + loadBounds(name::String, objective::Symbol) -> Tuple{Int64, Int64} + +Return the published lower and upper bounds associated with `name` for the +given objective direction. + +Bounds are loaded from `data/bounds.txt`, which stores entries as +`_ `. If no entry is found, the tuple +`(typemin(Int64), typemax(Int64))` is returned. +""" function loadBounds(name::String, objective::Symbol) file_name = joinpath(data_path, "bounds.txt") values = split(read(file_name, String))