Skip to content

Commit fd72a56

Browse files
authored
Work on two-interval equilibrium measure (#42)
* Work on two-interval equilibrium measure * two-band equilibrium measure converges * update versions * fix tests * Increase coverage
1 parent 16f2191 commit fd72a56

File tree

7 files changed

+154
-18
lines changed

7 files changed

+154
-18
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
version:
13-
- '1.5'
14-
- '^1.6.0-0'
13+
- '1.6'
1514
os:
1615
- ubuntu-latest
1716
- macOS-latest

Project.toml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
name = "SemiclassicalOrthogonalPolynomials"
22
uuid = "291c01f3-23f6-4eb6-aeb0-063a639b53f2"
33
authors = ["Sheehan Olver <[email protected]>"]
4-
version = "0.1.2"
4+
version = "0.2.0"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
88
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
99
ClassicalOrthogonalPolynomials = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd"
1010
ContinuumArrays = "7ae1f121-cc2c-504b-ac30-9b923412ae5c"
1111
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
12+
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
1213
HypergeometricFunctions = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
1314
InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c"
1415
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
@@ -17,17 +18,17 @@ QuasiArrays = "c4ea9172-b204-11e9-377d-29865faadc5c"
1718
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
1819

1920
[compat]
20-
ArrayLayouts = "0.6, 0.7"
21+
ArrayLayouts = "0.7"
2122
BandedMatrices = "0.16"
22-
ClassicalOrthogonalPolynomials = "0.3.5, 0.4"
23-
ContinuumArrays = "0.7, 0.8"
23+
ClassicalOrthogonalPolynomials = "0.4.2"
24+
ContinuumArrays = "0.8"
2425
FillArrays = "0.11.5"
2526
HypergeometricFunctions = "0.3.4"
26-
InfiniteArrays = "0.10.2, 0.11"
27+
InfiniteArrays = "0.11"
2728
LazyArrays = "0.21.3"
28-
QuasiArrays = "0.5, 0.6"
29-
SpecialFunctions = "0.10, 1.0"
30-
julia = "1.5"
29+
QuasiArrays = "0.6"
30+
SpecialFunctions = "1.0"
31+
julia = "1.6"
3132

3233
[extras]
3334
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

examples/equilibriummeasure.jl

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using SemiclassicalOrthogonalPolynomials, ClassicalOrthogonalPolynomials, ForwardDiff, Plots, StaticArrays
2+
import ForwardDiff: derivative, jacobian, Dual
3+
import SemiclassicalOrthogonalPolynomials: Weighted
4+
import ClassicalOrthogonalPolynomials: associated, affine
5+
6+
Base.floatmin(::Type{Dual{T,V,N}}) where {T,V,N} = Dual{T,V,N}(floatmin(V))
7+
8+
9+
####
10+
#
11+
# We first do a single interval.
12+
# Equilibrium measures for a symmetric potential
13+
# with one interval of support
14+
# a measure w(x) supported on
15+
# [-b,b]
16+
# such that
17+
# 1. H*w == V'
18+
# 2. sum(w) == 1
19+
# 3. w is bounded
20+
#
21+
# rescaling x == b*t these becomes find
22+
# a measure w̃(t) supported on
23+
# [-1,1]
24+
# such that
25+
# 1. H*w̃ == V'(b*t)
26+
# 2. sum(w̃) == 1/b
27+
# 3. w is bounded
28+
#
29+
# Note (1) and (2) can always be satisfied
30+
# thus the constraint comes from (3).
31+
# The following gives the evaluation of the
32+
# unweighted-component of the measure evaluated
33+
# at (a,b)
34+
#####
35+
36+
37+
V = x -> x^2
38+
function equilibriumcoefficients(T, b)
39+
U = associated(T)
40+
W = Weighted(T)
41+
t = axes(W,1)
42+
H = @. inv(t - t')
43+
= U \ (H*W)
44+
[1/(b*sum(W[:,1])); 2H̃[:,2:end] \ ( U \ derivative.(V, b*t))]
45+
end
46+
function equilibriumendpointvalue(b::Number)
47+
T = ChebyshevT{typeof(b)}()
48+
dot(T[end,:], equilibriumcoefficients(T,b))
49+
end
50+
51+
function equilibrium(b::Number)
52+
T = ChebyshevT{typeof(b)}()
53+
U = ChebyshevU{typeof(b)}()
54+
# convert to Weighted(U) to make value at ±b accurate
55+
Weighted(U)[affine(-b..b,axes(T,1)),:] * ((Weighted(T) \ Weighted(U))[3:end,:] \ equilibriumcoefficients(T,b)[3:end])
56+
end
57+
58+
b = 1.0 # initial guess
59+
for _ = 1:10
60+
b -= derivative(equilibriumendpointvalue,b) \ equilibriumendpointvalue(b)
61+
end
62+
63+
plot(equilibrium(b))
64+
ClassicalOrthogonalPolynomials.plotgrid(equilibrium(b))
65+
66+
67+
#####
68+
# Equilibrium measures for a symmetric potential
69+
# with two intervals of support consists of finding
70+
# a measure w(x) supported on
71+
# [-b,-a] ∪ [a,b]
72+
# such that
73+
# 1. H*w == V'
74+
# 2. sum(w) == 1
75+
# 3. w is bounded
76+
#
77+
# rescaling x == b*t these becomes find
78+
# a measure w̃(t) supported on
79+
# [-1,-a/b] ∪ [a/b,1]
80+
# such that
81+
# 1. H*w̃ == V'(b*t)
82+
# 2. sum(w̃) == 1/b
83+
# 3. w is bounded
84+
#
85+
# Note (1) and (2) can always be satisfied
86+
# thus the two constraints come from (3).
87+
# The following gives the evaluation of the
88+
# unweighted-component of the measure evaluated
89+
# at (a,b)
90+
#####
91+
V = x -> x^4 - 10x^2
92+
function equilibriumcoefficients(P,a,b)
93+
W = Weighted(P)
94+
Q = associated(P)
95+
t = axes(W,1)
96+
H = @. inv(t - t')
97+
= Q \ (H*W)
98+
[1/(b*sum(W[:,1])); 2H̃[:,2:end] \( Q \ derivative.(V, b*t))]
99+
end
100+
function equilibriumendpointvalues(ab::SVector{2})
101+
a,b = ab
102+
P = TwoBandJacobi(a/b, -1/2, -1/2, 1/2)
103+
P[[a/b,1],:] * equilibriumcoefficients(P,a,b)
104+
end
105+
106+
function equilibrium(ab)
107+
a,b = ab
108+
P = TwoBandJacobi(a/b, -1/2, -1/2, 1/2)
109+
Weighted(P) * equilibriumcoefficients(P,a,b)
110+
end
111+
112+
(a,b) = ab = SVector(2.,3.)
113+
ab -= jacobian(equilibriumendpointvalues,ab) \ equilibriumendpointvalues(ab)
114+
115+
116+
plot(equilibrium(ab))
117+

src/SemiclassicalOrthogonalPolynomials.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module SemiclassicalOrthogonalPolynomials
2+
using ClassicalOrthogonalPolynomials: WeightedOPLayout
23
using ClassicalOrthogonalPolynomials, FillArrays, LazyArrays, ArrayLayouts, QuasiArrays, InfiniteArrays, ContinuumArrays, LinearAlgebra, BandedMatrices,
34
SpecialFunctions, HypergeometricFunctions
45

@@ -12,7 +13,7 @@ import ClassicalOrthogonalPolynomials: OrthogonalPolynomial, recurrencecoefficie
1213
OrthogonalPolynomialRatio, Weighted, Expansion, UnionDomain, oneto, Hilbert, WeightedOrthogonalPolynomial, HalfWeighted,
1314
Associated
1415
import InfiniteArrays: OneToInf, InfUnitRange
15-
import ContinuumArrays: basis, Weight, @simplify, AbstractBasisLayout, BasisLayout, MappedBasisLayout, grid
16+
import ContinuumArrays: basis, Weight, @simplify, AbstractBasisLayout, BasisLayout, MappedBasisLayout, grid, plotgrid
1617
import FillArrays: SquareEye
1718
import HypergeometricFunctions: _₂F₁general2
1819

@@ -297,13 +298,16 @@ copy(L::Ldiv{SemiclassicalJacobiLayout,<:NormalizedBasisLayout}) = copy(Ldiv{Sem
297298
copy(L::Ldiv{ApplyLayout{typeof(*)},SemiclassicalJacobiLayout}) = copy(Ldiv{ApplyLayout{typeof(*)},BasisLayout}(L.A, L.B))
298299
copy(L::Ldiv{SemiclassicalJacobiLayout,ApplyLayout{typeof(*)}}) = copy(Ldiv{BasisLayout,ApplyLayout{typeof(*)}}(L.A, L.B))
299300

300-
301301
copy(L::Ldiv{MappedBasisLayout,SemiclassicalJacobiLayout}) = semijacobi_ldiv(L.A, L.B)
302302
copy(L::Ldiv{SemiclassicalJacobiLayout,MappedBasisLayout}) = semijacobi_ldiv(L.A, L.B)
303303

304+
copy(L::Ldiv{WeightedOPLayout,SemiclassicalJacobiLayout}) = copy(Ldiv{WeightedOPLayout,BasisLayout}(L.A, L.B))
305+
copy(L::Ldiv{SemiclassicalJacobiLayout,WeightedOPLayout}) = copy(Ldiv{BasisLayout,WeightedOPLayout}(L.A, L.B))
306+
304307

305308
copy(L::Ldiv{SemiclassicalJacobiLayout}) = semijacobi_ldiv(L.A, L.B)
306309
copy(L::Ldiv{<:Any,SemiclassicalJacobiLayout}) = semijacobi_ldiv(L.A, L.B)
310+
copy(L::Ldiv{<:AbstractBasisLayout,SemiclassicalJacobiLayout}) = semijacobi_ldiv(L.A, L.B)
307311
function copy(L::Ldiv{SemiclassicalJacobiLayout,SemiclassicalJacobiLayout})
308312
Q,P = L.A,L.B
309313
@assert Q.t == P.t

src/twoband.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ twoband(ρ) = UnionDomain(-1..(-ρ), ρ..1)
44
"""
55
TwoBandWeight(ρ, a, b, c)
66
7-
is a quasi-vector representing `|x|^(2c) * (x^2-ρ)^b * (1-x^2)^a` for `ρ ≤ |x| ≤ 1`
7+
is a quasi-vector representing `|x|^(2c) * (x^2-ρ^2)^b * (1-x^2)^a` for `ρ ≤ |x| ≤ 1`
88
"""
99
struct TwoBandWeight{T} <: Weight{T}
1010
ρ::T
@@ -28,7 +28,7 @@ end
2828

2929
function sum(w::TwoBandWeight{T}) where T
3030
if 2w.a == 2w.b == -1 && 2w.c == 1
31-
convert(T,π)/2
31+
convert(T,π)
3232
else
3333
error("not implemented")
3434
# 1/2 \[Pi] (-((\[Rho]^(1 + 2 b + 2 c)
@@ -112,7 +112,10 @@ function grid(L::SubQuasiArray{T,2,<:Associated{<:Any,<:TwoBandJacobi},<:Tuple{I
112112
[-g; g]
113113
end
114114

115-
115+
function plotgrid(L::SubQuasiArray{T,2,<:TwoBandJacobi,<:Tuple{Inclusion,AbstractUnitRange}}) where T
116+
g = plotgrid(legendre(parent(L).ρ .. 1)[:,parentindices(L)[2]])
117+
[-g; g]
118+
end
116119

117120
LinearAlgebra.factorize(L::SubQuasiArray{<:Any,2,<:Associated{<:Any,<:TwoBandJacobi},<:Tuple{Inclusion,OneTo}}) =
118121
ContinuumArrays._factorize(BasisLayout(), L)

test/runtests.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using SemiclassicalOrthogonalPolynomials
2-
using ClassicalOrthogonalPolynomials, ContinuumArrays, BandedMatrices, QuasiArrays, Test, LazyArrays, LinearAlgebra
2+
using ClassicalOrthogonalPolynomials, ContinuumArrays, BandedMatrices, QuasiArrays, Test, LazyArrays, FillArrays, LinearAlgebra
33
import BandedMatrices: _BandedMatrix
44
import SemiclassicalOrthogonalPolynomials: op_lowering, RaisedOP
55
import ClassicalOrthogonalPolynomials: recurrencecoefficients, orthogonalityweight, symtridiagonalize, Expansion
@@ -310,6 +310,12 @@ end
310310
@test (Q * (Q \ exp.(x)))[0.1] exp(0.1)
311311
@test (R * (R \ exp.(x)))[0.1] exp(0.1)
312312
end
313+
314+
@testset "conversion" begin
315+
D = legendre(0..1) \ P
316+
@test (P \ legendre(0..1))[1:10,1:10] == inv(Matrix(D[1:10,1:10]))
317+
@test_broken (P \ Weighted(P)) == (Weighted(P) \ P) == Eye(∞)
318+
end
313319
end
314320

315321
@testset "Hierarchy" begin

test/test_twoband.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using SemiclassicalOrthogonalPolynomials, ClassicalOrthogonalPolynomials, Test
2-
import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated
2+
import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated, plotgrid
33

44
@testset "Two Band" begin
55
@testset "TwoBandWeight" begin
@@ -33,7 +33,7 @@ import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated
3333
x = axes(w,1)
3434
H = inv.(x .- x')
3535
@test iszero(H*w)
36-
@test sum(w) == π/2
36+
@test sum(w) π
3737

3838
T = TwoBandJacobi(ρ, -1/2, -1/2, 1/2)
3939
Q = associated(T)
@@ -45,4 +45,10 @@ import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated
4545

4646
@test_broken H*TwoBandWeight(ρ, 1/2, 1/2, -1/2)
4747
end
48+
49+
@testset "plotgrid" begin
50+
ρ = 0.5
51+
P = TwoBandJacobi(ρ, -1/2, -1/2, 1/2)
52+
@test all(x -> ρ abs(x)  1, plotgrid(P[:,1:5]))
53+
end
4854
end

0 commit comments

Comments
 (0)