Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ makedocs(
"Loggers API" => "api/loggers.md",
],
"Approximators" => [
"Approximators Overview" => "api/approximators.md",
"Approximators API" => "api/approximators.md",
"ApproximatorErrors API" => "api/approximator_errors.md",
],
Expand Down
33 changes: 33 additions & 0 deletions docs/src/api/selectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Selectors
```@contents
Pages = ["selectors.md"]
```

## Abstract Types
```@docs
Selector

SelectorRecipe
```

## Selector Structures
```@docs
RLinearAlgebra.LUPP

LUPPRecipe

```

## Exported Functions
```@docs
complete_selector

update_selector!

select_indices!
```

## Internal Functions
```@docs

```
10 changes: 10 additions & 0 deletions src/Approximators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ randomized rangefinder.
"""
abstract type RangeApproximatorRecipe <: ApproximatorRecipe end


###################################
# Docstring Components
###################################
Expand All @@ -72,6 +73,7 @@ approx_arg_list = Dict{Symbol,String}(
:A => "`A::AbstractMatrix`, a target matrix for approximation.",
:compressor_recipe => "`S::CompressorRecipe`, a fully initialized realization for a
compression method for a specific matrix or collection of matrices and vectors.",

)

approx_output_list = Dict{Symbol,String}(
Expand All @@ -82,8 +84,10 @@ approx_output_list = Dict{Symbol,String}(
approx_method_description = Dict{Symbol,String}(
:complete_approximator => "A function that generates an `ApproximatorRecipe` given
arguments.",

:update_approximator => "A function that updates the `ApproximatorRecipe` in place
given the arguments.",

:rapproximate => "A function that computes a low-rank approximation of the matrix `A`
using the information in the provided `Approximator` data structure.",
:complete_approximator_error => "A function that generates an `ApproximatorErrorRecipe`
Expand Down Expand Up @@ -161,6 +165,7 @@ function complete_approximator(approximator::Approximator, A::AbstractMatrix)
)
end


###################################
# rapproximate Interface
###################################
Expand Down Expand Up @@ -430,3 +435,8 @@ end
include("Approximators/RangeApproximators/rangefinder.jl")
include("Approximators/RangeApproximators/randsvd.jl")
include("Approximators/RangeApproximators/helpers/power_its.jl")

############################################
# Include the selector files
############################################
include("Approximators/Selectors.jl")
147 changes: 147 additions & 0 deletions src/Approximators/Selectors.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
###################################
# Abstract Types
###################################
"""
Selector
An abstract type containing user controlled parameters for a technique that select indices
from a matrix.
"""
abstract type Selector end

"""
SelectorRecipe
An abstract type containing user controlled parameters and preallocated memory for a
technique that selects indices from matrix.
"""
abstract type SelectorRecipe end

select_arg_list = Dict{Symbol,String}(
:selector => "`selector::Selector`, a data structure containing the user-defined
parameters associated with a particular selection method.",
:selector_recipe => "`selector_recipe::SelectorRecipe`, a fully initialized realization
for a selector method for a particular matrix.",
:idx => "`idx::vector`, a vector where selected indices will be placed.",
:n_idx => "`n_idx::Int64`, the number of indices to be selected.",
:start_idx => "`start_idx::Int64`. the starting location in `idx` where the indices
will be placed.",
:A => "`A::AbstractMatrix`, a target matrix for approximation.",
)
select_output_list = Dict{Symbol,String}(
:selector_recipe => "A `SelectorRecipe` object.",
)
select_method_description = Dict{Symbol,String}(
:update_selector => "A function that updates the `SelectorRecipe` in place given the
arguments.",
:complete_selector => "A function that generates a `SelectorRecipe` given
arguments.",
:select_indices => "A function that selects indices from a matrix `A` using a specific
`SelectorRecipe`. It updates the vector `idx` in place with `n_idx` new indices starting
at index `start_idx`."
)
##################################
# Complete Selector Interface
##################################
"""
complete_selector(selector::Selector, A::AbstractMatrix)
$(select_method_description[:complete_selector])
# Arguments
- $(select_arg_list[:selector])
- $(select_arg_list[:A])
# Outputs
- $(select_output_list[:selector_recipe])
"""
function complete_selector(selector::Selector, A::AbstractMatrix)
return throw(
ArgumentError(
"No method `complete_selector` exists for selector of type\
$(typeof(selector)) and matrix of type $(typeof(A))."
)
)
end

##################################
# update_selector!
##################################
"""
update_selector!(selector::SelectorRecipe)
$(select_method_description[:update_selector])
# Arguments
- $(select_arg_list[:selector_recipe])
# Outputs
- $(select_output_list[:selector_recipe])
"""
function update_selector!(selector::SelectorRecipe)
return throw(
ArgumentError(
"No method `update_selector!` exists for selector of type\
$(typeof(selector))."
)
)
end

"""
update_selector!(selector::SelectorRecipe, A::AbstractMatrix)
$(select_method_description[:update_selector])
# Arguments
- $(select_arg_list[:selector_recipe])
- $(select_arg_list[:A])
# Outputs
- $(select_output_list[:selector_recipe])
"""
function update_selector!(selector::SelectorRecipe, A::AbstractMatrix)
return update_selector!(selector)
end

####################################
# select_indices!
####################################
"""
select_indices!(
selector::SelectorRecipe,
A::AbstractMatrix,
idx::AbstractVector,
n_idx::Int64,
start_idx::Int64
)
$(select_method_description[:select_indices])
# Arguments
- $(select_arg_list[:selector_recipe])
- $(select_arg_list[:A])
- $(select_arg_list[:idx])
- $(select_arg_list[:n_idx])
- $(select_arg_list[:start_idx])
# Outputs
- Returns `nothing`
"""
function select_indices!(
idx::AbstractVector,
selector::SelectorRecipe,
A::AbstractMatrix,
n_idx::Int64,
start_idx::Int64
)
return throw(
ArgumentError(
"No method `select_indices` exists for selector of type $(typeof(selector)),\
matrix of type $(typeof(A)), idx of type $(typeof(idx)), n_idx of type \
$(typeof(n_idx)), and start_idx of type $(typeof(start_idx))."
)
)
end

# Include the selector files
include("Selectors/lupp.jl")
94 changes: 94 additions & 0 deletions src/Approximators/Selectors/lupp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
LUPP <: Selector
A `Selector` that implements LU with partial pivoting for selecting column indices from a
matrix.
# Fields
- `compressor::Compressor`, the compression technique that will applied to the matrix,
before selecting indices.
# Constructor
LUPP(;compressor = Identity())
## Keywords
- `compressor::Compressor`, the compression technique that will applied to the matrix,
before selecting indices. Defaults the `Identity` compressor.
## Returns
- Will return a `LUPP` object.
"""
mutable struct LUPP <: Selector
compressor::Compressor
end

