def fit(self, X, y, instances):
    test_instances = instances['test']
    validation_instances = instances['validation']
    train_instances = instances['train']
    time_ = 0
    self.model_time = 0
    n_train = X.shape[0]
    if self.validation:
        validation_list = []
    X_torch = torch.from_numpy(X).float()
    y_torch = torch.from_numpy(y).float()
    true_solution = {}
    logging.info('training started')
    for e in range(self.epochs):
        for i in range(self.num_instance):
            start_time = time.time()
            self.optimizer.zero_grad()
            (source, dest) = train_instances[i]
            b = np.zeros(len(self.A))
            b[source] = 1
            b[dest] = (- 1)
            if (i not in true_solution):
                model = gp.Model()
                model.setParam('OutputFlag', 0)
                x = model.addMVar(shape=self.A.shape[1], lb=0.0, vtype=gp.GRB.CONTINUOUS, name='x')
                model.addConstr(((self.A @ x) == b), name='eq')
                model.setObjective((y_torch.detach().numpy() @ x), gp.GRB.MINIMIZE)
                model.optimize()
                x_true = x.X
                true_solution[i] = np.copy(x_true)
            x_true = true_solution[i]
            c_pred = self.net(X_torch).squeeze()
            c_spo = ((2 * c_pred) - y_torch)
            model = gp.Model()
            model.setParam('OutputFlag', 0)
            x = model.addMVar(shape=self.A.shape[1], lb=0.0, ub=1.0, vtype=gp.GRB.CONTINUOUS, name='x')
            model.addConstr(((self.A @ x) == b), name='eq')
            model.setObjective((c_spo.detach().numpy() @ x), gp.GRB.MINIMIZE)
            model.optimize()
            x_spo = x.X
            grad = torch.from_numpy((x_true - x_spo)).float()
            loss = self.net(X_torch).squeeze()
            loss.backward(gradient=grad)
            self.optimizer.step()
            logging.info('bkwd done')
            end_time = time.time()
            time_ += (end_time - start_time)
            if self.validation:
                if (((i + 1) % 20) == 0):
                    validation_list.append(validation_module(self.net, self.A, X, y, train_instances, validation_instances, test_instances, time_, e, i))
        print('Epoch {} Loss:{} Time: {:%Y-%m-%d %H:%M:%S}'.format((e + 1), loss.sum().item(), datetime.datetime.now()))
    if self.validation:
        dd = defaultdict(list)
        for d in validation_list:
            for (key, value) in d.items():
                dd[key].append(value)
        df = pd.DataFrame.from_dict(dd)
        logging.info(('Completion Time %s \n' % str(datetime.datetime.now())))
        return df
def fit(self, X, y, instances):
    test_instances = instances['test']
    validation_instances = instances['validation']
    train_instances = instances['train']
    time_ = 0
    self.model_time = 0
    n_train = X.shape[0]
    if self.validation:
        validation_list = []
    X_torch = torch.from_numpy(X).float()
    y_torch = torch.from_numpy(y).float()
    true_solution = {}
    logging.info('training started')
    for e in range(self.epochs):
        for i in range(self.num_instance):
            start_time = time.time()
            self.optimizer.zero_grad()
            (source, dest) = train_instances[i]
            b = np.zeros(len(self.A))
            b[source] = 1
            b[dest] = (- 1)
            if (i not in true_solution):
                model = gp.Model()
                model.setParam('OutputFlag', 0)
                x = model.addMVar(shape=self.A.shape[1], lb=0.0, vtype=gp.GRB.CONTINUOUS, name='x')
                model.addConstr(((self.A @ x) == b), name='eq')
                model.setObjective((y_torch.detach().numpy() @ x), gp.GRB.MINIMIZE)
                model.optimize()
                x_true = x.X
                true_solution[i] = np.copy(x_true)
            x_true = true_solution[i]
            c_pred = self.net(X_torch).squeeze()
            c_spo = ((2 * c_pred) - y_torch)
            model = gp.Model()
            model.setParam('OutputFlag', 0)
            x = model.addMVar(shape=self.A.shape[1], lb=0.0, ub=1.0, vtype=gp.GRB.CONTINUOUS, name='x')
            model.addConstr(((self.A @ x) == b), name='eq')
            model.setObjective((c_spo.detach().numpy() @ x), gp.GRB.MINIMIZE)
            model.optimize()
            x_spo = x.X
            grad = torch.from_numpy((x_true - x_spo)).float()
            loss = self.net(X_torch).squeeze()
            loss.backward(gradient=grad)
            self.optimizer.step()
            logging.info('bkwd done')
            end_time = time.time()
            time_ += (end_time - start_time)
            if self.validation:
                if (((i + 1) % 20) == 0):
                    validation_list.append(validation_module(self.net, self.A, X, y, train_instances, validation_instances, test_instances, time_, e, i))
        print('Epoch {} Loss:{} Time: {:%Y-%m-%d %H:%M:%S}'.format((e + 1), loss.sum().item(), datetime.datetime.now()))
    if self.validation:
        dd = defaultdict(list)
        for d in validation_list:
            for (key, value) in d.items():
                dd[key].append(value)
        df = pd.DataFrame.from_dict(dd)
        logging.info(('Completion Time %s \n' % str(datetime.datetime.now())))
        return df