在Julia中创建1/2/3维流形并投影至10维空间的实现方法
问题解答:将低维流形嵌入/投影到10维空间
核心逻辑
你说的“投影”更准确的说法是嵌入——把低维流形的点映射到高维空间中,同时保留流形的拓扑和几何特性。对于球面这类常见流形,最简单的实现方式是把低维球面的点扩展到高维欧氏空间的子空间里。
第一步:完善你的ScaledSphere流形定义
你现有的代码只搭了流形的结构框架,还需要实现几个关键接口方法,尤其是和嵌入空间相关的部分,这样才能和高维空间交互:
using ManifoldsBase, LinearAlgebra, Test import ManifoldsBase: check_point, check_vector, manifold_dimension, exp!, inner, representation_size, get_embedding import Base: show """ ScaledSphere{N} <: AbstractDecoratorManifold{ℝ} Define an `N`-sphere of radius `r`. Construct by `ScaledSphere(radius,n)`. """ struct ScaledSphere{N} <: AbstractDecoratorManifold{ManifoldsBase.ℝ} where {N} radius::Float64 end ScaledSphere(radius, n) = ScaledSphere{n}(radius) Base.show(io::IO, M::ScaledSphere{n}) where {n} = print(io, "ScaledSphere($(M.radius),$n)") # --- 新增关键接口实现 --- # 流形维度:N维球面是N维流形(比如2维球面是嵌入在3维空间的2维流形) manifold_dimension(::ScaledSphere{N}) where {N} = N # 流形中点的表示维度:嵌入到N+1维欧氏空间,所以点是N+1维向量 representation_size(::ScaledSphere{N}) where {N} = (N+1,) # 指定嵌入空间:N+1维欧氏空间 get_embedding(::ScaledSphere{N}) where {N} = Euclidean(N+1) # 验证点是否在缩放球面上:向量模长等于半径 function check_point(M::ScaledSphere{N}, p; kwargs...) where {N} if !isapprox(norm(p), M.radius; kwargs...) return DomainError(p, "Point not on ScaledSphere with radius $(M.radius)") end return nothing end # 验证切向量:与点p正交(球面的切空间是点处的正交补) function check_vector(M::ScaledSphere{N}, p, X; kwargs...) where {N} cp = check_point(M, p; kwargs...) cp !== nothing && return cp if !isapprox(dot(p, X), 0.0; kwargs...) return DomainError(X, "Vector not tangent to ScaledSphere at point $p") end return nothing end # 内积:继承嵌入空间的欧氏内积 inner(M::ScaledSphere, p, X, Y) = dot(X, Y) # 指数映射(用于生成流形上的点) function exp!(M::ScaledSphere{N}, q, p, X) where {N} r = M.radius norm_X = norm(X) if iszero(norm_X) q .= p return q end q .= cos(norm_X / r) .* p .+ r .* sin(norm_X / r) .* (X ./ norm_X) return q end
第二步:将低维流形嵌入到10维空间
把N维球面(原本嵌入在N+1维空间)映射到10维空间,最直接的方式是补零扩展——给低维向量补足够多的零,凑到10维,这种方式是等距嵌入,能完全保留流形的几何结构:
示例:2维球面(3维嵌入)→ 10维空间
# 创建半径1.5的2维球面(嵌入在3维空间) S = ScaledSphere(1.5, 2) # 取球面上的一个点(比如北极点) p = [0.0, 0.0, 1.5] @assert check_point(S, p) === nothing # 验证点在球面上 # 嵌入到10维空间:补7个零 p_10d = vcat(p, zeros(7)) # 此时p_10d是10维向量,模长还是1.5,对应10维空间里3维子空间中的球面点
批量生成10维空间中的流形点
如果要批量生成,先在低维流形上生成点,再扩展到10维即可:
function embed_to_10d(p_low::Vector{Float64}) # 给低维向量补零到10维 return vcat(p_low, zeros(10 - length(p_low))) end # 用指数映射生成2维球面上的随机点 X = randn(3) # 随机切向量 q = similar(p) exp!(S, q, p, X) @assert check_point(S, q) === nothing # 嵌入到10维 q_10d = embed_to_10d(q)
第三步:通用化到1/2/3维流形
- 1维流形(圆):用
ScaledSphere(1.5, 1),原本嵌入在2维空间,补8个零到10维 - 2维流形(球面):如上示例,补7个零
- 3维流形(3-球面):
ScaledSphere(1.5, 3),原本嵌入在4维空间,补6个零到10维
拓展:非平凡投影(从10维映射到低维流形)
如果你说的“投影”是指把10维空间的点映射到低维球面上,可以用径向投影:
function project_to_scaled_sphere(M::ScaledSphere{N}, p_10d::Vector{Float64}) where {N} r = M.radius # 取前N+1维,再归一化到半径r p_low = p_10d[1:N+1] norm_p = norm(p_low) iszero(norm_p) && error("Cannot project zero vector to sphere") return r .* (p_low ./ norm_p) end # 示例:把10维随机点投影到2维球面上 p_10d_rand = randn(10) p_projected = project_to_scaled_sphere(S, p_10d_rand) @assert check_point(S, p_projected) === nothing
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

