frogfish 发表于 2007-7-3 22:29

退火算法解非线性方程组

clear,clc
%这是退火算法的主程序,它需要调用的函数是
%函数(1)nonLinearSumError1:计算非线性方程组总误差的函数
%函数(2)newSolver1:在一组解的邻域产生另一组解
%函数(3)isSolution:验证方程是否得解
%设置初始值
i=0;T=10001;j=0;%i:同一温度下状态转移次数;T:温度;j:下降温度
precision=0.1;
x1Group=1;%x1Group:可能解的组数
x1N=4;%非线性方程组的元数
x1=round((-0.5+rand(x1Group,x1N))*20);%随机生成-10~10之间的初解
errorHold=Inf;
xHold=0;
%x1=[-7 5 1 -3];
i=0;
while i<200
i=i+1;
j=0;
T=T-50;%退火
while j<200
j=j+1;
functionError1=nonLinearSumError1(x1);%计算x1的误差
x2=newSolver1(x1,functionError1,-10,1,10);%在x1的邻域生成新一组解x2
functionError2=nonLinearSumError1(x2);%计算x2的误差
%检查方程是否得解
=isSolution(x1,functionError1,precision);
=isSolution(x2,functionError2,precision);
if isTrue1==1
'方程得解'
functionError1
solutiourn
i,j
return
elseif isTrue2==1
'方程得解'
solution2
functionError2
i,j
return
end
%x1
%x2
if functionError2-functionError1<0
x1=x2;%x2比x1好,用x2取代x1
elseif errorHold-functionError2<0
%x1=xHold;
else
p_x2x1=exp(-log(functionError2-functionError1)/T);
%状态转移概率,注意:误差取对数,因为要解的非线性方程组比较复杂,
%可能解的一点偏差会引起方程很大的变化。所以通过取对数缩小差距。
if rand(1)<p_x2x1 %状态转移
xHold=x1;%hHold:把比较好的解保留下来
errorHold=functionError1;%比较好的解对应的误差
x1=x2;
end
end

end
end
solution1
functionError1
solution2
functionError2

frogfish 发表于 2007-7-3 22:30

函数(1):计算待解方程的绝对总误差
function funtionError=nonLinearSumError1(X)%方程的解是-7,5,1,-3
funtionError=...
[
abs(X(:,1).^2-sin(X(:,2).^3)+X(:,3).^2-exp(X(:,4))-50.566253390821)+...
abs(X(:,1).^3+X(:,2).^2-X(:,4).^2+327)+...
abs(cos(X(:,1).^4)+X(:,2).^4-X(:,3).^3-624.679868769613)+...
abs(X(:,1).^4-X(:,2).^3+2.^X(:,3)-X(:,4).^4-2197)
];

frogfish 发表于 2007-7-3 22:30

函数(2):在x1的领域产生一组新的解
%newSolver1根据x1的误差给出一个新的可能解x
function x2=newSolver1(x1,x1Error,leftBound,distance,rightBound)
%parameter=
%leftBound:解空间的左边界,distance:可能解的间隔,rightBound:解空间的右边界
%解空间是指在一个坐标轴上解的左右边界和解之间的间隔
=size(x1);
%x1Group:x1的行数,x1N:方程的元数
%round((-0.5+rand(x1Group,x1N))*2)
if x1Error<=30%在解空间上移动1格
x2=x1+round((-0.5+rand(x1Group,x1N))*2)*distance;
k=x2<leftBound;%防止新解越过左边界
x2(:,k)=leftBound;
k=x2>rightBound;%防止新解越过右边界
x2(:,k)=rightBound;
elseif x1Error>30 && x1Error<=100%在解空间上移动3格以下
x2=x1+round((-0.5+rand(x1Group,x1N))*6)*distance;
k=x2<leftBound;
x2(:,k)=leftBound;
k=x2>rightBound;
x2(:,k)=rightBound;

elseif x1Error>100 && x1Error<=1000%在解空间上移动9格以下
x2=x1+round((-0.5+rand(x1Group,x1N))*20)*distance;
k=x2<leftBound;
x2(:,k)=leftBound;
k=x2>rightBound;
x2(:,k)=rightBound;
elseif x1Error>1000 && x1Error<=10000%在解空间上移动20格以下
x2=x1+round((-0.5+rand(x1Group,x1N))*40)*distance;
k=x2<leftBound;
x2(:,k)=leftBound;
k=x2>rightBound;
x2(:,k)=rightBound;
elseif x1Error>10000%在解空间上移动30格以下
x2=x1+round((-0.5+rand(x1Group,x1N))*60)*distance;
k=x2<leftBound;
x2(:,k)=leftBound;
k=x2>rightBound;
x2(:,k)=rightBound;
end
if x1==x2
x2=round((-0.5+rand(x1Group,x1N))*20);
end

frogfish 发表于 2007-7-3 22:31

函数(3):

%判断方程是否解开
function =isSolution(x,functionError,precision)
=min(functionError);%找到最小误差,最小误差所对应的行号
solution=x(xi,:);
if minError<precision
isTrue=1;
else
isTrue=0;
end

来自搜狐博客=〉人工智能
页: [1]
查看完整版本: 退火算法解非线性方程组