Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast Hadamard Transform #49

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c0e55ab
Added Row SRHT
nathanielpritchard May 22, 2024
054acc9
added column SRHT
nathanielpritchard May 22, 2024
20e6c85
Added FJLT for column
nathanielpritchard May 22, 2024
f0c01e2
made sketching matrix be returned for column SRHT and FJLT
nathanielpritchard May 22, 2024
e1a0ef6
added missing file
nathanielpritchard May 22, 2024
699b1a1
removed overlapping documentation
nathanielpritchard May 22, 2024
f38f2ce
Added citations for the samplers
nathanielpritchard May 22, 2024
5aa0c91
removed helper function folder and moved hadamard to sampler_helper
nathanielpritchard Jun 21, 2024
8562145
Made minor changes
nathanielpritchard Jun 23, 2024
cf1b1ba
Removed unnecessary files
nathanielpritchard Aug 9, 2024
362520c
Reverted unecessary files to master
nathanielpritchard Aug 9, 2024
052e04c
Merge branch 'master' into np_fast_hada_trans
nathanielpritchard Aug 9, 2024
aefbf89
Updated the dependency list
nathanielpritchard Aug 19, 2024
c96d3ca
merMerging brarnches:wq
nathanielpritchard Aug 19, 2024
49cb963
Fixed small formatting issues and added assertion to fwht
nathanielpritchard Aug 27, 2024
2a8c963
Updated with master'
nathanielpritchard Sep 26, 2024
5e77713
Rebased lambda commmit
nathanielpritchard Sep 26, 2024
a82691b
Added Row SRHT
nathanielpritchard May 22, 2024
7d150ba
added column SRHT
nathanielpritchard May 22, 2024
1ea1969
Fixed conflict with new samplers
nathanielpritchard Sep 26, 2024
ed42c49
made sketching matrix be returned for column SRHT and FJLT
nathanielpritchard May 22, 2024
135d30b
added missing file
nathanielpritchard May 22, 2024
c1b8644
removed overlapping documentation
nathanielpritchard May 22, 2024
9f763a2
Added citations for the samplers
nathanielpritchard May 22, 2024
6d7d809
removed helper function folder and moved hadamard to sampler_helper
nathanielpritchard Jun 21, 2024
aea41fe
Made minor changes
nathanielpritchard Jun 23, 2024
ad57568
Fixed merge conflict
nathanielpritchard Sep 26, 2024
7578849
Updated testing issue
nathanielpritchard Sep 26, 2024
3cac0fe
Updated the dependency list
nathanielpritchard Aug 19, 2024
e60b187
Fixed small formatting issues and added assertion to fwht
nathanielpritchard Aug 27, 2024
9b3ff07
Small wording changes in comments
nathanielpritchard Sep 26, 2024
ae2cb96
Changed the setup to return the sampling matrix, and renamed variable…
nathanielpritchard Sep 30, 2024
b3ecad0
updated tests set
nathanielpritchard Oct 2, 2024
d44dac7
Removed redundant directory
nathanielpritchard Oct 2, 2024
a513978
Deleted redundant file
nathanielpritchard Oct 2, 2024
8e4fed8
Fxing merge conflicts
nathanielpritchard Oct 2, 2024
bc2a5a0
Merge branch 'master' into np_fast_hada_trans
nathanielpritchard Oct 2, 2024
4883898
updated the log to the master
nathanielpritchard Oct 3, 2024
b373485
Fixed errors to have working test
nathanielpritchard Oct 3, 2024
dfd9e53
fixed merging issues with ma
nathanielpritchard Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Project.toml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nathanielpritchard we need to be more disciplined about incrementing the version.

Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ version = "0.1.9"
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
DocumenterTools = "35a29f4d-8980-5a13-9543-d66fff28ecb8"
Hadamard = "4a05ff16-5f95-55f4-bb53-bb3f467c689a"
Krylov = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[extras]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
Expand Down
10 changes: 10 additions & 0 deletions docs/src/api/helper_functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Internal Helper Functions

```@contents
Pages = ["helper_functions.md"]
```
## Fast Hadamard transform

```@docs
RLinearAlgebra.fwht!
```
16 changes: 14 additions & 2 deletions docs/src/api/linear_samplers.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ LinSysVecRowMaxDistance

LinSysVecRowDistCyclic
```
## Block Vector Row Samplers

```@docs
LinSysBlockRowFJLT

LinSysBlockRowSRHT
```

## Vector Column Samplers

Expand All @@ -58,7 +65,7 @@ LinSysVecColDetermCyclic
LinSysVecColOneRandCyclic
```

## Block Vector Row Samplers
## Block Row Samplers

```@docs
LinSysBlkRowGaussSampler
Expand All @@ -68,14 +75,19 @@ LinSysBlkRowReplace
LinSysBlkRowRandCyclic
```

