[Tip] Gurobi optimizer 설치 및 Academic 라이선스 파일 생성

gurobi의 가격이 1user당 $10,000이다 보니 학생 신분으로 얻을 수 있는 Academic 라이선스가 아니면 엄두가 나지 않는다.

비즈니스 trial 30일 라이선스 신청도 시간이 오래 걸린다.

아카데미 라이선스는 학교 다니는 주변 지인이 있는 경우 쉽게 얻을 수 있다. 아주 쉽게

나도 어찌어찌 아카데미 라이스선를 발급 받을 수 있는 키( XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX )를 얻게 되었는데 실제 라이선스 파일 발급은 이 키를 기반으로 얻을 수 있다.

내가 라이선스를 신청한 학교 도메인에 있고 예를 들어 linux 터미널에 접근 할 수 있다면 gurobi 사이트에서 gurobi 라이선스 파일을 받 을 수 있다.

$ grbgetkey XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

여기서 잠시 ….

gurobi 사이트에서 내게 발급된 라이선스 정보를 보면 현재(2019.12.05) 기준 gurobi 9.0 버전으로 발급된 것으로 되어 있으나

실제 라이선스 파일(gurobi.lic) 내용을 보면 버전 7에 대해서 발급 된것을 알 수 있다.

나는 9.0 버전으로 내려 받고 gurobi를 구동 했는데 유효하지 않은 라이선스라고 나왔다. 버전 7.5.x 버전을 받아 설치 하고 구동 했더니 잘 동작 했다.

여기서는 linux ubutu 18.04, gurobi 7.5.x 를 기준으로 설명한다.

gurobi optimzer 7.5.2 을 받는다
(또는 직접 다운로드)

아래 처럼 설치 한다

$ wget https://packages.gurobi.com/7.5/gurobi7.5.2_linux64.tar.gz
$ tar zxvf gurobi7.5.2_linux64.tar.gz
$ ls -al gurobi752/linux64
drwxr-xr-x 10 shpark shpark   4096 Dec  5 17:28 .
drwxr-xr-x  3 shpark shpark   4096 Nov 11  2017 ..
drwxr-xr-x  2 shpark shpark   4096 Dec  5 21:42 bin
drwxr-xr-x  7 shpark shpark   4096 Nov 11  2017 docs
-rwxr-xr-x  1 shpark shpark 273127 Nov 11  2017 EULA.pdf
drwxr-xr-x 12 shpark shpark   4096 Nov 11  2017 examples
drwxr-xr-x  3 shpark shpark   4096 Nov 11  2017 include
drwxr-xr-x  6 shpark shpark   4096 Nov 11  2017 lib

그리고 .bashrc 파일에 아래 경로들을 설정 한다.

$ vi .bashrc
export GUROBI_HOME=/home/shpark/gurobi752/linux64
export GRB_LICENSE_FILE=$GUROBI_HOME/gurobi.lic
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GUROBI_HOME/lib
export PATH=$PATH:$GUROBI_HOME/bin
$ source .bashrc

내가 학교 도메인에 있는 네트워크에 물려 있지 않기 때문에 grbgetkey XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 명령으로 라이선스 파일을 발급 받지 못한다. 예를 들어 학교 도메인이 ccc.edu 이고 내가 사용하는 도메인이 ddd.net 이라면 학교 도메인이 아니라고 나오고 라이선스 발급이 되지 않는다.

이런 경우 url을 직접 만들어 학교에 있는 wifi 에 접속한 가능한 사람에게 카톡으로 보내줘서 보내준 링크를 눌러 달라고 요청한다.

그러면 그 사람은 학교 도메인의 네트워크로 접속하기 때문에 license file에 해당하는 스트링을 브라우즈상에서 보게 되는데 이를 그 대로 복사해서 다시 카톡으로 보내 달라고 하면 된다.

그리고 그 스트링을 잘 잘라서 정렬 후 gurobi.lic 파일로 저장 하면 된다.

gurobi.lic 파일 포맷은 아래와 같다