function LUPP(;compressor = Identity())
LUPP(compressor)
end

"""
LUPPRecipe <: SelectorRecipe
A `SelectorRecipe` that contains all the necessary preallocations for selecting column
indices from a matrix using LU with partial pivoting.
# Fields
- `compressor::Compressor`, the compression technique that will applied to the matrix,
before selecting indices.
- `SA::AbstractMatrix`, a buffer matrix for storing the sketched matrix.
"""
mutable struct LUPPRecipe <: SelectorRecipe
compressor::CompressorRecipe
SA::AbstractMatrix
end

function complete_selector(ingredients::LUPP, A::AbstractMatrix)
compressor = complete_compressor(ingredients.compressor, A)
n_rows, n_cols = size(compressor)
SA = Matrix{eltype(A)}(undef, n_rows, n_cols)
return LUPPRecipe(compressor, SA)
end

function update_selector!(selector::LUPPRecipe)
update_compressor!(selector.compressor)
return nothing
end

function select_indices!(
idx::AbstractVector,
selector::LUPPRecipe,
A::AbstractMatrix,
n_idx::Int64,
start_idx::Int64
)
if n_idx > size(A, 2)
throw(
DimensionMismatch(
"`n_idx` cannot be larger than the number of columns in `A`."
)
)
end

if start_idx + n_idx - 1 > size(idx, 1)
throw(
DimensionMismatch(
"`start_idx` + `n_idx` - 1 cannot be larger than the lenght of `idx`."
)
)
end

if n_idx > selector.compressor.n_rows
throw(
DimensionMismatch(
"Must select fewer indices then the `compression_dim`."
)
)

end

mul!(selector.SA, selector.compressor, A)
# because LUPP selects rows and selectors select columns we need to pivot on A'
p = lu!(selector.SA').p
idx[start_idx:start_idx + n_idx - 1] = p[1:n_idx]
return nothing
end
7 changes: 6 additions & 1 deletion src/RLinearAlgebra.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module RLinearAlgebra
import Base.:*
import Base: transpose, adjoint
import LinearAlgebra: Adjoint, axpby!, dot, I, ldiv!, lmul!, lq!, lq, LQ, mul!, norm, qr!, svd
import LinearAlgebra: Adjoint, axpby!, dot, I, ldiv!, lmul!, lq!, lq, LQ, lu!
import LinearAlgebra: mul!, norm, qr!, svd
import StatsBase: sample, sample!, ProbabilityWeights, wsample!
import Random: bitrand, rand!, randn!
import SparseArrays: SparseMatrixCSC, sprandn, sparse
Expand Down Expand Up @@ -62,4 +63,8 @@ export FullResidual, FullResidualRecipe
export ApproximatorError, ApproximatorErrorRecipe
export complete_approximator_error, compute_approximator_error, compute_approximator_error!

# Export Selector types and functions
export Selector, SelectorRecipe
export LUPP, LUPPRecipe
export complete_selector, update_selector!, select_indices!
end #module
Loading
Loading