Swizzles.jl

AbstracterArrays
Author peterahrens
Popularity
6 Stars
Updated Last
2 Years Ago
Started In
December 2018

Swizzles

Swizzles are Julia operators that allow the user to fuse reduction and transposition operations into broadcast expressions. Swizzles are lazily evaluated, creating a language of Julia objects to represent tensor contractions and related operations. Swizzles were created as a good-faith attempt to implement tensor algebra using the abstractions and programming patterns of base Julia (broadcasting in particular). We hope that the results of our exploration may help inform future implementation decisions and redesigns of the Julia standard library. This project is no longer actively developed; Peter is partitioning graphs now. Swizzles.jl has been tested on Julia 1.5.

What Is?

Swizzle(op, mask...)(init, arg) creates an operator which initializes dst using init, then reduces arg into dst such that dimension d of dst corresponds to dimension mask[d] of arg. This operator is represented lazily using the array type SwizzledArray. Thus,

julia> using Swizzles

julia> A = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

julia> Swizzle(+, 2).(A)
3-element Array{Int64,1}:
 12
 15
 18

julia> Swizzle(+).(A)
45

We can use an instance of the singleton type Nil to insert a size 1 dimension into dst.

julia> Swizzle(+, nil, 2).(A)
1×3 Array{Int64,2}:
 12  15  18

It is convenient to represent transpositions (Swizzles which do not initialize or reduce) using the operator Beam(imask...). Beam(imask...)(arg) produces an output array dst such that dimension imask[d] of dst corresponds to dimension d of arg.

julia> B = [12; 15; 18]
3-element Array{Int64,1}:
 12
 15
 18

julia> Beam(2).(B)
1×3 Array{Int64,2}:
 12  15  18

Notice the similarity between index notation

A[i,j] = ∑ B[i,k,l] * D[l,j] * C[k,j]

and the Swizzles.jl representation

A .= Swizzle(+, 2, 1).(Beam(+, 2, 3, 4).(B) .* Beam(4, 1).(D) .* Beam(3, 1).(C))

Why?

Swizzles.jl was created to provide a trait-based dispatch mechanism for tensor kernel selection and array implementation. Swizzles uses BroadcastStyles and eachindex to help select implementations, and provides an alternative abstract array supertype, StylishArray, for new array types to target. The language of Swizzle and Broadcast provides a high-level intermediate representation for tensor operations.

More Examples!

julia> using Swizzles, LinearAlgebra

julia> x = rand(7); y = rand(7);

julia> Swizzle(+).(x .* y) ≈ dot(x, y)
true

julia> Swizzle(+).(abs.(x)) ≈ norm(x, 1)
true

julia> A = rand(5, 7); B = rand(7, 8);

julia> Swizzle(+, nil, 2).(A) ≈ sum(A, dims=1)
true

julia> Swizzle(+, 2).(A) ≈ sum(A, dims=1)[1,:]
true

julia> Beam(2, 1).(A) ≈ transpose(A)
true

julia> Beam(1, 4).(A) ≈ reshape(A, 5, 1, 1, 7)
true

julia> Swizzle(+, 1, 3).(A.*Beam(2, 3).(B)) ≈ A * B
true