def add_workload_constr()

in optimizer.py [0:0]


    def add_workload_constr(self, f_print=sys.stdout):

        N = self.abFP_num
        M = self.dataset_num
        y, z, w, u, v = self.get_y_z_w_u_v()

        constrs = []

        """ zw[j] = z[j] * w[j] always = 0 """

        """ u[i, j] = (1-y[i])*(z[j]-z[j]*w[j)) = (1-y[i])*z[j]
        u[i, j] = 1 only when y[i] == 0 (job on-prem) and z[j] == 1 (z represents the state of data on-prem, 1 means not in on-prem)
        This should be egress for input data (or say read), ingress for output data (or say write)
        """
        pair_num = len(self.df)
        temp_counter = 0
        step = pair_num // 10
        start = time.time()
        print("u constr start", file=f_print, flush=True)

        replicated_indices = [self.unique_db_tables[key] for key in self.rep_list if key in self.unique_db_tables]

        for j in range(M):
            if j in replicated_indices:
                continue
            job_ids = self.adj_list_input[j].keys()
            for i in job_ids:
                temp_counter += 1
                constrs.append(self.model.addConstr(u[(i, j)] + y[i] <= 1, name=f'u1_{i}_{j}'))
                constrs.append(self.model.addConstr(u[(i, j)] - z[j] <= 0, name=f'u2_{i}_{j}'))
                constrs.append(self.model.addConstr(- y[i] + z[j] - u[(i, j)] <= 0, name=f'u3_{i}_{j}'))

                if step != 0 and temp_counter % step == 0:
                    print(f"== progress:{temp_counter / pair_num * 100:.0f}%", file=f_print, flush=True)
        print_time(start, time.time(), "u constr created", file=f_print)

        """ v[i, j] = y[i] * (w[j] - z[j] * w[j]) = y[i] * w[j]
        v[i, j] = 1 only when y[i] == 1 (job in cloud) and w[j] == 1 (w represents the state of data in cloud, 1 means not in cloud)
        This should be ingress for input data (or say read), egress for output data (or say write)
        """
        temp_counter = 0
        start = time.time()
        print("v constr start", file=f_print, flush=True)
        for j in range(M):
            if j in replicated_indices:
                continue
            job_ids = self.adj_list_input[j].keys()
            for i in job_ids:
            # for i in range(N):
            #     if self.input_matrix_gb[i, j] > 0 or self.output_matrix_gb[i, j] > 0:
                temp_counter += 1
                constrs.append(self.model.addConstr(v[(i, j)] - y[i] <= 0, name=f'v1_{i}_{j}'))
                constrs.append(self.model.addConstr(v[(i, j)] - w[j] <= 0, name=f'v2_{i}_{j}'))
                constrs.append(self.model.addConstr(y[i] + w[j] - v[(i, j)] <= 1, name=f'v3_{i}_{j}'))
                if step != 0 and temp_counter % step == 0:
                    print(f"== progress:{temp_counter / pair_num * 100:.0f}%", file=f_print, flush=True)
        print_time(start, time.time(), "v constr created", file=f_print)
        return constrs