Or-Tools CP-SAT 솔버 내보내기 / 가져 오기 : 모델을로드 한 후 vars에 액세스하는 방법은 무엇입니까?

Dec 08 2020

OR-Tools CP-CAT 솔버 (참조)에 대한 Python 인터페이스를 사용하여 cp_model을 저장하고 나중에 또는 다른 프로세스에서로드하고 계속 상호 작용할 수 있기를 바랍니다.

모델을 Protubuf로 직렬화 한 다음로드하고 해결할 수 있습니다.

from google.protobuf import text_format
from ortools.sat.python import cp_model

def create_model():
    model = cp_model.CpModel()
    a = model.NewIntVar(0, 10, "var_a")
    b = model.NewIntVar(0, 10, "var_b")

    model.Maximize(a + b)
    return model
    
def clone_model(model):
    new_model = cp_model.CpModel()
    text_format.Parse(str(model), new_model.Proto())
    
    return new_model

def solve_model(model):
    solver = cp_model.CpSolver()
    status = solver.Solve(new_model)

    print(solver.StatusName(status))
    print(solver.ObjectiveValue())

# Works fine
model = create_model()
new_model = clone_model(model)
solve_model(new_model)

(출처)

그러나 모델을로드 한 후에도 계속 상호 작용하고 싶습니다. 예를 들어 다음과 같이 할 수 있기를 원합니다.

model = create_model()
new_model = clone_model(model)

c = new_model.NewIntVar(0, 5, "var_c")    
new_model.Add(a < c)

문제는이 마지막 줄이 a정의되지 않았기 때문에 작동하지 않는다는 것 입니다. 기존 모델의 변수에 액세스 할 방법을 찾을 수 없었습니다.

나는 다음과 같은 것을 찾고 a = new_model.getExistingVariable("var_a")있습니다. 그러면 모델을로드 한 후 모델의 기존 변수와 계속 상호 작용할 수 있습니다.

답변

2 etov Dec 08 2020 at 23:41

@Stradivari의 주석을 기반으로 작동하는 것처럼 보이는 접근 방식 pickle은 변수와 함께 모델 을 간단하게 만드는 것 입니다.

예를 들면 :

from ortools.sat.python import cp_model
import pickle

class ClonableModel:
    def __init__(self):
        self.model = cp_model.CpModel()
        self.vars = {}
        
    def create_model(self):
        self.vars['a'] = self.model.NewIntVar(0, 10, "var_a")
        self.vars['b'] = self.model.NewIntVar(0, 10, "var_b")

        self.model.Maximize(self.vars['a'] + self.vars['b'])
        
    # Also possible to serialize via a file / over network 
    def clone(self):
        return pickle.loads(pickle.dumps(self))
    
    def solve(self):
        solver = cp_model.CpSolver()
        status = solver.Solve(self.model)

        return '%s: %i' % (solver.StatusName(status), solver.ObjectiveValue())

이제 다음이 예상대로 작동합니다.

model = ClonableModel()
model.create_model()

new_model = model.clone()
new_model.model.NewIntVar(0,5,"c")
new_model.model.Add(new_model.vars['a'] < c)

print('Original model: %s' % model.solve())
print('Cloned model: %s' % new_model.solve())

# Original model: OPTIMAL: 20
# Cloned model: OPTIMAL: 14