-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathclp.go
124 lines (106 loc) · 4.4 KB
/
clp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
Package clp provides an interface to the COIN-OR Linear Programming (CLP)
library. As the name implies, CLP is a solver for linear-programming problems:
CLP is a high quality open-source LP solver. Its main strengths are its
Dual and Primal Simplex algorithms. It also has a barrier algorithm for
Linear and Quadratic objectives. There are limited facilities for Nonlinear
and Quadratic objectives using the Simplex algorithm. It is available as a
library and as a standalone solver. It was written by John Forrest, jjforre
at us.ibm.com
Linear programming is an optimization technique. Given an objective function,
such as a + b, and a set of constraints in the form of linear inequalities,
such as 0 ≤ 2a + b ≤ 10 and 3 ≤ 2b − a ≤ 8, find values for the variables that
maximizes or minimizes the objective function. In this example, the maximum
value of a + b is 7.6, which is achieved when a = 2.4 and b = 5.2. The example
code associated with Simplex.LoadProblem shows how to set up and solve this
precise problem using an API based directly on CLP's C++ API. The example code
associated with Simplex.EasyLoadDenseProblem shows how to specify the same
problem using a more equation-oriented API specific to the clp package.
The clp package currently exposes only a tiny subset of the CLP library.
Relevant URLs:
• COIN-OR (COmputational INfrastructure for Operations Research): http://www.coin-or.org/
• LP (Linear Programming): https://en.wikipedia.org/wiki/Linear_programming
• CLP (COIN-OR Linear Programming): http://www.coin-or.org/projects/Clp.xml
*/
package clp
// #cgo pkg-config: clp
// #include <stdlib.h>
import "C"
import (
"reflect"
"unsafe"
)
// A Nonzero represents an element in a sparse row or column.
type Nonzero struct {
Index int // Zero-based element offset
Value float64 // Value at that offset
}
// A Matrix sparsely represents a set of linear expressions. Each column
// represents a variable, each row represents an expression, and each cell
// containing a coefficient. Bounds on rows and columns are applied during
// model initialization.
type Matrix interface {
AppendColumn(col []Nonzero) // Append a column given values for all of its nonzero elements
Dims() (rows, cols int) // Return the matrix's dimensions
}
// cMalloc asks C to allocate memory. For convenience to Go, the arguments
// are like calloc's except that the size argument is a value, which cMalloc
// will take the size of. cMalloc panics on error (typically, out of memory).
func cMalloc(nmemb int, sizeVal interface{}) unsafe.Pointer {
size := reflect.TypeOf(sizeVal).Size()
mem := C.malloc(C.size_t(uintptr(nmemb) * size))
if mem == nil {
panic("clp: malloc failed")
}
return mem
}
// cFree asks C to free memory.
func cFree(mem unsafe.Pointer) {
C.free(mem)
}
// cSetArrayInt assigns a[i] = v where a is a C.int array allocated by
// cMalloc and i and v are Go ints.
func cSetArrayInt(a unsafe.Pointer, i, v int) {
eSize := unsafe.Sizeof(C.int(0))
ptr := unsafe.Pointer(uintptr(a) + uintptr(i)*eSize)
*(*C.int)(ptr) = C.int(v)
}
// c__GetArrayInt returns a[i] as a Go int where a is a C.int array allocated
// by cMalloc and i is a Go ints.
func cGetArrayInt(a unsafe.Pointer, i int) int {
eSize := unsafe.Sizeof(C.int(0))
ptr := unsafe.Pointer(uintptr(a) + uintptr(i)*eSize)
return int(*(*C.int)(ptr))
}
// cSetArrayDouble assigns a[i] = v where a is a C.double array allocated by
// cMalloc, i is an int, and v is a Go float64.
func cSetArrayDouble(a unsafe.Pointer, i int, v float64) {
eSize := unsafe.Sizeof(C.double(0.0))
ptr := unsafe.Pointer(uintptr(a) + uintptr(i)*eSize)
*(*C.double)(ptr) = C.double(v)
}
// cGetArrayDouble returns a[i] as a Go float64 where a is a C.double array
// allocated by cMalloc and i is an int.
func cGetArrayDouble(a unsafe.Pointer, i int) float64 {
eSize := unsafe.Sizeof(C.double(0.0))
ptr := unsafe.Pointer(uintptr(a) + uintptr(i)*eSize)
return float64(*(*C.double)(ptr))
}
// copyIntsGoC copies a slice of Go ints to a slice of C ints.
func copyIntsGoC(cs []C.int, gs []int) {
if len(gs) != len(cs) {
panic("Slices of different sizes were passed to copyIntsGoC")
}
for i, g := range gs {
cs[i] = C.int(g)
}
}
// copyIntsCGo copies a slice of C ints to a slice of Go ints.
func copyIntsCGo(gs []int, cs []C.int) {
if len(gs) != len(cs) {
panic("Slices of different sizes were passed to copyIntsCGo")
}
for i, c := range cs {
gs[i] = int(c)
}
}