API
API Documentation of OptiFloat.jl
optifloat(expr::Expr, T::Type, batchsize::Int, steps::Int, interval_compatible::Bool)The main function of OptiFloat.jl. Optimizes a floating point expression and returns a result object which contains an improved expression.
Example
julia> using OptiFloat
julia> expr = :(sqrt(x+1) - sqrt(x))
julia> optifloat(expr; T=Float16, batchsize=100, steps=1, interval_compatible=false)For more convenient usage, see @optifloat
Arguments
expr::Expr: The floating point expression that should be optimized.T::Type{<:AbstractFloat}: Floating point type that the expression should be evaluated on.batchsize::Int: Number of samples that OptiFloat will compute errors for. The samples are computed vialogsamplesuch that only samples which do not causeDomainErrors/overflows are used.steps::Int: Number of timessearch_candidates!is called.interval_compatible::Bool: Iffalsethe improved function only accepts normal numbers otherwise theresult.improvedwill be an expression that acceptsIntervals. In the latter case you have to loadIntervalArithmetic, otherwiseeval(result.improved)will fail.
Returns
An OptiFloatResult.
@optifloat expr kws...The main macro of OptiFloat.jl. Optimizes a floating point expression and returns a result object which contains an improved expression. Accepts the same keyword arguments as optifloat.
Examples
julia> using OptiFloat
julia> g = @optifloat sqrt(x+1) - sqrt(x) T=Float16 batchsize=1000
julia> g(Float16(3730))
Float16(0.00819)Internals
Rules that are used to generate new candidate expressions.
Rules that are used to simplify generated candidate expressions. This is a subset of REWRITE_THEORY.
Candidate{E<:Expression,A<:AbstractArray,F<:Function}Holds an original and a candidate expression, as well as their biterror and an indication if the candidate has already been used in search_candidates! (used: ✓, unused: ⊚). Should only be constructed via one of the two constructors below:
Candidate(candidate::Expr, original::Expr, points::AbstractMatrix)Candidate(candidate::Expr, points::AbstractMatrix)(if candidate and original are the same)
OptiFloatResult{O<:Expr,I<:Expr,C<:Candidate,R<:PiecewiseRegime}Fields
original::Expr: The original expression that was attempted to be optimized.improved::Expr: The (potentially) improved expression.original_candidate::Candidate: TheCandidateof the original expression. This struct includes the error on the sampled points.improved_regimes::PiecewiseRegime: The struct that was used to generateimproved.
parse_expression(T::Type{<:AbstractFloat}, expr::Expr; kws...)Parse a Julia Expr to a dynamic Expression that can be used to efficiently compute local_biterrors. Convenience overload of DynamicExpressions.parse_expression.
biterror(x::T, y::T) where {T}The biterror is defined as the logarithm of the ULP-distance (unit at the last place) biterror(x,y) = log2(ulpdistance(x,y)). For the example above to approximately 11 bits:
julia> using OptiFloat
julia> f(x) = sqrt(x+1) - sqrt(x)
julia> g(x) = 1 / (sqrt(x+1) + sqrt(x))
julia> x = Float16(3730)
julia> OptiFloat.biterror(f(x), g(x))infer_regimes(candidates::Vector{<:Candidate}, feature::Int, points::Matrix{T}; kws...)Pick as few candidates and their corresponding good regimes to define a PiecewiseRegime that represents an expression that performs well on all points.
function local_biterror(
tree::Node{T},
ops::AbstractOperatorEnum,
X::AbstractMatrix{T};
accum=default_accum
) where {T}Compute the error of the root node in tree. The children are evaluated exactly, such that only the error of the root node is returned. local_biterrors computes the local error for all nodes in the tree.
function local_biterror(
tree::Node{T},
ops::AbstractOperatorEnum,
X::AbstractMatrix{T};
accum=default_accum
) where {T}Compute the error per node/operation in tree. For each node, the children are evaluated exactly, such that only the error of the current node is returned. local_biterrors computes the error for all nodes in the tree.
local_biterrors(expr::Expression, x::AbstractArray)Recursively call local_biterror on all nodes in expr and return the local error for each node.
logsample(expr::Expression, batchsize::Int; eval_exact=true)Sample valid inputs to expr. If eval_exact=false expr is evaluated with BigFloats so samples might be generated that cause overflow in the original floating point type of expr.
optifloat(expr::Expr, T::Type, batchsize::Int, steps::Int, interval_compatible::Bool)The main function of OptiFloat.jl. Optimizes a floating point expression and returns a result object which contains an improved expression.
Example
julia> using OptiFloat
julia> expr = :(sqrt(x+1) - sqrt(x))
julia> optifloat(expr; T=Float16, batchsize=100, steps=1, interval_compatible=false)For more convenient usage, see @optifloat
Arguments
expr::Expr: The floating point expression that should be optimized.T::Type{<:AbstractFloat}: Floating point type that the expression should be evaluated on.batchsize::Int: Number of samples that OptiFloat will compute errors for. The samples are computed vialogsamplesuch that only samples which do not causeDomainErrors/overflows are used.steps::Int: Number of timessearch_candidates!is called.interval_compatible::Bool: Iffalsethe improved function only accepts normal numbers otherwise theresult.improvedwill be an expression that acceptsIntervals. In the latter case you have to loadIntervalArithmetic, otherwiseeval(result.improved)will fail.
Returns
An OptiFloatResult.
print_report(io::IO, original::Candidate, rs::PiecewiseRegime; rm_ansi=false)Output a report including a copy-pasteable function representing the PiecewiseRegime.
Generate samples from samplefn that yield finite results when called with testfn:
x = samplefn(T, inputsize)
y = testfn(x) <-- add to samples if isfinite(y)search_candidates!(candidates::Vector{<:Candidate}, points::Matrix{T}) where {T}Try to find better candidate expressions than the ones that are already present in candidates. The first unused candidate will be attempted to improve and new candidate expression are added to candidates. Once a candidate is picked, this function goes through the following steps:
Given an initial expression
candidate, compute thelocal_biterrorof every subexpression and pick the subexpressionsub_exprwith the worst error for further analysis.Recursively rewrite the
sub_exprbased on a set of rewrite rules, generating a number of new candidates.Simplify the candidates via equality saturation (implemented in Metatheory.jl)
Compute error of new candidates and add every candidate that performs better on any of the
pointsto the existing list.
@optifloat expr kws...The main macro of OptiFloat.jl. Optimizes a floating point expression and returns a result object which contains an improved expression. Accepts the same keyword arguments as optifloat.
Examples
julia> using OptiFloat
julia> g = @optifloat sqrt(x+1) - sqrt(x) T=Float16 batchsize=1000
julia> g(Float16(3730))
Float16(0.00819)