cvxpy 整数变量 - 从解决方案中排除某些整数值
cvxpy integer variable - exclude certain integer values from the solution
我有以下问题,我不知道 cvxpy 是否可以满足我的需要。
背景:我优化投资组合。在购买债券和优化每只债券的购买数量时,每只债券只能以 1,000 单位的倍数购买。
但是,大多数时候需要购买的最低数量是 10,000。
这意味着我们要么根本不购买债券,要么如果我们购买它,购买的数量必须是 10,000、11,000、12,000 等等。
有没有办法(似乎没有)限制整数变量可能具有的可能解决方案中的某些值?
因此,假设我们有一个非负整数变量 x。
我们基本上想买 1000x 但我们知道 x 可以是 x = {0, 10, 11, 12, ...}
是否可以跳过值 1.. 9 而不添加其他变量?
例如:
import numpy as np
import pandas as pd
import cvxpy as cvx
np.random.seed(1)
# np.random.rand(3)
p = pd.DataFrame({'bond_id': ['s1','s2', 's3', 's4', 's5', 's6', 's7','s8','s9', 's10'],
'er': np.random.rand(10),
'units': [10000,2000,3000,4000,27000,4000,0,0,0,0] })
final_units = cvx.Variable( 10, integer=True)
constraints = list()
constraints.append( final_units >= 0)
constraints.append(sum(final_units*1000) <= 50000)
constraints.append(sum(final_units*1000) >= 50000)
constraints.append(final_units <= 15)
obj = cvx.Maximize( final_units @ np.array(list(p['er'])) )
prob = cvx.Problem(obj, constraints)
solve_val = prob.solve()
print("\n* solve_val = {}".format(solve_val))
solution_value = prob.value
solution = str(prob.status).lower()
print("\n** SOLUTION 3: {} Value: {} ".format(solution, solution_value))
print("\n* final_units -> \n{}\n".format(final_units.value))
p['FINAL_SOL'] = final_units.value * 1000
print("\n* Final Portfolio: \n{}\n".format(p))
这个解决方案是我面临的问题的一个非常简化的版本。最终向量 final_units 可以建议值,如本例所示,我们必须购买 5,000 单位的债券 s9,但我不能,因为我可以购买的最小值为 10,000。
我知道我可以添加一个额外的整数向量来表达 OR 条件,但实际上我真正的问题远不止于此,我已经有数千个整数变量。因此,我想知道是否有一种方法可以在不向问题添加额外变量的情况下排除 1 到 9 的值。
谢谢
不,不使用 CVXPY。您可以使用 整数变量 x[i]
加上 二进制变量 y[i]
并使用约束(在数学中表示法):
y[i] * 10 <= x[i] <= y[i] * 15
这导致 x[i] ∈ {0, 10..15}。
一些求解器为此设置了变量类型:半整数变量。使用这个你不需要额外的二进制变量和这两个约束。 CVXPY 不支持此变量类型 AFAIK。
我有以下问题,我不知道 cvxpy 是否可以满足我的需要。 背景:我优化投资组合。在购买债券和优化每只债券的购买数量时,每只债券只能以 1,000 单位的倍数购买。 但是,大多数时候需要购买的最低数量是 10,000。 这意味着我们要么根本不购买债券,要么如果我们购买它,购买的数量必须是 10,000、11,000、12,000 等等。 有没有办法(似乎没有)限制整数变量可能具有的可能解决方案中的某些值? 因此,假设我们有一个非负整数变量 x。 我们基本上想买 1000x 但我们知道 x 可以是 x = {0, 10, 11, 12, ...} 是否可以跳过值 1.. 9 而不添加其他变量?
例如:
import numpy as np
import pandas as pd
import cvxpy as cvx
np.random.seed(1)
# np.random.rand(3)
p = pd.DataFrame({'bond_id': ['s1','s2', 's3', 's4', 's5', 's6', 's7','s8','s9', 's10'],
'er': np.random.rand(10),
'units': [10000,2000,3000,4000,27000,4000,0,0,0,0] })
final_units = cvx.Variable( 10, integer=True)
constraints = list()
constraints.append( final_units >= 0)
constraints.append(sum(final_units*1000) <= 50000)
constraints.append(sum(final_units*1000) >= 50000)
constraints.append(final_units <= 15)
obj = cvx.Maximize( final_units @ np.array(list(p['er'])) )
prob = cvx.Problem(obj, constraints)
solve_val = prob.solve()
print("\n* solve_val = {}".format(solve_val))
solution_value = prob.value
solution = str(prob.status).lower()
print("\n** SOLUTION 3: {} Value: {} ".format(solution, solution_value))
print("\n* final_units -> \n{}\n".format(final_units.value))
p['FINAL_SOL'] = final_units.value * 1000
print("\n* Final Portfolio: \n{}\n".format(p))
这个解决方案是我面临的问题的一个非常简化的版本。最终向量 final_units 可以建议值,如本例所示,我们必须购买 5,000 单位的债券 s9,但我不能,因为我可以购买的最小值为 10,000。 我知道我可以添加一个额外的整数向量来表达 OR 条件,但实际上我真正的问题远不止于此,我已经有数千个整数变量。因此,我想知道是否有一种方法可以在不向问题添加额外变量的情况下排除 1 到 9 的值。 谢谢
不,不使用 CVXPY。您可以使用 整数变量 x[i]
加上 二进制变量 y[i]
并使用约束(在数学中表示法):
y[i] * 10 <= x[i] <= y[i] * 15
这导致 x[i] ∈ {0, 10..15}。
一些求解器为此设置了变量类型:半整数变量。使用这个你不需要额外的二进制变量和这两个约束。 CVXPY 不支持此变量类型 AFAIK。