gmsk
is an unofficial wrapper for MOSEK, the conic optimizer from MOSEK ApS.
For Detailed Documentation, See
See Examples section on for many examples reproduced from C api code.
Hello World example from C api is provided below.
package main
import (
"fmt"
"log"
"github.com/fardream/gmsk"
)
// This is reproduced from MOSEK C example hellowworld.c
// However, the response code is checked here.
func main() {
checkOk := func(err error) {
if err != nil {
log.Fatalf("failed: %s", err.Error())
}
}
task, err := gmsk.MakeTask(nil, 0, 0)
if err != nil {
log.Fatal(err)
}
defer gmsk.DeleteTask(task)
checkOk(task.AppendVars(1))
checkOk(task.PutCJ(0, 1.0))
checkOk(task.PutVarBound(0, gmsk.BK_RA, 2.0, 3.0))
checkOk(task.PutObjSense(gmsk.OBJECTIVE_SENSE_MINIMIZE))
_, res := task.OptimizeTrm()
checkOk(res)
result := make([]float64, 1)
result, res = task.GetXx(gmsk.SOL_ITR, result)
fmt.Printf("Solution x = %.6f\n", result[0])
}
GMSK requires the C api for MOSEK, which can be obtained from MOSEK's website. To actually build the package, a recent enough C toolchain, and the environment should be properly set up.
On linux, this can be achieved by setting CPATH
environment variable and LIBRARY_PATH
# prepend mosek header folder to CPATH, replace {version} and {arch} with the one you have installed
export CPATH=${MSKHOME}/mosek/{version}/tools/platform/{arch}/h${CPATH:+":${CPATH}"}
# prepend mosek lib folder to LIBRARY_PATH
export LIBRARY_PATH=${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin${LIBRARY_PATH:+":${LIBRARY_PATH}"}
export LD_LIBRARY_PATH=${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin${LD_LIBRARY_PATH:+":${LD_LIBRARY_PATH}"}
Alternatively, this can set up for cgo specifically
export CGO_CFLAGS="-I${MSKHOME}/mosek/{version}/tools/platform/{arch}/h"
export CGO_LDFLAGS="-L${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin"
IF LD_LIBRARY_PATH
doesn't include MOSEK's binary folder when running the code, the binary can be set up by adding MOSEK's binary folder to rpath
, for example, the CGO_LDFLAGS
can be updated to add rpath
export CGO_LDFLAGS="-L${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin -Wl,-rpath=${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin"
Follow the installation instructions on MOSEK's website - remember to run install.py
. Note unless System Integrity Protect (SIP) is turned off on macOS, the environment variable LD_LIBRARY_PATH
(and macOS specific DYLD_LIBRARY_PATH
) will NOT work.
When building, the setup is similar to linux
# prepend mosek header folder to CPATH, replace {version} and {arch} with the one you have installed
export CPATH=${MSKHOME}/mosek/{version}/tools/platform/{arch}/h${CPATH:+":${CPATH}"}
# prepend mosek lib folder to LIBRARY_PATH
export LIBRARY_PATH=${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin${LIBRARY_PATH:+":${LIBRARY_PATH}"}
or
export CGO_CFLAGS="-I${MSKHOME}/mosek/{version}/tools/platform/{arch}/h"
export CGO_LDFLAGS="-L${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin"
However, the binary may not be able to find libmosek
at runtime. Besides default search path, macOS will also look for dynlib in the rpaths of the binary - however, it only does so if the load path of the dynlib starts with @rpath
- which is controlled by the LC_ID_DYLIB
of the dynlib (in this case, libmosek64
).
So there are two options
-
Use
rpath
. First addrpath
to the linker lineexport CGO_LDFLAGS="-L${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin -Wl,-headerpad,128 -Wl,-rpath,${MSKHOME}/mosek/{version}/tools/platform/{arch}/bin" #
Then check
LC_ID_DYNLIB
on thelibmosek64.dynlib
, and update it withinstall_name_tool
(which is part of Apple's development suite). For example, for 10.0 version of the libraryinstall_name_tool -id @rpath/libmosek64.10.0.dynlib path/to/libmosek64.10.0.dynlib
-
Change
LC_ID_DYNLIB
to the full absolute path oflibmosek64
.install_name_tool -id /abspath/to/libmosek64.10.0.dynlib path/to/libmosek64.10.0.dynlib