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 17 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
5 changes: 5 additions & 0 deletions docs/src/man/cls_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,8 @@ solver = RLSSolver(
# Solve the system
sol = rsolve(solver, A, b)
```

## Block Methods for Linear Systems

Because of the way that computers operate, it is often more efficient to work using
blocks of data rather than single vectors to generate updates to solutions.
9 changes: 7 additions & 2 deletions 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,16 @@ 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 LinSysBlkColRandCyclic, LinSysBlkColGaussSampler, LinSysBlkColReplace, 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
83 changes: 83 additions & 0 deletions src/linear_samplers/block_col_FJLT.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
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
- `blockSize::Int64`, the size of the sketching dimension
- `sparsity::Float64`, the sparsity of the sampling matrix
nathanielpritchard marked this conversation as resolved.
Show resolved Hide resolved
- `paddedSize::Int64`, the size of the matrix when padded
- `Sketch::Union{SparseMatrixCSC, Nothing}`, storage for sparse sketching matrix
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not think this is a good name for this field as it is its own sketch, certainly, but in this context it is part of a larger sketching procedure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have renamed it to sampling matrix because the sparse matrix is essentially sampling the random 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
blockSize::Int64
sparsity::Float64
paddedSize::Int64
Sketch::Union{SparseMatrixCSC, 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,
0.0
)
vp314 marked this conversation as resolved.
Show resolved Hide resolved

# 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.paddedSize = Int64(2^(div(log(2, n), 1) + 1))
# Find nearest power 2 and allocate
type.Ap = zeros(m, type.paddedSize)
# Pad matrix and constant vector
@views type.Ap[:, 1:n] .= A
nathanielpritchard marked this conversation as resolved.
Show resolved Hide resolved
else
type.paddedSize = n
type.Ap = A
end
# Compute scaling and sign flips
type.scaling = sqrt(type.blockSize / (type.paddedSize * type.sparsity))
type.signs = bitrand(type.paddedSize)
# Apply FWHT to padded matrix and vector
for i = 1:m
@views fwht!(type.Ap[i, :], signs = type.signs, scaling = type.scaling)
nathanielpritchard marked this conversation as resolved.
Show resolved Hide resolved
end

end

type.Sketch = sprandn(type.paddedSize, type.blockSize, type.sparsity)
AS = type.Ap * type.Sketch
# Residual of the linear system
res = A * x - b
grad = AS'res
nathanielpritchard marked this conversation as resolved.
Show resolved Hide resolved
H = hadamard(type.paddedSize)
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is H used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should be used when returning the actual sketching matrix. I have revised the code to actually accomplish this, instead partially return the sketching matrix.

sgn = [type.signs[i] ? 1 : -1 for i in 1:type.paddedSize]
return [sgn, type.Sketch .* type.scaling], AS, res, grad
Copy link
Contributor

Choose a reason for hiding this comment

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

You are not returning the actual sketch, just pieces of it? Is that correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

Unlike the row case, this one is a bit harder to justify in terms of transforming the problem since you need to get the residual from the original problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Justifying the padded transformation in this case is certainly harder; however, we probably should still provide the functionality of column sketching with these Hadamard matrices if we are going to provide it for the row versions.

end
79 changes: 79 additions & 0 deletions src/linear_samplers/block_col_SRHT.jl
vp314 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@

"""
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
- `blockSize::Int64`, the size of blocks being chosen
- `paddedSize::Int64`, the size of the matrix when padded
- `block::Union{Vector{Int64}, Nothing}`, storage for block indices
- `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 `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 LinSysBlockColSRHT <: LinSysBlkColSampler
blockSize::Int64
paddedSize::Int64
block::Union{Vector{Int64}, Nothing}
Ap::Union{AbstractMatrix, Nothing}
signs::Union{Vector{Bool}, Nothing}
scaling::Float64
end

LinSysBlockColSRHT(blockSize) = LinSysBlockColSRHT(
blockSize,
0,
nothing,
nothing,
nothing,
0.0
)
LinSysBlockColSRHT() = LinSysBlockColSRHT(2, 0, 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.paddedSize = Int64(2^(div(log(2, n), 1) + 1))
# Find nearest power 2 and allocate
type.Ap = zeros(m, type.paddedSize)
# Pad matrix and constant vector
type.Ap[:, 1:n] .= A
else
type.paddedSize = n
type.Ap = A
end
# Compute scaling and sign flips
type.scaling = sqrt(type.blockSize / type.paddedSize)
type.signs = bitrand(type.paddedSize)
for i = 1:m
@views fwht!(type.Ap[i, :], signs = type.signs, scaling = type.scaling)
end

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

type.block .= randperm(type.paddedSize)[1:type.blockSize]
AS = type.Ap[:, type.block]
# Residual of the linear system
res = A * x - b
grad = AS'res
H = hadamard(type.paddedSize)
sgn = [type.signs[i] ? 1 : -1 for i in 1:type.paddedSize]
return [sgn .* type.scaling, type.block], AS, res, grad
end
85 changes: 85 additions & 0 deletions src/linear_samplers/block_row_FJLT.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""
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
- `blockSize::Int64`, the size of the sketching dimension
- `sparsity::Float64`, the sparsity of the sampling matrix
- `paddedSize::Int64`, the size of the matrix when padded
- `Sketch::Union{SparseMatrixCSC, Nothing}`, storage for sparse sketching matrix
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment regarding the naming choice as in the column case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same response as in the column case.

- `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
blockSize::Int64
sparsity::Float64
paddedSize::Int64
Sketch::Union{SparseMatrixCSC, 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,
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.paddedSize = Int64(2^(div(log(2, m), 1) + 1))
# Find nearest power 2 and allocate
type.Ap = zeros(type.paddedSize, n)
type.bp = zeros(type.paddedSize)
# Pad matrix and constant vector
@views type.Ap[1:m, :] .= A
@views type.bp[1:m] .= b
nathanielpritchard marked this conversation as resolved.
Show resolved Hide resolved
else
type.paddedSize = m
type.Ap = A
type.bp = b
end
# Compute scaling and sign flips
type.scaling = sqrt(type.blockSize / (type.paddedSize * type.sparsity))
type.signs = bitrand(type.paddedSize)
# Apply FWHT to padded matrix and vector
fwht!(type.bp, signs = type.signs, scaling = type.scaling)
for i = 1:n
@views fwht!(type.Ap[:, i], signs = type.signs, scaling = type.scaling)
end
nathanielpritchard marked this conversation as resolved.
Show resolved Hide resolved

end

type.Sketch = sprandn(type.blockSize, type.paddedSize, type.sparsity)
SA = type.Sketch * type.Ap
Sb = type.Sketch * type.bp
# Residual of the linear system
res = SA * x - Sb
return type.Sketch, SA, res
Copy link
Contributor

Choose a reason for hiding this comment

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

You are not actually returning the sketch here, just a piece of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I think I see. You are transforming the original problem. You have created a new problem and so you are sketching the new problem with type.Sketch. Is this correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was correct, but to align with the other sampling/sketching methods the full matrix should be returned. I have made this adjustment in all the files.

end
Loading
Loading