1

This is a follow-up question to a previous post.

The problem I'm trying to solve is to find the largest combination of cells at the intersection of company and category with an average above a certain threshold. Additionally, if I include 3 categories for a certain company, then in order to include another company, all 3 categories of that company must also be included.

I am incorporating disjunctive reasoning into my optimization problem. I set a constraint where at least 2 of the 3 companies (columns) and all three categories (rows) have to be non-zero. I create zero_comp_vars and zero_cat_vars for this. In order for the optimization to incorporate this, I want to multiply the decision variable matrix by these, but element wise (e.g. so if the zero_comp_vars is [1,0,0] we multiply the first column of the decision variables matrix by 1 as a scalar and the second and third columns by 0 as a scalar. However, I believe doing this makes the function non-linear.

I can use vstack and hstack to convert zero_comp_vars and zero_cat_vars to matrices, but then encounter the DCP violation.

import numpy as np
import cvxpy as cp
import cvxopt 

util = np.array([[0.7, 0.95, 0.3], [2, 1.05, 2.2], [4, 1, 3]])

# The variable we are solving for
dec_vars = cp.Variable(util.shape, boolean = True)

zero_comp_vars = cp.Variable(util.shape[1], boolean = True)
zero_cat_vars = cp.Variable(util.shape[0], boolean = True)

# define constraints
zero_comp_constr = cp.sum(dec_vars, axis=0) >= 2 * zero_comp_vars
zero_cat_constr = cp.sum(dec_vars, axis=1) >= 3 * zero_cat_vars
# need the following two constraints, otherwise all the values in the zero_comp_constr and zero_cat_constr vectors can be 0
above_one_non_zero_comp = cp.sum(zero_comp_vars) >= 1
above_one_non_zero_cat = cp.sum(zero_cat_vars) >= 1

# min tin array
min_comp_array=np.empty(dec_vars.shape[0])
min_comp_array.fill(2)

min_comp_constr = cp.sum(dec_vars, axis=1) >= min_comp_array
tot_avg_constr = tot_util >= 2.0 * cp.sum(dec_vars)

temp = cp.multiply(util, dec_vars)
# realize as it's written, it's trying to do element-wise multiplication, and dec_vars has shape (3,)
temp2 = cp.multiply(temp, zero_comp_vars)
temp3 = cp.multiply(temp2, zero_cat_vars)

tot_util = cp.sum(temp3)

cluster_problem = cp.Problem(cp.Maximize(tot_util), [zero_comp_constr, zero_cat_constr, 
                                                     above_one_non_zero_comp, above_one_non_zero_cat,
                                                     min_comp_constr, tot_avg_constr])

cluster_problem.solve()
matsuo_basho
  • 2,833
  • 8
  • 26
  • 47

0 Answers0