分段线性函数线性化的Yalmip实现

1.函数表达

需要说明的是,这类分段函数需要是连续函数,下面将对其进行线性化。

因为该函数有四个分段点,为-2,-1,2,5,所有需要四个连续变量w(i)和三个0-1变量d(i)才能实现转换。 其中w(i)实现函数的线性化,d(i)w(i)进行限定,使其在x的取值范围内。

x=w(1)*b(1)+w(2)*b(2)+w(3)*b(3)+w(4)*b(4)=-2w(1)-w(2)+2w(3)+5w(4),其中b(i)为四个分段点。

y=w(1)f(b(1))+w(2)f(b(2))+w(3)f(b(3))+w(4)f(b(4))=w(1)+3w(2)+6w(3)+18w(4)

且需要约束如下:w(1)+w(2)+w(3)+w(4)=1d(1)+d(2)+d(3)=1w(1)\leq d(1),w(2)\leq d(1)+d(2),w(3)\leq d(2)+d(3),w(4)\leq d(3)w(i)\geq 0

2.yalmip调用Cplex求解

代码如下

clc;
x=4;
d=binvar(1,3);
w=sdpvar(1,4);
st=[];
st=[st,
    sum(d)==1,
    sum(w)==1,
    w(1)<=d(1),
    w(2)<=d(1)+d(2),
    w(3)<=d(2)+d(3),
    w(4)<=d(3),
    x==-2*w(1)-w(2)+2*w(3)+5*w(4),
    w>=0,
    ];
y=w(1)+3*w(2)+6*w(3)+18*w(4);
ops=sdpsettings('solver', 'cplex');%参数指定程序用cplex求解器
optimize(st,y,ops)
outcome=['y=',num2str(double(y))];

验证结果如下 :设定x=4可得y=14

 3.多个x同时求解

上面的代码只能单个求解,效率较低,下面更正代码如下,进行循环求解。

x=[250 60 90 120 150];
jw=250;
%增长率
jx=0.25;
%区间长度
L=100;
st=[];
z=binvar(6,5);
w=sdpvar(7,5);
for t=1:length(x)
st=[st,
    z(1,t)+z(2,t)+z(3,t)+z(4,t)+z(5,t)+z(6,t)==1,
    w(1,t)+w(2,t)+w(3,t)+w(4,t)+w(5,t)+w(6,t)+w(7,t)==1,
    w(1,t)>=0,
    w(2,t)>=0,
    w(3,t)>=0,
    w(4,t)>=0,
    w(5,t)>=0,
    w(6,t)>=0,
    w(7,t)>=0,
    x(t)==-200*w(1,t)-100*w(2,t)+100*w(4,t)+200*w(5,t)+300*w(6,t)+400*w(7,t),
    w(1,t)<=z(1,t),
    w(2,t)<=z(1,t)+z(2,t),
    w(3,t)<=z(2,t)+z(3,t),
    w(4,t)<=z(3,t)+z(4,t),
    w(5,t)<=z(4,t)+z(5,t),
    w(6,t)<=z(5,t)+z(6,t),
    w(7,t)<=z(6,t),
    ];
end
y=(jw*(1+2*jx)*(-2*L)-jw*(1+jx)*L)*w(1,:)-(jw*(1+jx)*(-L))*w(2,:)+(jw*L)*w(4,:)+(jw*(1+jx)*L+jw*L)*w(5,:)...
    +(jw*(1+2*jx)*L+jw*L*(2+jw))*w(6,:)+(jw*(1+3*jx)*L+jw*(3+3*jx)*L)*w(7,:);
ops=sdpsettings('solver', 'cplex');%参数指定程序用cplex求解器
optimize(st,y,ops)

  • 9
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
以下是使用Matlab进行分段函数线性化的示例代码: ```matlab % 定义分段函数 x = linspace(-5, 5, 100); y = zeros(size(x)); for i = 1:length(x) if x(i) < -2 y(i) = 0; elseif x(i) < 0 y(i) = x(i) + 2; elseif x(i) < 2 y(i) = -x(i) + 2; else y(i) = 0; end end % 绘制原始函数 figure; plot(x, y); title('原始函数'); % 线性化分段函数 x0 = 0; % 线性化点 y0 = x0 + 2; % 线性化点处的函数值 k1 = (y0 - 0) / (x0 - (-2)); % 前半段的斜率 k2 = (0 - y0) / (2 - x0); % 后半段的斜率 x1 = linspace(-5, x0, 100); % 前半段的线性化区间 x2 = linspace(x0, 5, 100); % 后半段的线性化区间 y1 = k1 * (x1 - (-2)); % 前半段的线性化函数 y2 = k2 * (x2 - x0) + y0; % 后半段的线性化函数 % 绘制线性化函数 figure; plot(x, y, x1, y1, x2, y2); title('线性化函数'); legend('原始函数', '线性化函数'); ``` 在这个示例中,我们定义了一个分段函数,并使用`for`循环将其在`[−5,5]`范围内离散化为100个点。然后,我们使用Matlab的`plot`函数绘制了原始分段函数。 接下来,我们选择一个线性化点`x0`,并计算出前半段和后半段的斜率。然后,我们使用`linspace`函数在`[-5,x0]`和`[x0,5]`范围内分别计算出前半段和后半段的线性化函数。最后,我们使用`plot`函数将原始函数线性化函数一起绘制出来。 注意,这个示例只是一个简单的示例,实际应用中可能需要更复杂的分段函数线性化方法。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值