python 有没有办法在数组变量N上写一个cvxpy的约束,使数组中的所有值要么是0,要么是相同的值?

2cmtqfgy  于 2023-01-29  发布在  Python
关注(0)|答案(1)|浏览(188)

假设我们有X=variable(n, boolean=True)和一个长度为n的包含重复整数的数组B。
我想写一个约束条件,使得X的解与B的元素相乘是一个包含0或单个值p作为元素的Array,其中p是B的元素。
解决方案示例
B=[2,3,4,3,3,2,2,3,5,4,7,7,2]
应该是X1=[0,1,0,1,1,0,0,0,0,0,0,0,0]或者X2=[1,0,0,0,0,0,1,0,0,0,0,0,1]
但不是X3=[0,0,1,1,0,0,1,0,0,0,0,0,1]
我尝试将设置为约束,同时使用numpycvxpy
constr=[cvxpy.sum(np.multiply(X,B))/sum(X)==max(np.multiply(X,B))]
但是我不能解决我使用上面的约束创建的问题

zlwx9yxi

zlwx9yxi1#

多亏了米哈尔·阿达马谢克,我终于找到了解决办法.
下面是求解器的完整代码和一个使用三个不同数组的示例。
我必须使用两组不同的辅助变量,一组用于实现“固定值集”约束,另一组用于表示“析取约束”

from typing import List
import pandas as pd
import numpy as np
import cvxpy as cp
M=1000**3

def aux_variable_constraint(aux:cp.Variable):
    return [cp.sum(aux,axis=0)==1]

def same_number_constraint(X:cp.Variable,arr:List,aux:cp.Variable,d_aux:cp.Variable):
    n=list(set(arr)) @ aux
    Z=cp.multiply(X,arr)

    constr=[]
    for j in range(X.shape[0]):
        constr+=[Z[j]<=n+M*(1-d_aux[j][0]),
        Z[j]>=n-M*(1-d_aux[j][0]),
        Z[j]<=M*(1-d_aux[j][1])
        ]
    return constr 

def pick_most_frequent_elements_solver(arr):
    aux=cp.Variable(len(set(arr)), boolean=True)
    d_aux=cp.Variable((len(arr),2), boolean=True)
    X=cp.Variable(len(arr),boolean=True)

    #obj definition, just to pick as much numbers as possible
    obj=cp.Maximize(cp.sum(X,axis=0))

    #constraints
    constraints=[]
    constraints+=aux_variable_constraint(aux)
    constraints+=[cp.sum(d_aux,axis=1)==np.ones(len(arr))]
    constraints+=same_number_constraint(X,arr,aux,d_aux)

    problem=cp.Problem(obj,constraints)

    problem.solve()
    print(X.value*arr)

A=[4,3,4,3,3,2,3,3,5,4,4,4,4]
B=[4,3,4,3,3,2,3,3,5,4,3,3,4]
C=[4,3,2,2,2,2,3,3,5,2,2,4,4]

pick_most_frequent_elements_solver(A)
pick_most_frequent_elements_solver(B)
pick_most_frequent_elements_solver(C)

相关问题