Block Term Decomposition

A block term decomposition (BTD) with r blocks writes

\[\hat A = \sum_{i=1}^r A_i,\]

where each block $A_i$ is represented as a Tucker decomposition. At present, only homogeneous BTDs are supported, that is, all blocks must have the same multilinear rank.

To compute a block term decomposition of A with 10 blocks, each of multilinear rank (5, 4, 3), use

julia> r = 10
julia> mlrank = (5, 4, 3)
julia> btd_res = btd(A, r, mlrank)
BTDResult{Float64}
  Blocks:       10
  Rel. error:   0.2551559591470521

The blocks of btd_res can be obtained as follows:

blocks = blocks(btd_res)

Each block is represented as a Tucker decomposition, so we can access its core and factor matrices via:

blk = blocks[1]
core(blk)
factors(blk)

BTD Docs

TensorKitchen.btdFunction
btd(A, blocks, ranks; kwargs...) returns a BTDResult

Computes a block-term decomposition of A with blocks Tucker blocks, each with multilinear rank ranks. The solver first finds an initial point, then refines it. Returns a BTDResult.

Main Options

  • init = :auto: Sets the algorithm to find the initial point. Possible options are:

    • :auto: Uses a default BTD initializer. For solver = :als, this uses BTDHOSVDMultistartInit; otherwise, it uses an ALS warm start.
    • :alswarm: Runs ALS first and uses the result as the initial point for manifold solver refinement.
    • custom initializer objects, e.g. BTDHOSVDMultistartInit(...).
  • solver = :rgd: Sets the algorithm for refinement. Possible options are:

    • :rgd (default): Riemannian gradient descent.
    • :als: Alternating least squares.
    • :rcg: Riemannian conjugate gradient.
    • :lbfgs: Limited-memory quasi-Newton refinement.

Extended Options

  • init_point = nothing: Explicit initial point. If provided, it overrides the default initial point.

  • warm_init = BTDHOSVDMultistartInit(...): Searches for initial points using HOSVD for :alswarm, optionally screens them with short ALS runs, and returns the lowest-cost candidate.

  • warm_steps = 200: Once finding the best initial point, it runs this many ALS iterations to refine the initial point.

  • warm_block_method = :hooi or :sthosvd: Block update method used during warm start.

  • warm_block_maxiter = 20: Maximum number of inner iterations for each block update during warm start.

  • warm_rel_error_gate = 5e-2: Skips manifold refinement if the warm-start error is above this threshold.

  • maxiter = 500: Maximum number of Riemannian gradient descent iterations.

  • stepsize = 0.01: Initial step size for line search in Riemannian gradient descent.

  • tol = 1e-6: Convergence tolerance.

  • gradient_mode = :riemannian: rgrad can be directly applied for manifold solvers.

    • If the model has a direct rgrad, it uses that.
    • Otherwise it computes egrad and projects it to the tangent space.
    • This behavior is in src/solvers/abstract.jl (line 289).
  • verbose = true: Enables progress output.

  • block_method = :hooi or :sthosvd: Block update method used for manifold solvers.

  • block_maxiter = 30: Maximum number of inner block-update iterations for manifold solvers.

  • btd_als_polish_maxiter = nothing: Number of final ALS polishing iterations. If nothing, an automatic budget is selected.

  • These settings are a robustness/quality feature for BTD-ALS. They are not used for manifold solvers.

    • max_stagnation_restarts = 1: More retries after a bad stagnated ALS pass. Higher values can improve solution quality, but increases runtime.
    • stagnation_rel_error = 1e-4: This is a “bad final error” cutoff, not an improvement threshold. Lower value means restarts trigger more easily.
    • restart_candidates = 24: It usually improves chance of finding a better basin, but cost grows roughly linearly.
    • restart_screening_steps = 5: It uses this many quick ALS steps to screen restart candidates.
    • restart_block_maxiter = 20: Inner block-update limit during restart screening for BTD-ALS.
    • restart_seed = nothing: Optional random seed for restart generation for BTD-ALS.

Example

julia> using Random
julia> Random.seed!(0)
julia> A = randn(20, 15, 10); blocks = 10; ranks = (5, 4, 3)
julia> res = btd(A, blocks, ranks; verbose = false)
BTDResult{Float64}
  Blocks:       10
  Rel. error:   0.2625821087015455
source
TensorKitchen.BTDResultType
BTDResult{T}

Result of block-term decomposition (btd); block components expose Tucker structure through accessors like core(blk), factors(blk), and blk.tensor.

  • solver_info: solver-specific diagnostics/metadata (NamedTuple). Typical keys include BTD-ALS restart diagnostics (total_iterations, stagnation_restarts, restart_rel_error_history) and BTD-TSD run settings (schedule, block_repeats, block_count, stepsize).
source
TensorKitchen.blocksFunction
blocks(r::BTDResult)

Return the Tucker block components of a block-term decomposition result.

source
TensorKitchen.reconstructMethod
reconstruct(res::BTDResult)

Reconstruct the dense tensor represented by a block-term decomposition result by summing the reconstructed Tucker blocks.

source