## Block Vector Col Samplers
## Block Col Samplers

```@docs
LinSysBlkColGaussSampler

LinSysBlkColReplace

LinSysBlkColRandCyclic

LinSysBlockColFJLT

LinSysBlockColSRHT

```

## Sample Function
Expand Down
8 changes: 7 additions & 1 deletion src/RLinearAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ module RLinearAlgebra

using LinearAlgebra, Random, Distributions

import SparseArrays: sprandn, SparseMatrixCSC

import Hadamard: hadamard
vp314 marked this conversation as resolved.
Show resolved Hide resolved
###########################################
# Exports
###########################################
Expand All @@ -43,14 +46,17 @@ export LinSysVecRowDetermCyclic, LinSysVecRowHopRandCyclic, LinSysVecRowOneRandC
LinSysVecRowPropToNormSampler, LinSysVecRowSVSampler, LinSysVecRowRandCyclic,
LinSysVecRowUnidSampler, LinSysVecRowUnifSampler, LinSysVecRowGaussSampler,
LinSysVecRowSparseUnifSampler, LinSysVecRowSparseGaussSampler, LinSysVecRowMaxResidual,
LinSysVecRowMaxDistance, LinSysVecRowResidCyclic, LinSysVecRowDistCyclic
LinSysVecRowMaxDistance, LinSysVecRowResidCyclic, LinSysVecRowDistCyclic, LinSysBlockRowSRHT,
LinSysBlockRowFJLT

# Vector Column Samplers
export LinSysVecColDetermCyclic, LinSysVecColOneRandCyclic
#Vector Block Row Samplers
export LinSysBlkRowGaussSampler, LinSysBlkRowRandCyclic, LinSysBlkRowReplace
#Vector Block Column Samplers
export LinSysBlkColRandCyclic, LinSysBlkColGaussSampler, LinSysBlkColReplace
export LinSysVecColDetermCyclic, LinSysVecColOneRandCyclic, LinSysBlockColSRHT, LinSysBlockColFJLT

#*****************************************#
# Linear Solver Routine Exports
#*****************************************#
Expand Down
9 changes: 9 additions & 0 deletions src/linear_samplers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ include("linear_samplers/vec_row_uniform.jl")
include("linear_samplers/vec_row_gaussian.jl")
include("linear_samplers/vec_row_uniform_sparse.jl")
include("linear_samplers/vec_row_gaussian_sparse.jl")
include("linear_samplers/block_row_SRHT.jl")
include("linear_samplers/block_row_FJLT.jl")
#include("linear_samplers/vec_row_uniform_sym_sparse.jl")
#include("linear_samplers/vec_row_uniform_sym.jl")

Expand All @@ -161,6 +163,13 @@ include("linear_samplers/vec_col_one_rand_cyclic.jl")
# Non-adaptive Sampling (with replacement)
#Leventhal-Lewis (non-symmetric)

# Non-adaptive Sketching
include("linear_samplers/block_col_SRHT.jl")
include("linear_samplers/block_col_FJLT.jl")
#############################################
# Fast Transforms
#############################################
include("linear_samplers/sampler_helpers/hadamard.jl")
#############################################
# Block Row Sampler/Sketch/Selector
#############################################
Expand Down
88 changes: 88 additions & 0 deletions src/linear_samplers/block_col_FJLT.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""
LinSysBlockColFJLT <: LinSysBlkColSampler

A mutable structure with fields to handle FJLT row sketching. For this procedure,
the hadamard transform and random sign swaps are applied once, then that matrix is repeatably
sampled.

# Fields
- `block_size::Int64`, the size of the sketching dimension
- `sparsity::Float64`, the sparsity of the sampling matrix, should be between 0 and 1
- `padded_size::Int64`, the size of the matrix when padded
- `sampling_matrix::Union{SparseMatrixCSC, Nothing}`, storage for sparse sketching matrix
- `hadamard::Union{AbstractMatrix, Nothing}`, storage for the hadamard matrix.
- `Ap::Union{AbstractMatrix, Nothing}`, storage for padded matrix
- `bp::Union{AbstractMatrix, Nothing}`, storage for padded vector
- `signs::Union{Vector{Bool}, Nothing}`, storage for random sign flips.
- `scaling::Float64`, storage for the scaling of the sketches.

Calling `LinSysBlockColFJLT()` defaults to setting `sparsity` to .3 and the blocksize to 2.

