Loss Landscape

NonArchimedeanMachineLearning.ConvexHullTreeType
ConvexHullTree{S,T,N}

A tree structure representing the convex hull of a set of polydiscs.

The convex hull consists of the input polydiscs and all their joins, with edges determined by the containment relation.

Fields

  • nodes::Vector{ValuationPolydisc{S,T,N}}: All nodes in the tree (input discs + joins)
  • children::Dict{Int,Vector{Int}}: Maps node index to indices of immediate children
  • parents::Dict{Int,Vector{Int}}: Maps node index to indices of immediate parents
  • leaf_indices::Vector{Int}: Indices of the original input discs
source
NonArchimedeanMachineLearning.build_tree_structureMethod
build_tree_structure(nodes::Vector{ValuationPolydisc{S,T,N}}, num_initial::Int) where {S,T,N}

Build parent-child relationships for the convex hull tree.

Arguments

  • nodes::Vector{ValuationPolydisc{S,T,N}}: All nodes (initial discs first, then joins)
  • num_initial::Int: Number of initial discs (these are the leaves)

Returns

Tuple{Dict{Int,Vector{Int}}, Dict{Int,Vector{Int}}}: (children dict, parents dict)

source
NonArchimedeanMachineLearning.compute_all_joinsMethod
compute_all_joins(initial_discs::Vector{ValuationPolydisc{S,T,N}}) where {S,T,N}

Compute all polydiscs in the convex hull by iteratively computing joins.

Starting from the initial list of polydiscs, repeatedly computes pairwise joins until no new polydiscs are generated.

Arguments

  • initial_discs::Vector{ValuationPolydisc{S,T,N}}: Initial list of polydiscs

Returns

Vector{ValuationPolydisc{S,T,N}}: All polydiscs in the convex hull

source
NonArchimedeanMachineLearning.compute_subtree_widthFunction
compute_subtree_width(tree::ConvexHullTree, node_idx::Int, leaf_width::Float64=1.0)

Recursively compute the width needed for a subtree rooted at the given node.

Arguments

  • tree::ConvexHullTree: The tree structure
  • node_idx::Int: Index of the root of the subtree
  • leaf_width::Float64: Width allocated to each leaf node (default: 1.0)

Returns

Float64: Total width needed for the subtree

source
NonArchimedeanMachineLearning.compute_tree_layoutMethod
compute_tree_layout(tree::ConvexHullTree{S,T,N}) where {S,T,N}

Compute (x, y) positions for all nodes in the tree for visualization.

Uses a radius-based layout where:

  • Y-coordinate is determined by radius (smaller radius = higher position)
  • Nodes with the same radius are at the same vertical level
  • X-coordinates spread nodes to avoid overlap while respecting tree structure

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree

Returns

Tuple{Dict{Int, Tuple{Float64, Float64}}, Dict{Int,Vector{Int}}, Dict{Int,Int}, Int}:

  • positions: Maps node index to (x, y) position
  • spanning_children: Children in the spanning tree
  • spanning_parent: Parent in the spanning tree
  • root_idx: Index of the root
source
NonArchimedeanMachineLearning.convex_hullMethod
convex_hull(discs::Vector{ValuationPolydisc{S,T,N}}) where {S,T,N}

Compute the convex hull tree of a list of polydiscs.

The convex hull is a tree whose nodes are the input polydiscs and all their joins, with edges determined by the containment relation.

Arguments

  • discs::Vector{ValuationPolydisc{S,T,N}}: List of polydiscs

Returns

ConvexHullTree{S,T,N}: The convex hull tree structure

Example

K = PadicField(2, 20)
d1 = ValuationPolydisc([K(0)], [3])
d2 = ValuationPolydisc([K(4)], [3])
d3 = ValuationPolydisc([K(8)], [3])
tree = convex_hull([d1, d2, d3])
source
NonArchimedeanMachineLearning.export_landscape_csvMethod
export_landscape_csv(tree::ConvexHullTree{S,T,N}, landscape::Dict, filename::String) where {S,T,N}

Export loss landscape data to CSV format for external plotting.

The CSV format is:

parent_idx,child_idx,geodesic_param,loss_value

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree structure
  • landscape::Dict: Loss landscape data from samplelosslandscape
  • filename::String: Output CSV file path

Example

tree = convex_hull([d1, d2, d3])
landscape = sample_loss_landscape(tree, loss_func, 10)
export_landscape_csv(tree, landscape, "landscape_data.csv")
source
NonArchimedeanMachineLearning.extract_spanning_treeMethod
extract_spanning_tree(tree::ConvexHullTree{S,T,N}) where {S,T,N}

Extract a spanning tree from the convex hull DAG.

The convex hull can form a DAG (directed acyclic graph) where nodes have multiple parents. This function extracts a proper tree by:

  1. Creating a virtual root if there are multiple roots
  2. Keeping only one parent per node (the one with smallest radius sum, breaking ties by index)

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree (potentially a DAG)

Returns

Tuple{Dict{Int,Vector{Int}}, Dict{Int,Int}, Int}: (children, parent, root_idx)

  • children: Maps node index to list of children in the spanning tree
  • parent: Maps node index to its single parent (-1 for root)
  • root_idx: Index of the root node (or -1 for virtual root)
source
NonArchimedeanMachineLearning.find_polydisc_indexMethod
find_polydisc_index(discs::Vector{ValuationPolydisc{S,T,N}}, p::ValuationPolydisc{S,T,N}) where {S,T,N}

Find the index of a polydisc in a vector using Berkovich equality, or return 0 if not found.

Uses the == operator which checks Berkovich equality: two polydiscs are equal if they have the same radius and their centers differ by elements with valuation >= radius.

Arguments

  • discs::Vector{ValuationPolydisc{S,T,N}}: Vector of polydiscs to search
  • p::ValuationPolydisc{S,T,N}: Polydisc to find

Returns

Int: Index of the first equal polydisc in the vector, or 0 if not found

source
NonArchimedeanMachineLearning.geodesic_interpolationMethod
geodesic_interpolation(d1::ValuationPolydisc{S,T,N}, d2::ValuationPolydisc{S,T,N}, x::Real) where {S,T,N}

Compute the polydisc at parameter x along the geodesic from d1 to d2.

For two discs with the same center, the geodesic is linear interpolation of radii. If d1 = D(a, r) and d2 = D(a, s) with r ≤ s, then at parameter x ∈ [0,1], the interpolated disc is D(a, (1-x)r + xs).

Note: This function works with actual radii (not valuations) for interpolation. The input discs may have integer valuation radii, but the output will have Float64 radii representing the interpolated actual radius.

Arguments

  • d1::ValuationPolydisc{S,T,N}: First polydisc (must be contained in d2)
  • d2::ValuationPolydisc{S,T,N}: Second polydisc (must contain d1)
  • x::Real: Interpolation parameter in [0, 1]

Returns

ValuationPolydisc{S,Float64,N}: Interpolated polydisc with Float64 radii

Example

K = PadicField(2, 20)
d1 = ValuationPolydisc([K(0)], [5])  # Small disc, valuation 5
d2 = ValuationPolydisc([K(0)], [2])  # Large disc, valuation 2
d_half = geodesic_interpolation(d1, d2, 0.5)  # Midpoint
source
NonArchimedeanMachineLearning.is_immediate_parentMethod
is_immediate_parent(parent_idx::Int, child_idx::Int, nodes::Vector{ValuationPolydisc{S,T,N}}) where {S,T,N}

Check if parent is an immediate parent of child (no intermediate node).

Returns true if:

  1. nodes[childidx] ⊆ nodes[parentidx] (containment)
  2. child has strictly smaller radius than parent (higher valuation = smaller disc)
  3. There is no intermediate node k with child ⊆ k ⊆ parent

Arguments

  • parent_idx::Int: Index of potential parent
  • child_idx::Int: Index of potential child
  • nodes::Vector{ValuationPolydisc{S,T,N}}: All nodes in the tree

Returns

Bool: true if parent is an immediate parent of child

source
NonArchimedeanMachineLearning.loss_to_colorFunction
loss_to_color(loss::Float64, min_loss::Float64, max_loss::Float64, colormap::Symbol=:viridis)

Convert a loss value to an RGB color using a colormap.

Arguments

  • loss::Float64: The loss value
  • min_loss::Float64: Minimum loss for normalization
  • max_loss::Float64: Maximum loss for normalization
  • colormap::Symbol: Color scheme (default: :viridis)

Returns

RGB color from the colormap

source
NonArchimedeanMachineLearning.plot_loss_landscapeMethod
plot_loss_landscape(tree::ConvexHullTree{S,T,N}, landscape::Dict; kwargs...) where {S,T,N}

Plot the loss landscape using Plots.jl (if available).

Creates a visualization showing:

  • Nodes as points
  • Edges colored by loss value
  • Loss values along geodesics

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree structure
  • landscape::Dict: Loss landscape data from samplelosslandscape

Keyword Arguments

  • title::String: Plot title (default: "Loss Landscape")
  • colormap::Symbol: Color scheme (default: :viridis)
  • show_node_labels::Bool: Whether to show node indices (default: true)
  • line_width::Real: Width of edge lines (default: 2)

Returns

Plot object from Plots.jl

Example

using Plots
tree = convex_hull([d1, d2, d3])
landscape = sample_loss_landscape(tree, loss_func, 10)
plt = plot_loss_landscape(tree, landscape, title="My Loss Landscape")
savefig(plt, "landscape.png")

Note

Requires Plots.jl to be installed and loaded:

using Plots
source
NonArchimedeanMachineLearning.plot_tree_simpleMethod
plot_tree_simple(tree::ConvexHullTree{S,T,N};
                 title::String="Convex Hull Tree",
                 show_node_labels::Bool=true,
                 line_width::Real=2,
                 node_size::Real=10,
                 figsize::Tuple{Int,Int}=(800, 600)) where {S,T,N}

Plot the convex hull tree structure without loss coloring.

Useful for visualizing just the tree structure before sampling loss.

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree structure

