Skip to content

Add native kron (Kronecker product) affine atom#101

Draft
Transurgeon wants to merge 4 commits into
mainfrom
kron-native-atom
Draft

Add native kron (Kronecker product) affine atom#101
Transurgeon wants to merge 4 commits into
mainfrom
kron-native-atom

Conversation

@Transurgeon

Copy link
Copy Markdown
Member

cvxpy's kron(A, B) always has one variable-free operand, so every output entry depends on a single child entry: Z[OUT] = coeff[OUT] * child[child_row[OUT]]. The output Jacobian is therefore the child Jacobian's rows gathered (with repetition) and scaled by the variable-free operand -- no coefficient matrix, no matmul, no CSC conversion; O(nnz(result)). child_row[] and coeff_idx[] depend only on the operand shapes and are precomputed once in new_kron.

Handles kron(param/const, var) and kron(var, param/const), parametric or constant, with column-major (Fortran) flattening, and re-evaluates the variable-free operand each solve. forward, Jacobian and the affine Hessian backprop are all scaled gathers.

Adds forward/Jacobian/wsum_hess unit tests (both forms, scalar operand, and numerical Jacobian/Hessian checks on a composite arg); all_tests now 405.

Transurgeon and others added 2 commits June 28, 2026 18:55
cvxpy's kron(A, B) always has one variable-free operand, so every output
entry depends on a single child entry: Z[OUT] = coeff[OUT] * child[child_row[OUT]].
The output Jacobian is therefore the child Jacobian's rows gathered (with
repetition) and scaled by the variable-free operand -- no coefficient matrix,
no matmul, no CSC conversion; O(nnz(result)). child_row[] and coeff_idx[]
depend only on the operand shapes and are precomputed once in new_kron.

Handles kron(param/const, var) and kron(var, param/const), parametric or
constant, with column-major (Fortran) flattening, and re-evaluates the
variable-free operand each solve. forward, Jacobian and the affine Hessian
backprop are all scaled gathers.

Adds forward/Jacobian/wsum_hess unit tests (both forms, scalar operand, and
numerical Jacobian/Hessian checks on a composite arg); all_tests now 405.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply clang-format and tidy the native kron atom: factor parameter
refresh into a helper, null freed pointers, and trim doc duplicated by
the kron_expr definition in subexpr.h.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Transurgeon Transurgeon marked this pull request as draft June 29, 2026 02:23
Transurgeon and others added 2 commits July 5, 2026 14:54
…matmul

block_left_multiply_fill_sparsity tested every row of A against each
(column, block) via has_overlap — O(n_vars x n_blocks x A_rows) at
Jacobian-init time. Gather instead: build a CSC view of A once, walk only
the columns hit by the block's child entries, dedup rows with a
generation-stamp workspace and sort ascending. Output is byte-identical
(same predicate, same order), so fill_values is untouched.

csr_csc_matmul_alloc had the same full row-times-column scan; same
treatment via a one-time CSR view of B.

Tests: dedup and interleaved-order cases that fail without the stamp or
the sort, plus randomized cross-checks against the original scan kept as
a reference implementation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
new_kron materialized every output row, including the structurally-zero
blocks of a sparse constant operand — kron(I_p, X) built p^2 blocks of
Jacobian rows with p(p-1) of them zero. Replace it with new_left_kron /
new_right_kron taking the constant operand's active (nonzero) block
indices, column-major; inactive output rows keep child_row == -1 and
contribute a zero value and an empty Jacobian row. cvxpy passes the
constant's nonzeros (all blocks for an updatable parameter, whose zeros
are not permanent).

Constructors assert active block indices are in range.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant