ap

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 18, 2024 License: Apache-2.0 Imports: 1 Imported by: 1

README

ap: assignment problem solvers for go

This package provides interfaces and data structures common to formulating and solving assignment problems, as well as codes for solving particular variants. More details about these can be found in:

Rainer Burkard, Mauro Dell'Amico, and Silvano Martello.
"Assignment Problems - Revised Reprint."
Society for Industrial and Applied Mathematics (2012).

At this time, ap only provides an incremental code to solve the Linear Sum Assignment Problem. Additional forms are planned for future milestones.

LSAPs take the following form:

min   ∑_i,j c_ij * x_ij
s.t.  ∑_i   x_ij = 1      ∀ j
      ∑_j   x_ij = 1      ∀ i
            x_ij ∈ {0,1}  ∀ i,j

Quick Start: CLI

To solve LSAPs from the command line, first install the lsap binary using Go.

go install github.com/ryanjoneil/ap/cmd/lsap

lsap reads JSON input data in the form of a square cost matrix from standard input and writes an optimal permutation and cost to standard output.

cat <<EOF | lsap | jq
[
    [  90,  76,  75,  70 ],
    [  35,  85,  55,  65 ],
    [ 125,  95,  90, 105 ],
    [  45, 110,  95, 115 ]
]
EOF
{
  "assignment": [
    3,
    2,
    1,
    0
  ],
  "cost": 265
}

Quick Start: Packages

Examples are available in the package docs.

ap: assignment representations & interfaces

Package ap provides solution representations and interfaces for working with assignment problems and solvers.

go get github.com/ryanjoneil/ap

The default representation of an assignment produced by an Assigner is a Permutation.

a := SomeAssigner{} // implements ap.Assign
p := a.Assign()     // p is an ap.Permutation

Permutations can be converted to cyclic and matrix representations of assignments, and vice versa. All representations provide Inverse methods reverse the direction of assignment.

p := ap.Permutation{1, 0, 2, 6, 5, 3, 4}
p.Cycles()  // {{0, 1}, {2}, {3, 6, 4, 5}}
p.Inverse() // {1, 0, 2, 5, 6, 4, 3}
p.Matrix()  // p[u] == v -> m[u][v] == true
ap/lsap: linear sum assignment problem solver

Package ap/lsap provides a efficient, iterative implementation of a primal-dual linear sum assignment problem solver.

go get github.com/ryanjoneil/ap/lsap

LSAPs are easy to construct and solve from a cost matrix.

a := lsap.New([][]int64{
    {10, 15, 12},
    {51, 75, 23},
    {11, 91, 10},
})

permutation := a.Assign() // [1 2 0]
cost := a.Cost()          // 49

lsap provides command line flags for outputting dual prices and reduced costs.

lsap -h
lsap solves linear sum assignment problems, given a square cost matrix
Usage:
        lsap < input.json -dual -rc > output.json
        cat <<EOF | lsap | jq
        [
                [  90,  76,  75,  70 ],
                [  35,  85,  55,  65 ],
                [ 125,  95,  90, 105 ],
                [  45, 110,  95, 115 ]
        ]
        EOF
Flags:
        -cycles
                output cyclic assignment form
        -dual
                output dual prices
        -matrix
                output matrix assignment form
        -rc
                output reduced cost matrix

Documentation

Overview

Package ap defines interfaces and data structures common to formulating and solving assignment problems. More details about these can be found in:

Rainer Burkard, Mauro Dell'Amico, and Silvano Martello.
"Assignment Problems - Revised Reprint."
Society for Industrial and Applied Mathematics (2012).

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func MaxOf added in v0.3.0

func MaxOf[T Integer]() T

MaxOf returns the maximum value of any signed integer type.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	i := ap.MaxOf[int64]()
	fmt.Println(i)
}
Output:

9223372036854775807

func MinOf added in v0.3.0

func MinOf[T Integer]() T

MinOf returns the minimum value of any signed integer type.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	i := ap.MinOf[int64]()
	fmt.Println(i)
}
Output:

-9223372036854775808

Types

type Assigner

type Assigner interface {
	Assign() Permutation
}

An Assigner creates a mapping between two sets U = V = {0, ..., n-1}.

type Coster added in v0.3.0

type Coster[T Integer] interface {
	Cost() T
}

A Coster provides an Integer cost value. This is usually the objective of value of a particular assignment.

type Cycle added in v0.3.0

type Cycle []int

A Cycle is an individual cycle in an assignment, such as [1 2 4]. The cycle is assumed to contain an arc from the final element to the initial element, so this cycle has the arcs (1 2), (2 4) and (4 1). A cycle can contain a a single element with an arc to itself, such as [3].

type Cycles added in v0.3.0

type Cycles []Cycle

Cycles represents multiple individual cycle structures corresponding to an assignment. For example, the permutation [1 0 2 6 5 3 4] is equivalent to the set of cycles [[0 1] [2] [3 6 4 5]]. If a permutation corresponds to a single cycle, then that cycle is a Hamiltonian cycle.

func (Cycles) Inverse added in v0.3.0

func (c Cycles) Inverse() Cycles

Inverse changes the direction of a set of cycles representing an assignment.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	c := ap.Cycles{{0, 1}, {2}, {3, 6, 4, 5}}
	fmt.Println(c.Inverse())
}
Output:

[[0 1] [2] [3 5 4 6]]

func (Cycles) Matrix added in v0.3.0

func (c Cycles) Matrix() Matrix

Matrix converts a cyclic representation of an assignment into a permutation matrix.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	c := ap.Cycles{{0, 1}, {2}, {3, 6, 4, 5}}
	for _, row := range c.Matrix() {
		fmt.Println(row)
	}
}
Output:

[false true false false false false false]
[true false false false false false false]
[false false true false false false false]
[false false false false false false true]
[false false false false false true false]
[false false false true false false false]
[false false false false true false false]

func (Cycles) Permutation added in v0.3.0

func (c Cycles) Permutation() Permutation

Permutation converts a cyclic representation of an assignment into a permutation representation.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	c := ap.Cycles{{0, 1}, {2}, {3, 6, 4, 5}}
	fmt.Println(c.Permutation())
}
Output:

[1 0 2 6 5 3 4]

type DualPricer added in v0.3.0

type DualPricer[T Integer] interface {
	DualPrices() DualPrices[T]
}

A DualPricer provides dual prices on the assignment constraints associated with sets U and V. A dual price is the value of a unit of slack on a binding constraint.

type DualPrices added in v0.3.0

type DualPrices[T Integer] struct {
	U []T `json:"u"`
	V []T `json:"v"`
}

DualPrices are dual prices for the assignment constraints corresponding to the U and V sets, respectively.

type Integer added in v0.3.0

type Integer interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64
}

Integer is any native signed int type.

type Matrix

type Matrix [][]bool

Matrix representation of an assignment. If u is assigned to v, then M[u][v] is true. Each row and each column has exactly one true element.

func (Matrix) Cycles added in v0.3.0

func (m Matrix) Cycles() Cycles

Cycles converts a permutation matrix to a cyclic representation.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	m := ap.Matrix{
		[]bool{true, false, false, false, false},
		[]bool{false, false, false, false, true},
		[]bool{false, false, false, true, false},
		[]bool{false, true, false, false, false},
		[]bool{false, false, true, false, false},
	}
	fmt.Println(m.Cycles())
}
Output:

[[0] [1 4 2 3]]

func (Matrix) Inverse added in v0.3.0

func (m Matrix) Inverse() Matrix

Inverse inverts a permutation matrix, changing its direction.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	m := ap.Matrix{
		[]bool{true, false, false, false, false},
		[]bool{false, false, false, false, true},
		[]bool{false, false, false, true, false},
		[]bool{false, true, false, false, false},
		[]bool{false, false, true, false, false},
	}
	for _, row := range m.Inverse() {
		fmt.Println(row)
	}
}
Output:

[true false false false false]
[false false false true false]
[false false false false true]
[false false true false false]
[false true false false false]

func (Matrix) Permutation added in v0.3.0

func (m Matrix) Permutation() Permutation

Permutation converts a matrix assignment representation into a permutation.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	m := ap.Matrix{
		[]bool{true, false, false, false, false},
		[]bool{false, false, false, false, true},
		[]bool{false, false, false, true, false},
		[]bool{false, true, false, false, false},
		[]bool{false, false, true, false, false},
	}
	fmt.Println(m.Permutation())
}
Output:

[0 4 3 1 2]

type Permutation added in v0.3.0

type Permutation []int

A Permutation P maps elements from one set U = {0,...,n-1} to another set V = {0,...,n-1}, where P[u] = v means that u ∈ U is assigned to v ∈ V.

p := ap.Permutation{1, 0, 2} // Assign 0 to 1, 1 to 0, and 2 to itself.

func (Permutation) Cycles added in v0.3.0

func (p Permutation) Cycles() Cycles

Cycles convert a permutation representation of an assignment to a cyclical representation of that assignment. If the result contains a single cycle, then that cycle is a Hamiltonian cycle.

p := ap.Permutation{1, 0, 2, 6, 5, 3, 4}
p.Cycles() // {{0, 1}, {2}, {3, 6, 4, 5}}
Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	p := ap.Permutation{1, 0, 2, 6, 5, 3, 4}
	fmt.Println(p.Cycles())

}
Output:

[[0 1] [2] [3 6 4 5]]

func (Permutation) Inverse added in v0.3.0

func (p Permutation) Inverse() Permutation

Inverse converts an assignment from a set U to a set V to an assignment from V to U. If, for example, U is the left hand side of a bipartite matching and V is the right hand side, this function essentially swaps their sides.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	p := ap.Permutation{1, 0, 2, 6, 5, 3, 4}
	fmt.Println(p.Inverse())
}
Output:

[1 0 2 5 6 4 3]

func (Permutation) Matrix added in v0.3.0

func (p Permutation) Matrix() Matrix

Matrix converts a permutation into a square matrix.

Example
package main

import (
	"fmt"

	"github.com/ryanjoneil/ap"
)

func main() {
	p := ap.Permutation{1, 0, 2, 6, 5, 3, 4}
	for _, row := range p.Matrix() {
		fmt.Println(row)
	}
}
Output:

[false true false false false false false]
[true false false false false false false]
[false false true false false false false]
[false false false false false false true]
[false false false false false true false]
[false false false true false false false]
[false false false false true false false]

type ReducedCoster added in v0.3.0

type ReducedCoster[T Integer] interface {
	ReducedCost(u, v int) T
}

A ReducedCoster provides a method for computing the reduced cost of assigning u ∈ U to v ∈ V, where u and v are both integers from 0 to n-1. The reduced cost of a basic edge (already part of an assignment) is zero, since it does not change the solution. Introducing a nonbasic edge (not in the assignment) may change the resulting assignment's overall cost.

Directories

Path Synopsis
cmd
lsap command
Package lsap solves linear sum assignment problems.
Package lsap solves linear sum assignment problems.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL