最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

数学建模算法整理

来源:动视网 责编:小OO 时间:2025-10-02 07:38:17
文档

数学建模算法整理

数学建模常用算法1.大多数建模赛题中都离不开计算机仿真,随机性模拟是非常常见的算法之一。    举个例子就是97年的A题,每个零件都有自己的标定值,也都有自己的容差等级,而求解最优的组合方案将要面对着的是一个极其复杂的公式和108种容差选取方案,根本不可能去求解析解,那如何去找到最优的方案呢?随机性模拟搜索最优方案就是其中的一种方法,在每个零件可行的区间中按照正态分布随机的选取一个标定值和选取一个容差值作为一种方案,然后通过蒙特卡罗算法仿真出大量的方案,从中选取一个最佳的。另一个例子就是去年的
推荐度:
导读数学建模常用算法1.大多数建模赛题中都离不开计算机仿真,随机性模拟是非常常见的算法之一。    举个例子就是97年的A题,每个零件都有自己的标定值,也都有自己的容差等级,而求解最优的组合方案将要面对着的是一个极其复杂的公式和108种容差选取方案,根本不可能去求解析解,那如何去找到最优的方案呢?随机性模拟搜索最优方案就是其中的一种方法,在每个零件可行的区间中按照正态分布随机的选取一个标定值和选取一个容差值作为一种方案,然后通过蒙特卡罗算法仿真出大量的方案,从中选取一个最佳的。另一个例子就是去年的
                        数学建模常用算法

1.大多数建模赛题中都离不开计算机仿真,随机性模拟是非常常见的算法之一。

     举个例子就是97 年的A 题,每个零件都有自己的标定值,也都有自己的容差等级,而求解最优的组合方案将要面对着的是一个极其复杂的公式和108 种容差选取方案,根本不可能去求解析解,那如何去找到最优的方案呢?随机性模拟搜索最优方案就是其中的一种  方法,在每个零件可行的区间中按照正态分布随机的选取一个标定值和选取一个容差值作为一种方案,然后通过蒙特卡罗算法仿真出大量的方案,从中选取一个最佳的。另一个例子就是去年的彩票第二问,要求设计一种更好的方案,首先方案的优劣取决于很多复杂的因素,同样不可能刻画出一个模型进行求解,只能靠随机仿真模拟。

1.1 蒙特卡罗算法

蒙特卡罗模拟

就是随机数相关的东西,你只要知道随机数是怎么得到。其它的事就要好办了。

rand(m,n)产生m*n均匀随机数。

ex:

用概率方法求pi

N=100000;

x=rand(N,1);

y=rand(N,1);

count=0;

for i=1:N

if (x(i)^2+y(i)^2<=1)

count=count+1;

end

end

PI=4*count/N

试给出下面中的蒙特卡洛模拟

在一次旅游途中,小王看到有人用20枚签(其中10枚标有5分分值,10枚标有10分分值)设赌。让游客从中抽出10枚,以10枚签的分值总和为奖罚金额,见表1

表1

分值   50,100         55,95     60,65,85,90        70,75,80

奖罚金额   奖100元          奖10元     不奖不罚         罚1元

你看,有奖有罚,在11个分值中有4个分值可以获奖,且最高奖额为100元;只有3个分值要受罚,而罚额仅为1元,很有吸引力吧?怪不得有些游客摩拳擦掌,跃跃欲试。那么这些奖是不是这么好拿呢?

试分析此游戏中,谁是真正的赢家?

%%假设前10个分值为5,后10个分值为10

income=0;   %% 收入

n=10000;    %% 模拟次数,即有n个人参加游戏

for i=1:n

    a=randperm(20);

    a=a(1:10);

b=find(a>10); %%10分分值的

    sumb=length(b)*10+(10-length(b))*5;

    if sumb==50||sumb==100

        income=income-100;

    elseif sumb==55||sumb==95

        income=income-10;

    elseif sumb==70||sumb==75||sumb==80

        income=income+1;

    end

end

Income

2.  数据拟合、参数估计、插值等算法 

     数据拟合在很多赛题中有应用,与图形处理有关的问题很多与拟合有关系,一个例子就是98 年美国赛A 题,生物组织切片的三维插值处理,94 年A 题逢山开路,山体海拔高度的插值计算,还有吵的沸沸扬扬可能会考的“非典”问题也要用到数据拟合算法,观察数据的走向进行处理。此类问题在MATLAB中有很多现成的函数可以调用,熟悉MATLAB,这些方法都能游刃有余的用好。 

2.1 三次样条插值在 Matlab 中的实现 

在 Matlab 中数据点称之为断点。如果三次样条插值没有边界条件,最常用的方法,就是采用非扭结(not-a-knot)条件。这个条件强迫第 1 个和第 2 个三多项式的三阶导数相等。对最后一个和倒数第 2 个三次多项式也做同样地处理。 

Matlab 中三次样条插值也有现成的函数: 