Nir Ailon and Bernard Chazelle. 2006. Approximate nearest neighbors and the fast Johnson-Lindenstrauss transform. In Proceedings of the thirty-eighth annual ACM symposium on Theory of Computing (STOC '06). Association for Computing Machinery, New York, NY, USA, 557–563. https://doi.org/10.1145/1132516.1132597
"""
mutable struct LinSysBlockColFJLT <: LinSysBlkColSampler
block_size::Int64
sparsity::Float64
padded_size::Int64
sampling_matrix::Union{SparseMatrixCSC, Nothing}
hadamard::Union{AbstractMatrix, Nothing}
Ap::Union{AbstractMatrix, Nothing}
bp::Union{AbstractVector, Nothing}
signs::Union{Vector{Bool}, Nothing}
scaling::Float64
end

LinSysBlockColFJLT(;blocksize = 2, sparsity = .3) = LinSysBlockColFJLT(
blocksize,
sparsity,
0,
nothing,
nothing,
nothing,
nothing,
nothing,
0.0
)

# Common sample interface for linear systems
function sample(
type::LinSysBlockColFJLT,
A::AbstractArray,
b::AbstractVector,
x::AbstractVector,
iter::Int64
)
if iter == 1
m, n = size(A)
# If matrix is not a power of 2 then pad the rows
if rem(log(2, n), 1) != 0
type.padded_size = Int64(2^(div(log(2, n), 1) + 1))
# Find nearest power 2 and allocate
type.Ap = zeros(m, type.padded_size)
# Pad matrix and constant vector
type.Ap[:, 1:n] .= A
else
type.padded_size = n
type.Ap = A
end
type.hadamard = hadamard(type.padded_size)
# Compute scaling and sign flips
type.scaling = sqrt(type.block_size / (type.padded_size * type.sparsity))
type.signs = bitrand(type.padded_size)
# Apply FWHT to padded matrix and vector
for i = 1:m
Av = view(type.Ap, i, :)
# Perform the fast walsh hadamard transform and update the ith column of Ap
fwht!(Av, signs = type.signs, scaling = type.scaling)
end

end

type.sampling_matrix = sprandn(type.padded_size, type.block_size, type.sparsity)
AS = type.Ap * type.sampling_matrix
# Residual of the linear system
res = A * x - b
grad = AS' * res
sgn = [type.signs[i] ? 1 : -1 for i in 1:type.padded_size]
return ((sgn .* type.hadamard) * type.sampling_matrix .* type.scaling), AS, res, grad
end
85 changes: 85 additions & 0 deletions src/linear_samplers/block_col_SRHT.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

"""
LinSysBlockColSRHT <: LinSysBlkColSampler

A mutable structure with fields to handle SRHT column sketching. For this procedure,
the hadamard transform and random sign swaps are applied once, then that matrix is repeatably
sampled.

# Fields
- `block_size::Int64`, the size of blocks being chosen
- `padded_size::Int64`, the size of the matrix when padded
- `block::Union{Vector{Int64}, Nothing}`, storage for block indices
- `hadamard::Union{AbstractMatrix, Nothing}`, storage for the hadamard matrix.
- `Ap::Union{AbstractMatrix, Nothing}`, storage for padded matrix
- `signs::Union{Vector{Bool}, Nothing}`, storage for random sign flips.
- `scaling::Float64`, storage for the scaling of the sketches.

Calling `LinSysBlockColSRHT()` defaults to setting `block_size` to 2.

Nir Ailon and Bernard Chazelle. 2006. Approximate nearest neighbors and the fast Johnson-Lindenstrauss transform. In Proceedings of the thirty-eighth annual ACM symposium on Theory of Computing (STOC '06). Association for Computing Machinery, New York, NY, USA, 557–563. https://doi.org/10.1145/1132516.1132597
"""
mutable struct LinSysBlockColSRHT <: LinSysBlkColSampler
block_size::Int64
padded_size::Int64
block::Union{Vector{Int64}, Nothing}
hadamard::Union{AbstractMatrix, Nothing}
Ap::Union{AbstractMatrix, Nothing}
signs::Union{Vector{Bool}, Nothing}
scaling::Float64
end

LinSysBlockColSRHT(block_size) = LinSysBlockColSRHT(
block_size,
0,
nothing,
nothing,
nothing,
nothing,
0.0
)
LinSysBlockColSRHT() = LinSysBlockColSRHT(2, 0, nothing, nothing, nothing, nothing, 0.0)

# Common sample interface for linear systems
function sample(
type::LinSysBlockColSRHT,
A::AbstractArray,
b::AbstractVector,
x::AbstractVector,
iter::Int64
)
if iter == 1
m, n = size(A)
# If matrix is not a power of 2 then pad the rows
if rem(log(2, n), 1) != 0
type.padded_size = Int64(2^(div(log(2, n), 1) + 1))
# Find nearest power 2 and allocate
type.Ap = zeros(m, type.padded_size)
# Pad matrix and constant vector
type.Ap[:, 1:n] .= A
else
type.padded_size = n
type.Ap = A
end
type.hadamard = hadamard(type.padded_size)
# Compute scaling and sign flips
type.scaling = sqrt(type.block_size / type.padded_size)
type.signs = bitrand(type.padded_size)
for i = 1:m
Av = view(type.Ap, i, :)
# Perform the fast walsh hadamard transform and update the ith column of Ap
fwht!(Av, signs = type.signs, scaling = type.scaling)
end

type.block = zeros(Int64, type.block_size)
end

type.block .= randperm(type.padded_size)[1:type.block_size]
AS = type.Ap[:, type.block]
# Residual of the linear system
res = A * x - b
grad = AS'res
H = hadamard(type.padded_size)
sgn = [type.signs[i] ? 1 : -1 for i in 1:type.padded_size]
return ((sgn .* type.hadamard) .* type.scaling)[:, type.block], AS, res, grad
end
92 changes: 92 additions & 0 deletions src/linear_samplers/block_row_FJLT.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""
LinSysBlockRowFJLT <: LinSysBlkRowSampler

A mutable structure with fields to handle FJLT row sketching. For this procedure,
the hadamard transform and random sign swaps are applied once, then that matrix is repeatably
sampled.

# Fields
- `block_size::Int64`, the size of the sketching dimension
- `sparsity::Float64`, the sparsity of the sampling matrix
- `padded_size::Int64`, the size of the matrix when padded
- `sampling_matrix::Union{SparseMatrixCSC, Nothing}`, storage for sparse sketching matrix
- `hadamard::Union{AbstractMatrix, Nothing}`, storage for the hadamard matrix.
- `Ap::Union{AbstractMatrix, Nothing}`, storage for padded matrix
- `bp::Union{AbstractMatrix, Nothing}`, storage for padded vector
- `signs::Union{Vector{Bool}, Nothing}`, storage for random sign flips.
- `scaling::Float64`, storage for the scaling of the sketches.

Calling `LinSysBlockRowFJLT()` defaults to setting `sparsity` to .3 and the blocksize to 2.

Nir Ailon and Bernard Chazelle. 2006. Approximate nearest neighbors and the fast Johnson-Lindenstrauss transform. In Proceedings of the thirty-eighth annual ACM symposium on Theory of Computing (STOC '06). Association for Computing Machinery, New York, NY, USA, 557–563. https://doi.org/10.1145/1132516.1132597
"""
mutable struct LinSysBlockRowFJLT <: LinSysBlkRowSampler
block_size::Int64
sparsity::Float64
padded_size::Int64
sampling_matrix::Union{SparseMatrixCSC, Nothing}
hadamard::Union{AbstractMatrix, Nothing}
Ap::Union{AbstractMatrix, Nothing}
bp::Union{AbstractVector, Nothing}
signs::Union{Vector{Bool}, Nothing}
scaling::Float64
end

LinSysBlockRowFJLT(;blocksize = 2, sparsity = .3) = LinSysBlockRowFJLT(
blocksize,
sparsity,
0,
nothing,
nothing,
nothing,
nothing,
nothing,
0.0
)

# Common sample interface for linear systems
function sample(
type::LinSysBlockRowFJLT,
A::AbstractArray,
b::AbstractVector,
x::AbstractVector,
iter::Int64
)
if iter == 1
m, n = size(A)
# If matrix is not a power of 2 then pad the rows
if rem(log(2, m), 1) != 0
type.padded_size = Int64(2^(div(log(2, m), 1) + 1))
# Find nearest power 2 and allocate
type.Ap = zeros(type.padded_size, n)
type.bp = zeros(type.padded_size)
# Pad matrix and constant vector
type.Ap[1:m, :] .= A
type.bp[1:m] .= b
else
type.padded_size = m
type.Ap = A
type.bp = b
end
type.hadamard = hadamard(type.padded_size)
# Compute scaling and sign flips
type.scaling = sqrt(type.block_size / (type.padded_size * type.sparsity))
type.signs = bitrand(type.padded_size)
# Apply FWHT to padded matrix and vector
fwht!(type.bp, signs = type.signs, scaling = type.scaling)
for i = 1:n
Av = view(type.Ap, :, i)
# Perform the fast walsh hadamard transform and update the ith row of Ap
@views fwht!(Av, signs = type.signs, scaling = type.scaling)
end

end

type.sampling_matrix = sprandn(type.block_size, type.padded_size, type.sparsity)
SA = type.sampling_matrix * type.Ap
Sb = type.sampling_matrix * type.bp
# Residual of the linear system
res = SA * x - Sb
sgn = [type.signs[i] ? 1 : -1 for i in 1:type.padded_size]
return type.sampling_matrix * (sgn .* type.hadamard) .* type.scaling, SA, res
end
Loading
Loading