※ 주의: 문자열 끝 예를들어 ACADEMIC 끝에 공백이 있을 경우가 있는데 반드시 제거 해야 한다. 이 것 때문에 오류가 많이 발생 한다

그러면 url을 만드는 방법을 알아 보자

url 의 형식은 아래와 같다

http://apps.gurobi.com//keyserver?id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&hostname=xxxx&hostid=xxxxx&username=xxxxx&os=linux64&sockets=1&cpu=xxxxxx&localdate=yyyy-mm-dd

위 url의 파라미터 id, hostname, hostid,username,os,sockets등을 어떻게 알아내서 채우는지 알아 보자
grbprobe 를 실행하여 많은 정보를 알 수 있다. grbprobe 는 /home/shpark/gurobi752/linux64/bin에 있다.

$ grbprobe

HOSTNAME=nmt0
HOSTID=f6d5c6d5
PLATFORM=linux64
USERNAME=shpark
CPU=Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz

위의 결과로 hostname, hostid, username, os,cpu 정보를 채울 수 있다. 단 cpu정보는 공백 및 특수 문자가 있으므로 url encoding을 한다.

예를 들어 cpu 정보를 urll encoding하면 “Intel%28R%29%20Xeon%28R%29%20CPU%20E5-2690%20v4%20%40%202.60GHz” 이 된다.

온라인 url encoding 사이트 <– 링크 클릭

그리고 sockets는 아래 정보에서 알수 있다.

$ lscpu

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              28
On-line CPU(s) list: 0-27
Thread(s) per core:  2
Core(s) per socket:  14
Socket(s):           1

참고로 grbprobe 가 생성한 hostid와 시스템에서 보여주는 hostid가 다른 경우가 있다

예를 들어 아래 처럼, 이런 경우는 grbprobe 가 보여주는 hostid를 시스템에 설정하는 것이 좋다.

hostid를 변경하는 방법은 맨 아래 shell 코드가 있다

$ hostid
007f0101

그러면 url은 아래와 같이 완성된다. id 는 부여 받은 것으로 넣고 localdates는 현재 년월일을 넣어면 된다

http://apps.gurobi.com//keyserver?id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXXXXXX&hostname=nmt0&hostid=f6d5c6d5&username=shpark&os=linux64&sockets=1&cpu=Intel%28R%29%20Xeon%28R%29%20CPU%20E5-2690%20v4%20%40%202.60GHz&localdate=2019-12-05

위와 같이 하여 학교 wifi가 접속된 PC 또는 휴대폰에서 위 링크를 실행하면 아래와 같은 문자열을 돌려 준다. 실패시에는 RESULT값이 0이 아닌 다른 값을 돌려 준다.

RESULT=0 LICENSEID=383565 # DO NOT EDIT THIS FILE except as noted # # License ID xxxxxx TYPE=ACADEMIC VERSION=7 HOSTNAME=nmt0 HOSTID=f6d5c6d5 USERNAME=shpark EXPIRATION=2020-12-04 KEY=xxxxxxx

이제 리턴된 위의 문자열을 위 그림에서 보여준 gurobi.lic 파일 포맷에 맞게 정리 하고 GRB_LICENSE_FILE 변수에 지정된 경로에 gurobi.lic 파일로 저장한다.

아래에 VERSION 정보를 보면 7 버전으로 되어 있다. 따라서 gurobi optimizer도 7.x 버전을 설치 해야 한다. 다른 버전을 설치 하면 버전이 맞지 않다고 에러가 발생한다. (현재 gurobi optimizer 버전이 9.0 인데 라이선스는 7 버전으로 발급된다)

# DO NOT EDIT THIS FILE except as noted #
# License ID xxxxxx
TYPE= ACADEMIC
VERSION=7
HOSTNAME=nmt0
HOSTID=f6d5c6d5
USERNAME=shpark
EXPIRATION=2020-12-04
KEY=xxxxxxx

gurobi.lic 파일이 정상적인지 확인 하려면 $GUROBI_HOME/bin 에 있는 gurobi.sh 를 실행 해서 확인 할 수 있다.

아래에서 볼 수 있듯이 “gurobi>” 프롬트와 “Academic license – for non-commercial use only” 라는 문구를 통해 라이선서 파일이 정상임을 알 수 있다.

