具有非线性约束和二元变量的线性目标函数

时间:2016-10-06 11:14:52

标签: matlab optimization binary constraints linear-programming

我有一个问题,我需要优化候选人的选择。每个候选人都有一个分数(介于0和1之间),一个类型(10个选项,从1到10)和一个数量。

我要优化的变量是二进制的。它们代表候选人的选择与否。对象函数是线性的,它是二元变量和分数向量的标量积。我们的想法是选择最高的得分总和。

现在我有一个线性约束:可以选择的候选人数最多为35。

但我还有10个非线性约束:有10种候选者。在最终选择中,每种类型的总量最多应为所有类型总量的10%。

因此我使用intlinprog编写了一个代码,因为它处理二进制变量,但我正在努力处理非线性约束。我不确定最好是尝试线性化它们还是使用其他求解器?

这是代码:

rng('default');

clc;
clear;
n = 100;
maxSize =  35;
nbType = 10;
NAV = 6000000;
thresholdType = 0.1 * NAV;

%%%TOP BASKET
score = rand(n,1)/10+0.9;
quantity = rand(n,1)*300000;
type = ceil(rand(n,1)*nbType);
typeMask = zeros(n,nbType);

for i=1:nbType
    typeMask(:,i) = type(:,1) == i;
end

f = -score;
intcon = [1:1:n];

%Write the linear INEQUALITY constraints: 
A = [ones(1,n);bsxfun(@times,typeMask,quantity)'/thresholdType];
b = [maxSize;ones(nbType,1)];

%Write the linear EQUALITY constraints:
Aeq = [];
beq = [];

%Write the BOUND constraints: 
lb = zeros(n,1);
ub = ones(n,1); % Enforces i1,i2,...in binary

%x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub);
x = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub);

问题是,在我的A,b中,第一个约束是线性约束(最多35个候选),最后10个约束是非线性的,因此它显然不能给出正确的结果。

2 个答案:

答案 0 :(得分:0)

这是一种使用线性分区算法的方法。

它是如何运作的:

  1. 按降序排列元素
  2. 取出前K个元素并将它们放入不同的集合(其中k = typeq)
  3. 对于下一个N-K元素,将它们放入具有最低和的
  4. 集合中

    你已经完成了。

    该算法不应该为您提供最小化每种类型的每个数量之和的方差的解决方案。但这是一个很好的近似值,尤其是当maxSizen很大时。

    您还可以使用combnk(35,100)计算一组n元素(35 | 100)中k元素的所有可能组合。然后你可以检查哪种组合给你最小的方差,但当然这种方法很耗时。

    clc;
    clear;
    n = 1000;
    maxSize =  400;
    typeq = 10;
    
    %creation of the dataset
    id = 1:n;
    quantity = rand(n,1)*1000;
    type = ceil(rand(n,1)*typeq);
    
    %sort the vectors
    [quantity,rank]  = sort(quantity,'descend');
    type = type(rank);
    id = id(rank);
    
    % Get the id of the 10 biggest quantities for the 10 different types
    [~,b] = unique(flipud(type));
    b = (n-b)+1;
    
    
    if length(b) < typeq
        error('Not enough type') %mean that all the type are not represented.
    end
    
    ids = id(b);
    types = type(b);
    quantitys = quantity(b);
    
    %Now we add the biggest remaining quantity to the type that have the smallest sum(quantity per type)
    for i = typeq+1:maxSize
    [~,minq]  = sort(accumarray(types,quantitys,[],@sum));
    quantity(b) = [];
    type(b) = [];
    id(b) = [];
    
    b = find(type==minq(1),1);
    
    %if there is no more value for the type that have the smallest sum(quantity) we take the second smallest type, the third.... until that the type still exist.
    ii = 2;
    while isempty(b)
        b = find(type == minq(ii),1);
        ii = ii+1;
        disp('Variance is going to increase')
    end
    
    ids = [ids(:);id(b)];
    types = [types(:);type(b)];
    quantitys = [quantitys(:);quantity(b)];
    end
    
    % the selected ID
    id_selected  = sort(ids);
    % The sum for each type.
    res = accumarray(types,quantitys,[],@sum);
    cnt = accumarray(types,ones(maxSize,1),[],@sum);
    for i = 1:typeq
        fprintf('The total quantity for type %d = %f and we have %d elements of this type\n',i,res(i),cnt(i))
    end
    

答案 1 :(得分:-1)

澄清:每种类型的候选人的候选人数不得超过10%?也就是说,对于例如共33名候选人,每种类型的候选人最多为3.3人?翻译成逻辑,最多为3个选项,因此总共30个。 如果我正确理解你的描述,那么你的约束系统会导致每个类型的候选人数相同,而候选人总数的10%,候选人总数必须是10的整数倍。