泛函是一种映射,它以函数为自变量,数为因变量,把函数映射为数。
例如
F[y]=∫abydx 就是一个 C[a,b]→R 泛函,其中 C[a,b] 表示区间 [a,b] 上所有连续函数组成的集合。
若一个泛函依赖函数的前 n 阶导数,则通常将其定义域写为 Cn[a,b],这表示区间 [a,b] 上所有 n 阶连续可导函数组成的集合。许多重要的 Cn[a,b]→R 泛函都可以用定积分表示为
F[y]=∫abL(x,y,y′,y′′,⋯,y(n))dx 本文将推导 L=L(x,y,y′) 这类泛函的导数,并用得到的结果求解最速降线问题与狄多问题。
泛函的微分:变分#
变分就是泛函的微分。类比于多元函数的微分,变分定义为自变量(函数)沿某一方向的微小扰动所引起因变量(数)变化的线性主部。
设
yε(x)=y(x)+εη(x) 于是自变量的微小变化为
δy(x)=εη(x) 从而因变量变为
F[yε]=F[y+εη]=∫abL(x,y+εη,y′+εη′)dx 定义关于 ε 的函数 Φ
Φ(ε)=F[y+εη] 从而因变量的变化量为
Φ(ε)−Φ(0)=Φ′(0)ε+o(ε) 其线性主部,即变分为
δF=Φ′(0)ε 于是对 Φ 求导
Φ′(ε)=dεdF[y+εη]=∫ab∂ε∂L(x,y+εη,y′+εη′)dx 由链式法则
∂ε∂L=∂x∂L∂ε∂x+∂yε∂L∂ε∂yε+∂yε′∂L∂ε∂yε′ 代入
∂ε∂x∂ε∂yε∂ε∂yε′=0=η=η′ 得到
∂ε∂L=∂yε∂Lη+∂yε′∂Lη′ 从而有
Φ′(ε)=∫ab(∂yε∂Lη+∂yε′∂Lη′)dx 令 ε→0 得到
Φ′(0)Φ′(0)ε=∫ab(∂y∂Lη+∂y′∂Lη′)dx=∫ab(∂y∂Lεη+∂y′∂Lεη′)dx 代入 δy(x)=εη(x) 得到最终的变分
δF=∫ab(∂y∂Lδy+∂y′∂Lδy′)dx 泛函的极值点:欧拉-拉格朗日方程#
泛函取到极值的一个必要条件就是变分为零。但上述变分的积分项中同时包含了 δy 和 δy′,不方便判断取到零的条件。因此接下来要尝试消去 δy′。
首先将 δF 展开为两个积分项
δF=∫ab∂y∂Lδydx+∫ab∂y′∂Lδy′dx 然后对含 δy′ 的项进行分部积分
∫ab∂y′∂Lδy′dx=[∂y′∂Lδy]ab−∫abdxd(∂y′∂L)δydx 代回原式
δF=∫ab∂y∂Lδydx+[∂y′∂Lδy]ab−∫abdxd(∂y′∂L)δydx=∫ab[∂y∂L−dxd(∂y′∂L)]δydx+[∂y′∂Lδy]ab 其中
[∂y′∂Lδy]ab=∂y′∂L(b)δy(b)−∂y′∂L(a)δy(a) 固定边界变分#
对于常见的变分问题,自变量函数在区间边界上固定,即满足固定边界条件 δy(a)=0 和 δy(b)=0,从而
[∂y′∂Lδy]ab=0 于是
δF=∫ab[∂y∂L−dxd(∂y′∂L)]δydx 由于区间 (a,b) 内的 δy 可以任意变化,因此 δF=0 要求和 δy 相乘的部分必须为零(这就是变分法基本引理),从而得到欧拉-拉格朗日方程
∂y∂L−dxd(∂y′∂L)=0 类比于普通微积分中的导数定义,这里可以推广符号,将上式左边定义为泛函的导数
δyδF=∂y∂L−dxd(∂y′∂L) 这样泛函的变分就可视为泛函变分密度的积分
δF=∫abδyδFδydx 类似于多变量函数,其全微分为各自变量的偏微分之和
dF=i=1∑n∂yi∂Fdyi 只不过泛函的自变量是无穷维的、需要用连续变量标记的向量,因此不同于有限维向量中的求和,需要使用积分。
自由边界变分#
如果不假设边界固定,让右端点 x=b 可以自由变化(包括横向和纵向的变化),那么此时问题会更复杂一点。
由于右端点的横坐标 b 可以变化,因此泛函需要改写为
F[y,b]=∫abL(x,y,y′)dx 然后类似地定义 b 的变化量
bε=b+εζ 从而
δb=εζ 泛函变为
F[y,bε]=F[y,b+εζ]=∫ab+εζL(x,y,y′)dx 同样定义一个辅助函数 Φ
Φ(ε)=F[y,b+εζ] 泛函的变化量为
F[y,b+εζ]−F[y,b]Φ(ε)−Φ(0)=∫ab+εζL(x,y,y′)dx−∫abL(x,y,y′)dx=∫bb+εζL(x,y,y′)dx 展开 Φ(ε)−Φ(0) 得到线性主部
Φ(ε)−Φ(0)=Φ′(0)ε+o(ε) 而
Φ′(ε)=dεdF[y,b+εζ]=∂ε∂∫bb+εζL(x,y,y′)dx=ζL(b+εζ,y(b+εζ),y′(b+εζ)) 得到端点变化产生的变分
Φ′(0)ε=L(b,y(b),y′(b))δb 与曲线变化产生的变分加在一起,得到总的变分
δF=L(b,y(b),y′(b))δb+∫ab(∂y∂Lδy+∂y′∂Lδy′)dx 然后进行同样的分部积分,但由于右端点不固定,所以相关项不为零,得到
δF=L(b,y(b),y′(b))δb+∂y′∂L(b)δy(b)+∫ab[∂y∂L−dxd(∂y′∂L)]δydx 此时让 δF=0 不仅要满足欧拉-拉格朗日方程,还多出了一个额外的条件
L(b,y(b),y′(b))δb+∂y′∂L(b)δy(b)=0 该条件还可以进一步讨论,从而分为只允许纵坐标变化、只允许横坐标变化和可以任意变化三种情况。
经过扰动(包括端点的扰动和曲线的扰动)后,最终的右端点变为
Bε(bε,yε(bε)) 其纵坐标的变化量为
δyB=yε(bε)−y(b) 而
yε(bε)=y(b+εζ)+εη(b+εζ) 对 y(b+εζ) 和 η(b+εζ) 分别进行一阶展开
{y(b+εζ)=y(b)+εy′(b)ζ+o(ε)η(b+εζ)=η(b)+εη′(b)ζ+o(ε) 忽略二阶小量 ε2η′(b)ζ 和高阶小量 o(ε),代回原式
δyB=y(b)+εy′(b)ζ+εη(b)−y(b)=εy′(b)ζ+εη(b)=y′(b)δb+δy(b) 移项得到
δy(b)=δyB−y′(b)δb 再把上式代入原来的条件
L(b,y(b),y′(b))δb+∂y′∂L(b)[δyB−y′(b)δb][L(b,y(b),y′(b))−y′(b)∂y′∂L(b)]δb+∂y′∂L(b)δyB=0=0 因此
- 当端点横坐标可自由变化而纵坐标固定时,与 δb 相乘的部分必须为零,得到
L(b,y(b),y′(b))−y′(b)∂y′∂L(b)=0 - 当端点的纵坐标可自由变化而横坐标固定时,与 δyB 相乘的部分必须为零,得到
∂y′∂L(b)=0 - 当端点的横纵坐标均可自由变化时,上面两项都要为零,稍微化简后便得到
∂y′∂L(b)=0L(b,y(b),y′(b))=0
上述条件被称作自然边界条件。
另一种情况是,端点被限制在曲线 y=ψ(x) 上,此时有
δyB=ψ′(b)δb 代入得到
[L(b,y(b),y′(b))−y′(b)∂y′∂L(b)]δb+ψ′(b)∂y′∂L(b)δb[L(b,y(b),y′(b))−y′(b)∂y′∂L(b)+ψ′(b)∂y′∂L(b)]δb=0=0 从而有
L(b,y(b),y′(b))−y′(b)∂y′∂L(b)+ψ′(b)∂y′∂L(b)=0 这叫做横截条件。
变分法的应用:最速降线问题#
最速降线问题#
设一质点从原点 A=(0,0) 运动到 B=(w,h) 处(w,h>0 且 y 轴正方向向下),初速度为零,重力加速度为 g,忽略所有摩擦力。质点沿哪条曲线运动所需的时间最短?
这是固定边界变分问题。
将解表示为时间泛函的极值点#
设曲线为
由能量守恒得到 (x,y) 处的速度为
v=2gy 弧长微元为
ds=1+(y′)2dx 从而时间可表示为一个泛函
T[y]=∫ABvds=∫0w2gy1+(y′)2dx 因此最速降线就是使 T[y] 取极小值的函数。
求时间泛函的极值点#
由于常数 2g 不影响泛函的极值点,因此定义拉格朗日函数时忽略掉它
L(y,y′)=y1+(y′)2=y−21[1+(y′)2]21 显然 L 中不包含自变量 x。下面利用这一性质计算欧拉-拉格朗日方程的首次积分——这也叫贝尔特拉米恒等式。
首先得到
∂x∂L=0 然后计算全导数
dxdL=∂x∂L+∂y∂Ldxdy+∂y′∂Ldxdy′=y′∂y∂L+y′′∂y′∂L 接着把欧拉-拉格朗日方程 ∂y∂L=dxd(∂y′∂L) 代入其中
dxdL=y′dxd(∂y′∂L)+y′′∂y′∂L 反向使用导数的乘积法则,得到
dxdL=dxd(y′∂y′∂L) 再移项合并求导
dxd(L−y′∂y′∂L)=0 最后对两侧同时积分,得到贝尔特拉米恒等式
L−y′∂y′∂L=C 原先的欧拉-拉格朗日方程中还有二阶导数,现在只剩下一阶导数了。接下来的任务就是求解这个一阶微分方程。
首先计算偏导数
∂y′∂L=y−2121[1+(y′)2]−21(2y′)=y[1+(y′)2]y′ 然后把 L 和 ∂y′∂L 代入贝尔特拉米恒等式
y1+(y′)2−y′y[1+(y′)2]y′y[1+(y′)2]1y[1+(y′)2]1y[1+(y′)2]=C=C=C2=C21 这里更换一下常数符号 C21=2r ,得到
y[1+(y′)2]=2r 接下来是需要注意力的三角变换。令
y′=cot2θ 代入上式得到
y(1+cot22θ)ycsc22θyy=2r=2r=2rsin22θ=r(1−cosθ) 现在有了 y 关于 θ 的参数方程,再得到 x 关于 θ 的参数方程就可以确定曲线了。
先求 dy
dy=rsinθdθ 然后间接计算 dx
dx=y′dy=cot2θrsinθdθ=r(2sin2θcos2θcos2θsin2θ)dθ=r(2sin22θ)dθ=r(1−cosθ)dθ 最后两侧同时积分
x=r(θ−sinθ)+C 代入曲线必过的原点坐标 A=(0,0) 即可确定常数值
于是最速降线为
{x=r(θ−sinθ)y=r(1−cosθ) 这正是摆线的参数方程。
最速降线问题的解#
代入曲线经过的另一个点 B=(w,h) 得到方程
{w=r(θB−sinθB)h=r(1−cosθB) 消去 r 后得到
1−cosθBθB−sinθB=hw 可惜这是一个超越方程,无法得到 θB 的初等函数表示。
假设用数值方法求出了 0<θB<2π,代入便可得到
r=1−cosθBh=θB−sinθBw 代回参数方程便得到了最终的曲线
⎩⎨⎧x=θB−sinθBw(θ−sinθ)y=1−cosθBh(1−cosθ)θ∈[0,θB] 需要注意的是,这条曲线并不严格满足 C1[0,w],因为在 θ=0 处斜率无穷大,不可求导。但变分法的实际要求更为宽松,因此结论仍然有效。
最短的时间也可以计算出来。首先是速度
v=2gy=2gr(1−cosθ)=2grsin2θ 然后求弧长微元
ds=dx2+dy2=(dθdx)2+(dθdy)2dθ 分别得到
{dθdx=r(1−cosθ)dθdy=rsinθ 于是
ds=r2(1−cosθ)2+r2sin2θdθ=2rsin2θdθ 从而
Tmin=∫ABvds=∫0θBgrdθ=θBgr 代入 r=1−cosθBh 得到最短时间
Tmin=θBg(1−cosθB)h 可以对比一下直线下降所需的时间。此时质点做匀加速直线运动,初速度为 0,终速度为 2gh,然后由平均速度乘时间等于路程得到
22ghTline=w2+h2 即
Tline=gh2w2+2h2 另外,本例其实只证明了取极值的必要条件,并没有证明充分性。因此实际的结论是:如果存在最速降线,那么一定是前文求出的摆线,且时间为前文求出的时间。
const board = JXG.JSXGraph.initBoard(BOARDID, {
boundingbox: [-1, -1, 10, 10],
axis: true,
showCopyright: false,
showNavigation: false,
});
const g = 9.8
function theta(w, h) {
let lastW;
let lastH;
let lastTheta;
if (w === lastW && h === lastH) {
return lastTheta;
}
lastW = w;
lastH = h;
lastTheta = JXG.Math.Numerics.fzero(
(t) => (t - Math.sin(t)) - w / h * (1 - Math.cos(t)),
[1e-2, 2 * Math.PI - 1e-2]
);
return lastTheta;
}
function r(w, h) {
return h / (1 - Math.cos(theta(w, h)));
}
function timeCycloid(w, h) {
return theta(w, h) * Math.sqrt(r(w, h) / g);
}
function timeLine(w, h) {
return Math.sqrt(2 * (w * w + h * h) / (g * h))
}
const A = board.create("point", [0, 0], {
name: "A",
fixed: true
});
const B = board.create("point", [2, 1], { name: "B" });
board.create('line', [A, B], {
straightFirst: false,
straightLast: false,
strokeColor: 'green',
strokeWidth: 3
})
board.create('curve', [
(t) => r(B.X(), B.Y()) * (t - Math.sin(t)),
(t) => r(B.X(), B.Y()) * (1 - Math.cos(t)),
0, () => theta(B.X(), B.Y())
], {
strokeWidth: 3
});
board.create("text", [
() => B.X() + 0.25,
() => B.Y() + 0.25,
() => `(${B.X().toFixed(2)}, ${B.Y().toFixed(2)})`
])
board.create("text", [
0.5,
8.5,
() => `
摆线时间 ${timeCycloid(B.X(), B.Y())}<br>
直线时间 ${timeLine(B.X(), B.Y())}
`
]);
变分法的应用:狄多问题#
狄多问题#
设一曲线从原点 A=(0,0) 出发,经过上半平面回到 x 轴 B=(d,0) 处(d>0 且可任取),其总长度为 l。哪条曲线与 x 轴围成的面积最大?
这是右端点横坐标可变化的自由边界变分问题。
将解表示为面积泛函的极值点#
设曲线为
狄多问题有一个约束条件,即长度需满足
l=∫ABds=∫0d1+(y′)2dx 围成的面积可表示为
S[y,d]=∫0dydx 因此与 x 轴围成面积最大的曲线就是使 S[y,d] 取极大值,且满足约束条件 ∫0d1+(y′)2dx−l=0 的函数。
求面积泛函的极值点#
由于带有约束条件,因此需要用拉格朗日乘子构造一个辅助泛函
J[y,d]=S[y,d]+λ(∫0d1+(y′)2dx−l)=∫0dydx+∫0dλ1+(y′)2dx−λl=∫0d(y+λ1+(y′)2)dx−λl 再对 y,d 变分时 λ 视为常数,因此 λl 不改变泛函的极值条件,定义拉格朗日函数时忽略掉它
L(y,y′)=y+λ1+(y′)2=y+λ[1+(y′)2]21 由于问题是端点横坐标可自由变化的变分问题,因此极值点需要满足欧拉-拉格朗日方程和自然边界条件。
先考虑欧拉-拉格朗日方程。由于拉格朗日函数中不包含自变量 x,因此复用之前求出的贝尔特拉米恒等式,得到
L−y′∂y′∂L=C 计算偏导数
∂y′∂L=λ21[1+(y′)2]−21(2y′)=λ1+(y′)2y′ 代入 L 和 ∂y′∂L
y+λ1+(y′)2−y′λ1+(y′)2y′y+λ1+(y′)21=C=C 然后化简
1+(y′)2λ1+(y′)2λ21+(y′)2(y′)2y′=C−y=(C−y)2=(C−y)2λ2=(C−y)2λ2−(C−y)2=±C−yλ2−(C−y)2 接着分离变量
dxdyλ2−(C−y)2C−ydy=±C−yλ2−(C−y)2=±dx 再进行积分变换。令 u=C−y,于是
du=−dy 代入得到
λ2−u2−udu=±dx 两侧同时积分
λ2−u2λ2−u2=±(x−C′)=(x−C′)2 代回 u=C−y 得到
λ2−(C−y)2=(x−C′)2 令 C=y0,C′=x0,r=∣λ∣,便得到了标准的圆方程
(x−x0)2+(y−y0)2=r2 因此曲线是过上半平面的一段圆弧
y(x)=y0+r2−(x−x0)2 再来考虑自然边界条件。由于只允许右端点的横坐标变化,因此
(L−y′∂y′∂L)x=d=0 而贝尔特拉米恒等式要求 L−y′∂y′∂L=C,因此有
由于此前令 C=y0,于是可知圆心在 x 轴上
y(x)=r2−(x−x0)2 代入曲线必过的原点 A(0,0),并由 r,x0>0 得到
0r=r2−x02=x0 从而有
y(x)=r2−(x−r)2=2rx−x2 因此最终的圆弧一定是个以 AB 为直径的上半圆。
狄多问题的解#
已知半圆的弧长为
从而
r=πl 因此右端点的横坐标为
d=2r=π2l 得到最终的曲线表达式
y(x)=π2lx−x2x∈[0,π2l] 同样地,上述曲线并不满足 C1[0,d],因为在 x=0,x=d 处斜率都为无穷大。但变分法的适用条件更为宽松,因此结论仍然有效。
还可以顺便求出最大的面积
Smax=21πr2=2πl2 即
Smax=2πl2 同样地,本例只证明了极值曲线的必要条件。因此,实际的结论是:如果存在与 x 轴围成面积最大的曲线,那么这条曲线一定是前文求出的半圆,且面积为前文求出的面积。
const board = JXG.JSXGraph.initBoard(BOARDID, {
boundingbox: [-2, 10, 20, -1],
axis: true,
showCopyright: false,
showNavigation: false,
keepAspectRatio: true
});
function r(l) {
return l / Math.PI
}
function d(l) {
return 2 * l / Math.PI
}
function S(l) {
return l * l / (2 * Math.PI)
}
const l = board.create('slider', [
[6, 9],
[16, 9],
[0, 10, 20]
], {
name: 'l'
});
const A = board.create("point", [0, 0], {
name: "A",
fixed: true
});
const B = board.create("point", [
() => d(l.Value()),
0
], {
name: "B",
fixed: true
});
board.create('semicircle', [A, B])
board.create("text", [
10,
8,
() => `面积 ${S(l.Value())}`
]);