y=interp1(x0,y0,x,'spline'); 

y=spline(x0,y0,x); 

pp=csape(x0,y0,conds),y=ppval(pp,x)。 

其中x0,y0是已知数据点,x是插值点,y是插值点的函数值。 

对于三次样条插值,我们提倡使用函数csape,csape的返回值是 pp 形式,要求插值点的函数值,必须调用函数 ppval。 

pp=csape(x0,y0):使用默认的边界条件,即 Lagrange 边界条件。 

pp=csape(x0,y0,conds)中的 conds 指定插值的边界条件,其值可为: 

'complete'    边界为一阶导数,即默认的边界条件 

'not-a-knot'   非扭结条件  

'periodic'     周期条件 

'second'      边界为二阶导数,二阶导数的值[0, 0]。 

'variational'   设置边界的二阶导数值为[0,0]。 

对于一些特殊的边界条件,可以通过 conds 的一个

1×2矩阵来表示,conds 元素的取值为 1,2。此时,使用命令 

pp=csape(x0,y0_ext,conds) 

其中 y0_ext=[left,y0,right],这里 left 表示左边界的取值,right 表示右边界的取值。 

conds(i)=j 的含义是给定端点i 的 j 阶导数, 即 conds 的第一个元素表示左边界的条

件,第二个元素表示右边界的条件,conds=[2,1]表示左边界是二阶导数,右边界是一阶

导数,对应的值由 left 和 right 给出。

2.2 二维插值 

前面讲述的都是一维插值,即节点为一维变量,插值函数是一元函数(曲线) 。若节点是二维的,插值函数就是二元函数,即曲面。如在某区域测量了若干点(节点)的高程(节点值) ,为了画出较精确的等高线图,就要先插入更多的点(插值点) ,计算这些点的高程(插值)。

 

2.1.1  插值节点为网格节点 

已知m×n个节点:  (i=1,2.....m;j=1,2.....n)并且

。求点(x,y)处的插值z 。 

Matlab 中有一些计算二维插值的程序。如 

   z=interp2(x0,y0,z0,x,y,'method') 

其中 x0,y0 分别为m 维和n 维向量,表示节点,z0 为n×m维矩阵,表示节点值,x,y为一维数组,表示插值点,x 与 y 应是方向不同的向量,即一个是行向量,另一个是列向量,z 为矩阵,它的行数为 y 的维数,列数为 x 的维数,表示得到的插值,'method'的用法同上面的一维插值。 

如果是三次样条插值,可以使用命令 

pp=csape({x0,y0},z0,conds,valconds),z=fnval(pp,{x,y}) 

其中 x0,y0 分别为m 维和n 维向量,z0 为

m×n维矩阵,z 为矩阵,它的行数为x 的维数,列数为 y 的维数,表示得到的插值,具体使用方法同一维插值。 

例2 在一丘陵地带测量高程,x 和 y 方向每隔100米测一个点,得高程如2表,试插值一曲面,确定合适的模型,并由此找出最高点和该点的高程。 

解:编写程序如下: 

clear,clc 

x=100:100:500; 

y=100:100:400; 

z=[636    697    624    478   450   

   698    712    630    478   420 

   680    674    598    412   400 

   662    626    552    334   310]; 

