0

我有以下问题,我不知道 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 的值,而无需为问题添加额外的变量。谢谢

4

1 回答 1

1

不,不是 CVXPY。您可以使用整数变量 x[i]加上二进制变量 y[i]对其进行建模,并使用约束(以数学表示法):

 y[i] * 10 <= x[i] <= y[i] * 15

这导致 x[i] ∈ {0, 10..15}。

一些求解器为此提供了一个变量类型:半整数变量。使用它,您不需要额外的二进制变量和这两个约束。CVXPY 不支持这种变量类型 AFAIK。

于 2020-11-18T18:42:59.230 回答