Keyword Arguments

  • title::String: Plot title (default: "Convex Hull Tree")
  • show_node_labels::Bool: Whether to show node indices (default: true)
  • line_width::Real: Width of edge lines (default: 2)
  • node_size::Real: Size of node markers (default: 10)
  • figsize::Tuple{Int,Int}: Figure size in pixels (default: (800, 600))

Returns

Plot object from Plots.jl

source
NonArchimedeanMachineLearning.plot_tree_with_lossMethod
plot_tree_with_loss(tree::ConvexHullTree{S,T,N}, landscape::Dict;
                    title::String="Loss Landscape on Tree",
                    colormap::Symbol=:viridis,
                    show_node_labels::Bool=true,
                    line_width::Real=4,
                    node_size::Real=8,
                    figsize::Tuple{Int,Int}=(800, 600)) where {S,T,N}

Plot the convex hull tree with edges colored by loss values.

Creates a proper tree visualization where:

  • Nodes are positioned in a hierarchical tree layout (root at top)
  • Each edge segment is colored according to the loss value at that point
  • A colorbar shows the loss scale

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree structure
  • landscape::Dict: Loss landscape data from sample_loss_landscape

Keyword Arguments

  • title::String: Plot title (default: "Loss Landscape on Tree")
  • colormap::Symbol: Color scheme (default: :viridis)
  • show_node_labels::Bool: Whether to show node indices (default: true)
  • line_width::Real: Width of edge lines (default: 4)
  • node_size::Real: Size of node markers (default: 8)
  • figsize::Tuple{Int,Int}: Figure size in pixels (default: (800, 600))

Returns

Plot object from Plots.jl

Example

using Plots
tree = NonArchimedeanMachineLearning.convex_hull([d1, d2, d3])
landscape = sample_loss_landscape(tree, loss_func, 20)
plt = plot_tree_with_loss(tree, landscape)
savefig(plt, "tree_landscape.png")
source
NonArchimedeanMachineLearning.print_landscape_summaryMethod
print_landscape_summary(tree::ConvexHullTree{S,T,N}, landscape::Dict) where {S,T,N}

Print a text-based summary of the loss landscape.

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree structure
  • landscape::Dict: Loss landscape data from samplelosslandscape

Example

tree = convex_hull([d1, d2, d3])
landscape = sample_loss_landscape(tree, loss_func, 10)
print_landscape_summary(tree, landscape)
source
NonArchimedeanMachineLearning.radius_strictly_smallerMethod
radius_strictly_smaller(r1::NTuple{N,T}, r2::NTuple{N,T}) where {N,T}

Check if r1 is strictly smaller than r2 in the valuation sense.

A radius is "smaller" if it has higher valuation values (representing a smaller disc). Returns true if all components of r1 >= r2 and at least one is strictly greater.

Arguments

  • r1::NTuple{N,T}: First radius tuple (valuation)
  • r2::NTuple{N,T}: Second radius tuple (valuation)

Returns

Bool: true if r1 represents a strictly smaller disc than r2

source
NonArchimedeanMachineLearning.radius_to_valuationMethod
radius_to_valuation(r::Real, p::Integer)

Convert an actual radius to a valuation.

For a p-adic disc with actual radius r, the valuation is -log_p(r).

Arguments

  • r::Real: The actual radius
  • p::Integer: The prime

Returns

Float64: The valuation (possibly non-integer)

source
NonArchimedeanMachineLearning.sample_loss_landscapeMethod
sample_loss_landscape(tree::ConvexHullTree{S,T,N}, f::Function, num_samples::Int=10) where {S,T,N}

Sample function values along geodesics in the convex hull tree.

For each parent-child edge in the tree, this function samples the function f at num_samples points along the geodesic connecting them. The geodesic parameter ranges from 0 (at the child) to 1 (at the parent).

Arguments

  • tree::ConvexHullTree{S,T,N}: The convex hull tree structure
  • f::Function: Function to evaluate, takes a ValuationPolydisc and returns a scalar
  • num_samples::Int: Number of sample points along each geodesic (default: 10)

Returns

Dict{Tuple{Int,Int}, Vector{Tuple{Float64,Float64}}}: Dictionary mapping (parent_idx, child_idx) pairs to vectors of (x, y) pairs, where:

  • x ∈ [0,1] is the geodesic parameter (0 = child, 1 = parent)
  • y is the function value at that point

Example

K = PadicField(2, 20)
d1 = ValuationPolydisc([K(0)], [3])
d2 = ValuationPolydisc([K(4)], [3])
tree = convex_hull([d1, d2])

# Define a simple function
f(disc) = sum(disc.radius)

# Sample the landscape
landscape = sample_loss_landscape(tree, f, 5)
source
NonArchimedeanMachineLearning.valuation_to_radiusMethod
valuation_to_radius(val::Real, p::Integer)

Convert a valuation to an actual radius.

For a p-adic disc with valuation radius val, the actual radius is p^(-val).

Arguments

  • val::Real: The valuation (can be integer or float)
  • p::Integer: The prime

Returns

Float64: The actual radius as a real number

source