pp=csape({x,y},z') 

xi=100:10:500;yi=100:10:400 

cz1=fnval(pp,{xi,yi}) 

cz2=interp2(x,y,z,xi,yi','spline') 

[i,j]=find(cz1==max(max(cz1))) 

x=xi(i),y=yi(j),zmax=cz1(i,j) 

2.1.2  插值节点为散乱节点 

已知n 个节点: (i=1,2.....n)

求点(x,y)处的插值z 。 

对上述问题,Matlab 中提供了插值函数 griddata,其格式为: 

ZI = GRIDDATA(X,Y,Z,XI,YI) 

其中 X、Y、Z 均为 n 维向量,指明所给数据点的横坐标、纵坐标和竖坐标。向量 XI、YI 是给定的网格点的横坐标和纵坐标,返回值 ZI 为网格(XI,YI)处的函数值。XI与 YI 应是方向不同的向量,即一个是行向量,另一个是列向量。 

例3 在某海域测得一些点(x,y)处的水深 z 由下表给出,在矩形区域(75,200)

×(-50,150) 内画出海底曲面的图形。 

 

解:编写程序如下: 

x=[129  140  103.5  88  185.5  195  105  157.5  107.5  77  81  162  162  117.5]; 

y=[7.5  141.5  23   147  22.5  137.5  85.5  -6.5  -81   3  56.5  -66.5  84 -33.5]; 

z=-[4     8    6     8    6     8     8     9     9   8    8    9    4    9]; 

xi=75:1:200; 

yi=-50:1:150; 

zi=griddata(x,y,z,xi,yi','cubic') 

subplot(1,2,1), plot(x,y,'*') 

subplot(1,2,2), mesh(xi,yi,zi)

2.2 最小二乘法的 Matlab 实现 

2.2.1 解方程组方法  

在上面的记号下, 

 

Matlab 中的线性最小二乘的标准型为 

          

命令为:A=R\\Y。

例 4  用最小二乘法求一个形如:

的经验公式,使它与如下所示的数据拟合。 

x     19     25    31     38    44 

y    19.0   32.3   49.0   73.3   97.8 

 

解  编写程序如下 

x=[19     25    31     38    44]'; 

y=[19.0   32.3   49.0   73.3   97.8]'; 

r=[ones(5,1),x.^2]; 

ab=r\\y 

x0=19:0.1:44; 

y0=ab(1)+ab(2)*x0.^2; 

plot(x,y,'o',x0,y0,'r') 

2.2.2 多项式拟合方法 

如果取:{}={}

即用m 次多项式拟合给定数据, Matlab中有现成的函数 

a=polyfit(x0,y0,m) 

其中输入参数 x0,y0 为要拟合的数据,m 为拟合多项式的次数,输出参数 a 为拟合多项式 y=amxm+…+a1x+a0系数 a=[ am, …, a1, a0]。 

多项式在 x 处的值 y 可用下面的函数计算 

y=polyval(a,x)。 

2.3   规划类问题算法 

     竞赛中很多问题都和数学规划有关,可以说不少的模型都可以归结为一组不等式作为约束条件、几个函数表达式作为目标函数的问题,遇到这类问题,求解就是关键了,比如98年B 题,用很多不等式完全可以把问题刻画清楚,因此列举出规划后用Lindo、Lingo 等软件来进行解决比较方便,所以还需要熟悉这两个软件。

2.3.1 求解线性规划的 Matlab 解法 

单纯形法是求解线性规划问题的最常用、最有效的算法之一。下面我们介绍线性规划的 Matlab            

解法。 

Matlab 中线性规划的标准型为:

基本函数形式为 linprog(c,A,b), 它的返回值是向量 x 的值。 还有其它的一些函数调用形式(在 Matlab 指令窗运行 help linprog 可以看到所有的函数调用形式),如: 

[x,fval]=linprog(c,A,b,Aeq,beq,LB,UB,X0,OPTIONS) 

这里 fval 返回目标函数的值, LB 和 UB 分别是变量 x 的下界和上界,x0是x的初始值,OPTIONS 是控制参数。

例 2  求解下列线性规划问题

解 (i)编写 M 文件 

c=[2;3;-5]; 

a=[-2,5,-1;1,3,1]; b=[-10;12]; 

aeq=[1,1,1]; 

beq=7; 

x=linprog(-c,a,b,aeq,beq,zeros(3,1)) 

value=c'*x 

§4 蒙特卡洛法(随机取样法) 

前面介绍的常用的整数规划求解方法, 主要是针对线性整数规划而言, 而对于非线性整数规划目前尚未有一种成熟而准确的求解方法, 因为非线性规划本身的通用有效解法尚未找到,更何况是非线性整数规划。 

然而, 尽管整数规划由于变量为整数而增加了难度; 然而又由于整数解是有限个,于是为枚举法提供了方便。当然,当自变量维数很大和取值范围很宽情况下,企图用显枚举法(即穷举法)计算出最优值是不现实的,但是应用概率理论可以证明,在一定的计算量的情况下,完全可以得出一个满意解。 

例 7  已知非线性整数规划为: 

 

如果用显枚举法试探,共需计算个点,其计算量非常之大。然而应用蒙特卡洛去随机计算个点,便可找到满意解,那么这种方法的可信度究竟怎样呢?下面就分析随机取样采集个点计算时,应用概率理论来估计一下可信度。不失一般性,假定一个整数规划的最优点不是孤立的奇点。假设目标函数落在高值区的概率分别为 0.01,0.00001,则当计算 个点后,有任一个点能落在高值区的概率分别为:

解  (i)首先编写 M 文件 mente.m 定义目标函数 f 和约束向量函数 g,程序如下:  

function [f,g]=mengte(x); 

f=x(1)^2+x(2)^2+3*x(3)^2+4*x(4)^2+2*x(5)-8*x(1)-2*x(2)-3*x(3)-... 

x(4)-2*x(5); 

g=[sum(x)-400 

x(1)+2*x(2)+2*x(3)+x(4)+6*x(5)-800 

2*x(1)+x(2)+6*x(3)-200 

x(3)+x(4)+5*x(5)-200]; 

(ii)编写M文件mainint.m如下求问题的解: 

rand('state',sum(clock)); 

p0=0; 

tic 

for i=1:10^6 

   x=99*rand(5,1); 

x1=floor(x);x2=ceil(x); 

[f,g]=mengte(x1); 

if sum(g<=0)==4

if p0<=f

      x0=x1;p0=f; 

   end 

end 

[f,g]=mengte(x2); 

if sum(g<=0)==4

if p0<=f

      x0=x2;p0=f; 

   end 

end 

end 

x0,p0 

toc 

 

本题可以使用LINGO软件求得精确的全局最有解,程序如下: 

model: 

sets: 

row/1..4/:b; 

col/1..5/:c1,c2,x; 

link(row,col):a; 

endsets 

data: 

c1=1,1,3,4,2; 

c2=-8,-2,-3,-1,-2; 

a=1 1 1 1 1 

  1 2 2 1 6 

  2 1 6 0 0 

                                                                               

  0 0 1 1 5; 

b=400,800,200,200; 

enddata 

max=@sum(col:c1*x^2+c2*x); 

@for(row(i):@sum(col(j):a(i,j)*x(j))@for(col:@gin(x)); 

@for(col:@bnd(0,x,99)); 

end 

解  (i)编写 M 文件 fun1.m 定义目标函数 

function f=fun1(x); 

f=sum(x.^2)+8; 

 

(ii)编写M文件fun2.m定义非线性约束条件 

function [g,h]=fun2(x); 

g=[-x(1)^2+x(2)-x(3)^2 

x(1)+x(2)^2+x(3)^3-20];  %非线性不等式约束 

h=[-x(1)-x(2)^2+2 

x(2)+2*x(3)^2-3]; %非线性等式约束 

(iii)编写主程序文件 example2.m 如下: 

options=optimset('largescale','off'); 

[x,y]=fmincon('fun1',rand(3,1),[],[],[],[],zeros(3,1),[], ... 

'fun2', options) 

解:编写 M 文件 fun2.m 如下: 

function [f,g]=fun2(x); 

f=100*(x(2)-x(1)^2)^2+(1-x(1))^2; 

g=[-400*x(1)*(x(2)-x(1)^2)-2*(1-x(1));200*(x(2)-x(1)^2)]; 

编写主函数文件example6.m如下: 

options = optimset('GradObj','on'); 

[x,y]=fminunc('fun2',rand(1,2),options) 即可求得函数的极小值。 

在求极值时,也可以利用二阶导数,编写 M 文件 fun3.m 如下: 

function [f,df,d2f]=fun3(x); 

f=100*(x(2)-x(1)^2)^2+(1-x(1))^2; 

df=[-400*x(1)*(x(2)-x(1)^2)-2*(1-x(1));200*(x(2)-x(1)^2)]; 

d2f=[-400*x(2)+1200*x(1)^2+2,-400*x(1) 

-400*x(1),200]; 

编写主函数文件example62.m如下: 

options = optimset('GradObj','on','Hessian','on'); 

[x,y]=fminunc('fun3',rand(1,2),options) 

即可求得函数的极小值。 

 

求多元函数的极值也可以使用 Matlab 的 fminsearch 命令,其使用格式为: 

[X,FVAL,EXITFLAG,OUTPUT]=FMINSEARCH(FUN,X0,OPTIONS,P1,P2,...) 

function f=fun4(x); 

f=sin(x)+3; 

 

编写主函数文件example7.m如下: 

x0=2; 

[x,y]=fminsearch(@fun4,x0)  

即求得在初值 2 附近的极小点及极小值。

Matlab 中求解二次规划的命令是 

[X,FVAL]= QUADPROG(H,f,A,b,Aeq,beq,LB,UB,X0,OPTIONS) 

返回值 X 是决策向量 x 的值,返回值 FVAL 是目标函数在 x 处的值。 (具体细节可以参

看在 Matlab 指令中运行 help quadprog 后的帮助) 。 

例 8  求解二次规划 

h=[4,-4;-4,8]; 

f=[-6;-3]; 

a=[1,1;4,1]; 

b=[3;9]; 

[x,value]=quadprog(h,f,a,b,[],[],zeros(2,1)) 

解  (1)编写 M 文件 fun6.m 定义目标函数如下: 

function f=fun6(x,s); 

f=sum((x-0.5).^2); 

(2)编写 M 文件 fun7.m 定义约束条件如下: 

function [c,ceq,k1,k2,s]=fun7(x,s); 

c=[];ceq=[]; 

if isnan(s(1,1)) 

    s=[0.2,0;0.2 0]; 

end 

%取样值 

w1=1:s(1,1):100; 

w2=1:s(2,1):100; 

%半无穷约束 

k1=sin(w1*x(1)).*cos(w1*x(2))-1/1000*(w1-50).^2-sin(w1*x(3))-x(3)-1; 

k2=sin(w2*x(2)).*cos(w2*x(1))-1/1000*(w2-50).^2-sin(w2*x(3))-x(3)-1; 

%画出半无穷约束的图形 

plot(w1,k1,'-',w2,k2,'+'); 

(3)调用函数 fseminf 

在 Matlab 的命令窗口输入 

[x,y]=fseminf(@fun6,rand(3,1),2,@fun7) 

即可。 

解  (1)编写 M 文件 fun8.m 定义向量函数如下: 

function f=fun8(x); 

f=[2*x(1)^2+x(2)^2-48*x(1)-40*x(2)+304 

    -x(1)^2-3*x(2)^2 

    x(1)+3*x(2)-18 

    -x(1)-x(2) 

    x(1)+x(2)-8]; 

(2)调用函数 fminimax 

[x,y]=fminimax(@fun8,rand(2,1)) 

解  (1)编写 M 文件 fun9.m 定义目标函数及梯度函数: 

function [f,df]=fun9(x); 

f=exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1); 

df=[exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+8*x(1)+6*x(2)+1);exp(x(1))*(4*x(2)

+4*x(1)+2)]; 

(2)编写 M 文件 fun10.m 定义约束条件及约束条件的梯度函数: 

function [c,ceq,dc,dceq]=fun10(x); 

c=[x(1)*x(2)-x(1)-x(2)+1.5;-x(1)*x(2)-10]; 

dc=[x(2)-1,-x(2);x(1)-1,-x(1)]; 

ceq=[];dceq=[]; 

(3)调用函数 fmincon,编写主函数文件 example13.m 如下: 

%采用标准算法 

options=optimset('largescale','off'); 

%采用梯度 

options=optimset(options,'GradObj','on','GradConstr','on'); 

[x,y]=fmincon(@fun9,rand(2,1),[],[],[],[],[],[],@fun10,options) 

3.4 Matlab 优化工具箱的用户图形界面解法:

Matlab 优化工具箱中的 optimtool 命令提供了优化问题的用户图形界面解法。

optimtool 可应用到所有优化问题的求解,计算结果可以输出到 Matlab 工作空间中。

2.4   图论问题 

     98 年B 题、00 年B 题、95 年锁具装箱等问题体现了图论问题的重要性,这类问题算法有很多,包括:Dijkstra、Floyd、Prim、Bellman-Ford,最大流,二分匹配等问题。每一个算法都应该实现一遍,否则到比赛时再写就晚了。

2.4.1 两个指定点间的最短路径

Dijkstra算法(单源最短路径边权非负)

w=[0 8 inf inf inf inf 7 inf inf inf inf;inf 0 3 inf inf inf 6 inf inf inf inf;...

    inf inf 0 5 6 inf inf inf inf inf inf;inf inf inf 0 1 inf inf inf inf inf 12;...

    inf inf inf inf 0 2 inf inf inf 9 inf;inf inf inf inf inf 0 9 inf 3 inf inf;...

    inf inf 5 inf inf inf 0 10 inf inf inf;8 inf inf inf inf inf inf 0 inf inf inf;...

    inf inf inf inf 7 inf inf 9 0 inf inf;inf inf inf inf inf inf inf inf 2 0 2;...

    inf inf inf inf 10 inf inf inf inf inf 0]

n=size(w,1);

w1=w(1,:);

for i=1:n

    dist(i)=w1(i);

    path(i)=1;

end

s=[];

s(1)=1;

u=s(1);

k=1

dist

path

while k    for i=1:n

        for j=1:k

            if i~=s(j)

if dist(i)>dist(u)+w(u,i)

                    dist(i)=dist(u)+w(u,i);

                    path(i)=u;

                end

            end

        end

    end

    dist

    path

   distdist=dist;

    for i=1:n

        for j=1:k

            if i~=s(j)

               distdist(i)=distdist(i);

            else

               distdist(i)=inf;

            end

        end

    end

       distv=inf;

        for i=1:n

if distdist(i)                distv=distdist(i)

                v=i;

            end

        end

       distv

        v

        s(k+1)=v

        k=k+1

        u=s(k)

    end

    dist

    path

Linggo代码:

编写 LINGO 程序如下: 

model: 

sets: 

cities/A,B1,B2,C1,C2,C3,D/; 

roads(cities,cities)/A B1,A B2,B1 C1,B1 C2,B1 C3,B2 C1, 

B2 C2,B2 C3,C1 D,C2 D,C3 D/:w,x; 

endsets 

data: 

w=2 4 3 3 1 2 3 1 1 3 4; 

enddata 

n=@size(cities); !城市的个数; 

min=@sum(roads:w*x); 

@for(cities(i)|i #ne#1 #and# i #ne#n: 

@sum(roads(i,j):x(i,j))=@sum(roads(j,i):x(j,i))); 

@sum(roads(i,j)|i #eq#1:x(i,j))=1; 

@sum(roads(i,j)|j #eq#n:x(i,j))=1; 

end 

 

 编写 LINGO 程序如下: 

model: 

sets: 

cities/1..11/; 

roads(cities,cities):w,x; 

endsets 

data: 

w=0; 

enddata 

calc: 

w(1,2)=2;w(1,3)=8;w(1,4)=1; 

w(2,3)=6;w(2,5)=1; 

w(3,4)=7;w(3,5)=5;w(3,6)=1;w(3,7)=2; 

w(4,7)=9; 

w(5,6)=3;w(5,8)=2;w(5,9)=9; 

w(6,7)=4;w(6,9)=6; 

w(7,9)=3;w(7,10)=1; 

w(8,9)=7;w(8,11)=9; 

w(9,10)=1;w(9,11)=2;w(10,11)=4; 

@for(roads(i,j):w(i,j)=w(i,j)+w(j,i)); 

@for(roads(i,j):w(i,j)=@if(w(i,j) #eq# 0, 1000,w(i,j))); 

endcalc 

n=@size(cities);  !城市的个数; 

min=@sum(roads:w*x); 

@for(cities(i)|i #ne#1 #and# i #ne# 

n:@sum(cities(j):x(i,j))=@sum(cities(j):x(j,i))); 

@sum(cities(j):x(1,j))=1; 

@sum(cities(j):x(j,1))=0; !不能回到顶点1; 

@sum(cities(j):x(j,n))=1; 

@for(roads:@bin(x)); 

end 

 

与有向图相比较,在程序中只增加了一个语句@sum(cities(j):x(j,1))=0,即

从顶点 1 离开后,再不能回到该顶点。 

求得的最短路径为 1→2→5→6→3→7→10→9→11,最短路径长度为 13。

2.4.2 Flord算法

%a=[0 50 inf inf inf;inf 0 inf inf 80;inf 30 0 20 inf;inf inf inf 0 70;65 inf 100 inf 0];

function [D,path]=floyd(a)    %  Floyd’s Algorithm

n=size(a,1);

%设置D和Path的初值

D=a;path=zeros(n,n);

for  i=1:n

  for j=1:n

     if D(i,j)~=inf

     path(i,j)=j;   %j是i的后继点

     end

  end

end

%做n次迭代,每次迭代均更新D(i,j)和path(i,j)

for k=1:n

    for i=1:n

       for j=1:n

          if D(i,k)+D(k,j)          k,i,j

          D(i,j)=D(i,k)+D(k,j)  %修改长度

          path(i,j)=path(i,k)    %修改路径

          end

       end

    end

end

%a=[0 50 inf inf inf;inf 0 inf inf 80;inf 30 0 20 inf;inf inf inf 0 70;65 inf 100 inf 0];

%[D,path]=floyd(a)

2.4.3 prim算法(最优选线问题,最小生成树)

clear;

a=[0  8  inf  1  5;

   8  0  6  inf  7;

  inf  6  0  9  10;

   1  inf  9  0  3;

   5  7  10  3  0];

T=[];c=0;v=1;n=5;sb=2:n; 

for j=2:n    

    b(1,j-1)=1;

    b(2,j-1)=j;

    b(3,j-1)=a(1,j);

end

while size(T,2)     [tmin,i]=min(b(3,:));    

     T(:,size(T,2)+1)=b(:,i);

     c=c+b(3,i);

     v=b(2,i);     

   temp=find(sb == b(2,i));

   sb(temp)=[];b(:,i)=[];

   for j=1:length(sb) 

       d=a(v,b(2,j));

if d          b(1,j)=v;b(3,j)=d;

       end

   end

end

T,c

2.4.4 Bellman-Ford算法(单源最短路径边权可正可负)

function [D,R]= floydwarshall(A)

% %采用floyd算法计算图中任意两点之间最短路程,可以有负权。

%参数D为连通图的权矩阵

%R是路由矩阵

D=A; n=length(D); %赋初值

for(i=1:n)for(j=1:n)R(i,j)=j;end;end %赋路径初值

for(k=1:n)

for(i=1:n)

for(j=1:n)

if(D(i,k)+D(k,j) R(i,j)=k;end;end;end %更新rij,需要通过k

 k; %显示迭代步数

 D; %显示每步迭代后的路长

 R; %显示每步迭代后的路径

 pd=0;for i=1:n %含有负权时

 if(D(i,i)<0)pd=1;break;end;end %跳出内层的for循环 存在一条含有顶点vi的负回路

 if(pd==1) fprintf('有负回路');break;end %存在一条负回路, 跳出最外层循环 终止程序

end %程序结束

2.4.5 最大流算法

function [flow,val]=mincostmaxflow(rongliang,cost,flowvalue);

%第一个参数:容量矩阵;第二个参数:费用矩阵;

%前两个参数必须在不通路处置零

%第三个参数:指定容量值(可以不写,表示求最小费用最大流)

%返回值flow 为可行流矩阵,val 为最小费用值

global M

flow=zeros(size(rongliang));allflow=sum(flow(1,:));

if nargin<3

flowvalue=M;

end

while allfloww=(flow0).*cost)';

path=floydpath(w);%调用floydpath 函数

if isempty(path)

val=sum(sum(flow.*cost));

return;

end

theta=min(min(path.*(rongliang-flow)+(path.*(rongliang-flow)==0).*M));

theta=min([min(path'.*flow+(path'.*flow==0).*M),theta]);

flow=flow+(rongliang>0).*(path-path').*theta;

allflow=sum(flow(1,:));

end

val=sum(sum(flow.*cost));

2.4.6 二分匹配

二分图最大匹配 匈牙利算法

#include

#include

const int N=502;

int map[N][N];

int link[N],useif[N];

int n,m;

int can(int t)

{

for(int i=1;i<=m;i++)

{

if(useif[i]==0 && map[t][i])

{

useif[i]=1;

if(link[i]==-1 || can(link[i]))

{

link[i]=t;

return 1;

}

}

}

return 0;

}

int maxmatch()

{

int i,num;

num=0;

memset(link,-1,sizeof(link));

for(i=1;i<=n;i++)

{

memset(useif,0,sizeof(useif));

if(can(i))

num++;

}

return num;

}

int main()

{

int k,a,b;

while(scanf("%d",&k),k)

{

scanf("%d%d",&n,&m);

memset(map,0,sizeof(map));

while(k--)

{

scanf("%d%d",&a,&b);

map[a][b]=1;

}

printf("%d\\n",maxmatch());

}

return 0;

}

2.5   计算机算法设计中的问题 

     计算机算法设计包括很多内容:动态规划、回溯搜索、分治算法、分支定界。比如92 年B 题用分枝定界法,97 年B 题是典型的动态规划问题,此外98 年B 题体现了分治算法。这方面问题和ACM 程序设计竞赛中的问题类似,推荐看一下《计算机算法设计与分析》(电子工业出版社)等与计算机算法有关的书。 

2.5.1 动态规划

如果一个问题能用动态规划方法求解,那么,我们可以按下列步骤首先建立起动态规划的数学模型: 

(i)将过程划分成恰当的阶段。 

(ii)正确选择状态变量,使它既能描述过程的状态,又满足无后效性,同时确定允许状态集合

(iii)选择决策变量,确定允许决策集合

(iv)写出状态转移方程。 

(v)确定阶段指标及指标函数的形式(阶段指标之和,阶段指标之积,阶段指标之极大或极小等)。 

(vi)写出基本方程即最优值函数满足的递归方程,以及端点条件。 

model: 

Title Dynamic Programming; 

sets: 

vertex/A,B1,B2,C1,C2,C3,C4,D1,D2,D3,E1,E2,E3,F1,F2,G/:L; 

road(vertex,vertex)/A B1,A B2,B1 C1,B1 C2,B1 c3,B2 C2,B2 C3,B2 C4, 

C1 D1,C1 D2,C2 D1,C2 D2,C3 D2,C3 D3,C4 D2,C4 D3, 

D1 E1,D1 E2,D2 E2,D2 E3,D3 E2,D3 E3, 

E1 F1,E1 F2,E2 F1,E2 F2,E3 F1,E3 F2,F1 G,F2 G/:D; 

endsets 

data: 

D=5 3 1 3 6 8 7 6 

6 8 3 5 3 3 8 4 

2 2 1 2 3 3 

3 5 5 2 6 6 4 3; 

L=0,,,,,,,,,,,,,,,; 

enddata 

@for(vertex(i)|i#GT#1:L(i)=@min(road(j,i):L(j)+D(j,i))); 

End

2.5.2分支定界

2.6.2 神经网络

下面利用上文所叙述的网络结构及方法,对蠓虫分类问题求解。编写 Matlab 程序

如下:

clear 

p1=[1.24,1.27;1.36,1.74;1.38,1.;1.38,1.82;1.38,1.90; 

   1.40,1.70;1.48,1.82;1.54,1.82;1.56,2.08]; 

p2=[1.14,1.82;1.18,1.96;1.20,1.86;1.26,2.00 

   1.28,2.00;1.30,1.96]; 

p=[p1;p2]'; 

pr=minmax(p); 

goal=[ones(1,9),zeros(1,6);zeros(1,9),ones(1,6)]; 

plot(p1(:,1),p1(:,2),'h',p2(:,1),p2(:,2),'o') 

net=newff(pr,[3,2],{'logsig','logsig'}); 

net.trainParam.show = 10; 

net.trainParam.lr = 0.05; 

net.trainParam.goal = 1e-10; 

net.trainParam.epochs = 50000; 

net = train(net,p,goal); 

x=[1.24 1.80;1.28 1.84;1.40 2.04]'; 

y0=sim(net,p) 

y=sim(net,x) 

层次分析法:

根据层次总排序权值,该生最满意的工作为工作 1。 

计算的 Matlab 程序如下: 

clc,clear 

fid=fopen('txt3.txt','r');  

n1=6;n2=3; 

a=[]; 

for i=1:n1 

   tmp=str2num(fgetl(fid));   

   a=[a;tmp]; %读准则层判断矩阵 

end 

for i=1:n1 

    str1=char(['b',int2str(i),'=[];']); 

    str2=char(['b',int2str(i),'=[b',int2str(i),';tmp];']); 

    eval(str1); 

    for j=1:n2 

        tmp=str2num(fgetl(fid)); 

        eval(str2); %读方案层的判断矩阵 

    end 

 end 

ri=[0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45]; %一致性指标 

[x,y]=eig(a); 

lamda=max(diag(y)); 

num=find(diag(y)==lamda); 

w0=x(:,num)/sum(x(:,num)); 

cr0=(lamda-n1)/(n1-1)/ri(n1) 

for i=1:n1 

    [x,y]=eig(eval(char(['b',int2str(i)]))); 

    lamda=max(diag(y)); 

    num=find(diag(y)==lamda); 

    w1(:,i)=x(:,num)/sum(x(:,num)); 

    cr1(i)=(lamda-n2)/(n2-1)/ri(n2); 

end 

cr1, ts=w1*w0, cr=cr1*w0 

 

纯文本文件txt3.txt中的数据格式如下: 

1   1      1     4   1      1/2 

1   1      2     4   1      1/2 

1   1/2     1     5   3      1/2 

1/4   1/4  1/5     1  1/3      1/3 

1   1      1/3   3     1      1 

2   2      2     3     3      1 

1   1/4   1/2 

4   1      3 

2   1/3     1 

1   1/4    1/5 

4   1      1/2 

5   2      1 

1   3      1/3 

1/3  1      1/7 

3   7      1 

1   1/3    5 

3   1      7 

1/5   1/7   1 

1   1      7 

1   1      7 

1/7  1/7    1 

1   7      9 

1/7   1     1 

1/9   1     1 

模糊算法(折衷型多目标决策优化)

mohu.txt 

290 85 90 100 85 90 100 75 80 85 75 80 85                              

288 85 90 100 75 80 85 85 90 100 60 70 75

288 75 80 85 85 90 100 50 55 60 60 70 75

285 85 90 100 75 80 85 75 80 85 75 80 85

283 75 80 85 85 90 100 75 80 85 75 80 85

283 75 80 85 50 55 60 85 90 100 75 80 85

280 85 90 100 75 80 85 60 70 75  75 80 85

280 75 80 85 85 90 100 85 90 100 60 70 75

280 75 80 85 75 80 85 85 90 100 75 80 85

280 50 55 60 75 80 85 85 90 100 60 70 75

278 50 55 60 60 70 75 75 80 85 85 90 100

277 85 90 100 75 80 85 60 70 75 85 90 100

275 75 80 85 60 70 75 50 55 60 85 90 100

275 50 55 60 75 80 85 85 90 100 75 80 85

274 85 90 100 75 80 85 60 70 75 75 80 85

273 75 80 85 85 90 100 75 80 85 60 70 75

%数据存在纯文本文件 mohu.txt 中

clc,clear 

load mohu.txt 

sj=[repmat(mohu(:,1),1,3),mohu(:,2:end)]; 

%首先进行归一化处理 

m=size(sj,1); n=size(sj,2)/3;

w=[0.5*ones(1,3),0.125*ones(1,12)]; 

w=repmat(w,m,1); 

y=[]; 

%收益型指标对应的模糊指标值归一化处理

for i=1:n 

    tm=sj(:,3*i-2:3*i); 

    max_t=max(tm); 

    max_t=repmat(max_t,m,1); 

    max_t=max_t(:,3:-1:1); 

    yt=tm./max_t;    yt(:,3)=min([yt(:,3)',ones(1,m)]); 

    y=[y,yt]; 

end 

%成本型指标对应的模糊指标值归一化处理

% for i=1:n 

%     tm=sj(:,3*i-2:3*i); 

%     min_t=min(tm);

%     min_t=repmat(min_t,m,1);

%     tm=tm(:,3:-1:1);

%     yt=min_t./tm;    yt(:,3)=min([yt(:,3)',ones(1,m)]); 

%     y=[y,yt]; 

% end 

%下面求模糊决策矩阵 

r=[]; 

for i=1:n 

    tm1=y(:,3*i-2:3*i);tm2=w(:,3*i-2:3*i); 

    r=[r,tm1.*tm2]; 

end 

%求 M+、M-和距离 

mplus=max(r);mminus=min(r); 

 

 

dplus=dist(mplus,r');dminus=dist(mminus,r'); 

%求隶属度 

mu=dminus./(dplus+dminus); 

[mu_sort,ind]=sort(mu,'descend') 

文档

数学建模算法整理

数学建模常用算法1.大多数建模赛题中都离不开计算机仿真,随机性模拟是非常常见的算法之一。    举个例子就是97年的A题,每个零件都有自己的标定值,也都有自己的容差等级,而求解最优的组合方案将要面对着的是一个极其复杂的公式和108种容差选取方案,根本不可能去求解析解,那如何去找到最优的方案呢?随机性模拟搜索最优方案就是其中的一种方法,在每个零件可行的区间中按照正态分布随机的选取一个标定值和选取一个容差值作为一种方案,然后通过蒙特卡罗算法仿真出大量的方案,从中选取一个最佳的。另一个例子就是去年的
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top