from docplex.mp.model import Model

from cplex.callbacks import LazyConstraintCallback

from docplex.mp.callbacks.cb_mixin import *

p_id is the list of lists of customers,

n is the set of vehicles,

dth is the fixed parameter, and

q_prob is the dictionary representing the probability of availability of vehicles (day-wise)

Creating Model

trial_mod=Model('My Trial Model',log_output=True)

Defining decision variables

x_ind={(i,d+dth):trial_mod.binary_var(name='x_{0}_{1}'.format(i,d+dth)) for i in n_id for d in range(len(p_id))}

Others decision variables are also defined but they are not relevant here.

Adding constraints using Callback (lazyconstrainrts)

At integer node (means whenever we obtain the candidate solution), I want to check that \parod_{i\in n} (1-q_i^dx_i^d) >= threshold \forall d. If not then I want to add a cut as

\sum(x_ind[i,d+dth] for i in n_id if x_^*ind[i,d+dth]==0)+ \sum(1-x_ind[i,d+dth] for i in n_id if x_^*ind[i,d+dth]==1) >= 1 \forall d.

For that, I have written callback code as

class NonLinearConstraintCallback(ConstraintCallbackMixin, LazyConstraintCallback):

        def __init__(self, env, trial_mod, x_ind, dic_nurse_avail_remaining_days):
            LazyConstraintCallback.__init__(self, env)
            self.trial_mod = trial_mod
            self.x_ind = x_ind
            self.dic_nurse_avail_remaining_days = dic_nurse_avail_remaining_days

        def __call__(self):
          sol = self.make_solution_from_vars(self.x_ind.values())
          for d in range(1,len(p_id)):
                prob_product = 1.0
                    for i in n_id:
                       ind_vars_value = sol.get_value(x_ind[i,d+dth])
                       prob_product *= (1 - (1 self.dic_nurse_avail_remaining_days['nurse_{}_day_{}_planned_{}'.format(i,day-1+1,d+dth)])*ind_vars_value)                    
                    if prob_product < threshold:
                       lhs_terms = []
                       for i in n_id:
                          ind_vars_value2 = sol.get_value(x_ind[i,d+dth])
                          if round(ind_vars_value2, 2) <= 0.2:
                          elif round(ind_vars_value2, 2) >= 0.9:
                             lhs_terms.append(1 - self.x_ind[i,d+dth])
                       lhs = sum(lhs_terms)
                       self.trial_mod.add_constraint(lhs >= 1)

cb = trial_mod.register_callback(NonLinearConstraintCallback)

cb.x_ind = x_ind

cb.dic_nurse_avail_remaining_days = dic_nurse_avail_remaining_days

trial_mod.lazy_callback = cb

When I solve using command trial_mod.solve(log_output=True) I can see that callback is adding violated cut correctly. But when it comes to the solution printing command i.e. trial_mod.print_solution() it gives the error as

docplex.mp.utils.DOcplexException: Model did not solve successfully.

When I tried to print the status of the solution using command print(trial_mod.solve_details), it tells the status as

status = Unknown status value.

I am not able to visualize the reasons for such errors.

This post is in continuation of Getting error in callback (lazy constraints) for docplex with Python to solve MILP.



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.