$ cd $GUROBI_HOME/bin
$ ./gurobi.sh

Python 2.7.13 (default, Sep  4 2017, 15:40:17)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Academic license - for non-commercial use only

Gurobi Interactive Shell (linux64), Version 7.5.2
Copyright (c) 2017, Gurobi Optimization, Inc.
Type "help()" for help
gurobi>

Julia에 Gurobi package 설치 – gurobi optimzer를 설치 하고 라이선스도 정상임을 확인 한 후 julia Gurobi package 를 설치 한다.

현재 master버전 Gurobi 패키지는 gurobi optimizer 9.0을 지원 하므로 master 버전을 설치 한다

기존에 julia Gurobi가 이미 다른 버전의 gurobi opimizer를 사용하도록 build 되었다면 다시 빌드만 하면 된다

Pkg> add Gurobi#master
Pkg> build Gurobi

Julia에서도 정상적으로 동작하는지 확인 해보면 아래서 보듯 정상임을 알 수 있다.

julia> using Gurobi

julia> Gurobi.Env()
Academic license - for non-commercial use only
Gurobi.Env(Ptr{Nothing} @0x00000000016bfed0)

Julia에서 Gurobi를 사용 했을 때 제대로 계산 하는 것을 아래에서 볼 수 있다.

using JuMP, Gurobi

m = Model(with_optimizer(Gurobi.Optimizer, Presolve=0, OutputFlag=0))

@variable(m, 0 <= x1 <= 10)
@variable(m, x2 >= 0)
@variable(m, x3 >= 0)

@objective(m, Max, x1 + 2x2 + 5x3)

@constraint(m, constraint1, -x1 + x2 + 3x3 <= -5)
@constraint(m, constraint2, x1 + 3x2 - 7x3 <= 10)
print(m)
JuMP.optimize!(m)
println("Optimal Solutions:")
println("x1 = ",JuMP.value(x1))
println("x2 = ",JuMP.value(x2))
println("x3 = ",JuMP.value(x3))

println("Dual Variables:")
println("dual1 = ", JuMP.shadow_price(constraint1))
println("dual2 = ", JuMP.shadow_price(constraint2))

결과는

Academic license - for non-commercial use only
Max x1 + 2 x2 + 5 x3
Subject to
 constraint1 : -x1 + x2 + 3 x3 ≤ -5.0
 constraint2 : x1 + 3 x2 - 7 x3 ≤ 10.0
 x1 ≥ 0.0
 x2 ≥ 0.0
 x3 ≥ 0.0
 x1 ≤ 10.0
Academic license - for non-commercial use only
Optimal Solutions:
x1 = 10.0
x2 = 2.1875
x3 = 0.9375
Dual Variables:
dual1 = 1.8124999999999998
dual2 = 0.06249999999999989

마지막으로 hostid가 다른 경우 hostid를 변경하는 방법을 알아 보자.

아래와 같이 set_host_id.sh 라는 shell 파일을 만든다.

set_host_id.sh

#!/bin/bash
#
# Purpose: Write the passed in parameter as hostid to /etc/hostid
#          If no parameter is passed, write current hostid to /etc/hostid
# Author:  Fazle Arefin

if [[ -n "$1" ]]; then
  host_id=$1
  # chars must be 0-9, a-f, A-F and exactly 8 chars
  egrep -o '^[a-fA-F0-9]{8}$' <<< $host_id || exit 1
else
  host_id=$(hostid)
fi

a=${host_id:6:2}
b=${host_id:4:2}
c=${host_id:2:2}
d=${host_id:0:2}

echo -ne \\x$a\\x$b\\x$c\\x$d > /etc/hostid &&
  echo "Success" 1>&2

exit 0

그리고 다음과 같이 하면 된다.

$ chmod +x set_host_id.sh
$ sudo ./set_host_id.sh f6d5c6d5
$ hostid
f6d5c6d5

참조 : https://towardsdatascience.com/running-julia-gurobi-jupyter-on-aws-33f7016ab229

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다