HerbiePlugin alternatives and similar packages
Based on the "Math" category.
Alternatively, view HerbiePlugin alternatives based on common mentions on social networks and blogs.

vector
An efficient implementation of Intindexed arrays (both mutable and immutable), with a powerful loop optimisation framework . 
statistics
A fast, high quality library for computing with statistics in Haskell. 
hgeometry
HGeometry is a library for computing with geometric objects in Haskell. It defines basic geometric types and primitives, and it implements some geometric data structures and algorithms. The main two focusses are: (1) Strong type safety, and (2) implementations of geometric algorithms and data structures that have good asymptotic running time guarantees. 
dimensional
Dimensional library variant built on Data Kinds, Closed Type Families, TypeNats (GHC 7.8+). 
computationalalgebra
GeneralPurpose Computer Algebra System as an EDSL in Haskell 
mwcrandom
A very fast Haskell library for generating high quality pseudorandom numbers. 
matrix
A Haskell native implementation of matrices and their operations. 
numhask
A haskell numeric prelude, providing a clean structure for numbers and operations that combine them. 
vectorspace
Vector & affine spaces, linear maps, and derivatives 
poly
Fast polynomial arithmetic in Haskell (dense and sparse, univariate and multivariate, usual and Laurent) 
cf
"Exact" real arithmetic for Haskell using continued fractions (Not formally proven correct) 
optimization
Some numerical optimization methods implemented in Haskell 
bayesstack
Framework for Gibbs sampling of probabilistic models 
rampart
:european_castle: Determine how intervals relate to each other. 
equationalreasoning
Agdastyle equational reasoning in Haskell 
safedecimal
Safe and very efficient arithmetic operations on fixed decimal point numbers 
sbvPlugin
Formally prove properties of Haskell programs using SBV/SMT. 
polynomial
Haskell library for manipulating and evaluating polynomials 
monoidsubclasses
Subclasses of Monoid with a solid theoretical foundation and practical purposes 
eigen
Haskel binding for Eigen library. Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms. 
modulararithmetic
A useful type for working with integers modulo some constant. 
manifoldrandom
Coordinatefree hypersurfaces as Haskell types
Clean code begins in your IDE with SonarLint
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of HerbiePlugin or a related project?
README
Herbie GHC Plugin
The Herbie GHC Plugin automatically improves the numerical stability of your Haskell code. The Herbie plugin fully supports the SubHask numeric prelude, and partially supports the standard prelude (see the known bugs section below).
This README is organized into the following sections:
 Example: linear algebra and numerical stability
 How the Herbie plugin works
 Installing and using the Herbie plugin
 Compiling all of stackage with the Herbie plugin
 Known bugs
Example: linear algebra and numerical instability
The popular linear library contains the following calculation:
w :: Double > Double > Double
w far near = (2 * far * near) / (far  near)
This code looks correct, but it can give the wrong answer.
When the values of far
and near
are both very small (or very large), the product far * near
will underflow to 0 (or overflow to infinity).
In the worst case scenario using Double
s, this calculation can lose up to 14 bits of information.
The Herbie plugin automatically prevents this class of bugs (with some technical caveats, see how it works below). If you compile the linear package with Herbie, the code above gets rewritten to:
w :: Double > Double > Double
w far near = if far < 1.7210442634149447e81
then ((2 * far) / (far  near)) * near
else if far < 8.364504563556443e16
then 2 * far * (near / (far  near))
else ((2 * far) / (far  near)) * near
This modified code is numerically stable. The if statements check to see which regime we are in (very small or very large) and select the calculation that is most appropriate for this regime.
The test suite contains MANY more examples of the types of expressions the Herbie plugin can analyze.
How it works
GHC Plugins let library authors add new features to the Haskell compiler. The Herbie plugin gets run after type checking, but before any optimizations. Because GHC is so good at optimizing, the code generated by the Herbie plugin is just as fast as handwritten code. The plugin has two key components: first it finds the floating point computations in your code; then it replaces them with numerically stable versions.
Finding the computations
When the Herbie plugin is run, it traverses your code's abstract syntax tree looking for mathematical expressions. These expressions may:
consist of the following operators:
/
,*
,
,*
,**
,^
,^^
,$
,cos
,sin
,tan
,acos
,asin
,atan
,cosh
,sinh
,tanh
,exp
,log
,sqrt
,abs
contain an arbitrary number of free variables
contain arbitrary nonmathematical subexpressions
For example, in the function below:
test :: String > String
test str = show ( sqrt (1+fromIntegral (length str))
 sqrt (fromIntegral (length str))
:: Float
)
the Herbie plugin extracts the expression sqrt (x+1)  sqrt x
;
calculates the numerically stable version 1 / (sqrt (x+1) + sqrt x)
;
and then substitutes back in.
The Herbie plugin performs this procedure on both concrete types (Float
and Double
) and polymorphic types.
For example, the plugin will rewrite
f :: Field a => a > a > a
f far near = (far+near)/(far*near*2)
to
f :: Field a => a > a > a
f far near = 0.5/far + 0.5/near
(The Field
constraint comes from SubHask.)
These polymorphic rewrites are always guaranteed to preserve the semantics when the expression is evaluated on an exact numeric type.
So both versions of f
above are guaranteed to give the same result when called on Rational
values,
but the rewritten version will be more accurate when called on Float
or Double
.
The main limitation of the Herbie plugin is that any recursive part of an expression is ignored. This is because analyzing the numeric stability of a Turing complete language is undecidable (and no practical heuristics are known). <!Creating a practical algorithm that can analyze the cases programmers encounter in practice remains an open research problem.> Fortunately, the Herbie plugin can still analyze the nonrecursive subexpressions of a recursive expression. So in the code:
go :: Float > Float > Float
go 0 b = b
go a b = go (a1) (sqrt $ (a+b) * (a+b))
the expression sqrt $ (a+b) * (a+b)
gets rewritten by Herbie into abs (a+b)
.
Disabling Herbie
You can prevent Herbie from analyzing a function using an annotation pragma. In the following example:
{# ANN foo "NoHerbie" #}
foo x = (x + 1)  x
Herbie will NOT rewrite the code into
foo x = 1
These GHC annotations can only be applied to top level bindings. They prevent Herbie from searching anywhere inside the binding.
Improving the stability of expressions
The Herbie plugin uses two sources of information to find numerically stable replacements for expressions. The simplest source is a sqlite3 database. This database contains about 400 expressions that are known to be used by Haskell libraries.
The more important source is the Herbie program. Herbie is a recent research project on using probabilistic searches to find numerically stable expressions. Because Herbie is probabilistic, it provides weak theoretic guarantees on the numerical stability of the resulting expressions; but in practice, the improved expressions are significantly better. To ensure reproducible builds, the same random seed is used on all calls to the Herbie program. For more details on how Herbie works, check out the PLDI15 paper.
The Herbie program can take a long time to run.
If the program doesn't return a solution within two minutes,
then the Herbie plugin assumes that no better solution is possible and continues processing.
To improve compile times, every time the Herbie program returns a new solution,
the solution is added to the Herbie.db
database.
When compiling a file, if all the math expressions are already in the database,
then the Herbie plugin imposes essentially no overhead on compile times.
Installing and Using the Herbie Plugin
The Herbie plugin requires GHC 7.10.1 or 7.10.2. It is installable via cabal using the command:
cabal update && cabal install HerbiePlugin
It is recommended (but not required) that you also install the Herbie program. (Without installing the program, the Herbie plugin can only replace expressions in the standard database.) The Herbie program is written in racket, so you must first install Racket. Go to the download page for Racket 6.1.1 and install the version for your platform. Then run the commands:
git clone http://github.com/mikeizbicki/HerbiePlugin recursive
cd HerbiePlugin/herbie
raco exe o herbieexec herbie/interface/inout.rkt
The last line creates an executable herbieexec
that the Herbie plugin will try to call.
You must move the program somewhere into your PATH
for these calls to succeed.
One way to do this is with the command:
sudo mv herbieexec /usr/local/bin
To compile a file with the Herbie plugin, you need to pass the flag fplugin=Herbie
to when calling GHC.
You can have cabal install
automatically apply the Herbie plugin by passing the following flags
ghcoption=fplugin=Herbie
ghcoption=packageid herbiehaskell0.1.0.050ba55c8f248a3301dce2d3339977982
Running Herbie on all of stackage
Stackage LTS3.5 is a collection of 1351 of the most popular Haskell libraries. The script install.sh compiles all of stackage using the Herbie plugin.
48 of the 1351 packages (3.5%) use floating point computations internally. Of these, 40 packages (83%) contain expressions whose numerical stability is improved with the Herbie plugin. In total, there are 303 distinct numerical expressions used in all stackage packages, and 164 of these expressions (54%) are more stable using the Herbie plugin.
The table below shows a detailed breakdown of which packages contain the unstable expressions. Notice that the unstable and stable expression columns may not add up to the total expressions column. The difference is the expressions could not be analyzed because the Herbie program timed out.
package  total math expressions  unstable expressions  stable expressions 

mathfunctions0.1.5.2  92  50  34 
colour2.3.3  28  8  18 
linear1.19.1.3  28  19  8 
diagramslib1.3.0.3  25  15  10 
diagramssolve0.1  25  14  11 
statistics0.13.2.3  15  5  7 
plot0.2.3.4  12  9  2 
randomfu0.2.6.2  11  4  5 
Chart1.5.3  10  8  2 
circlepacking0.1.0.4  9  3  6 
mwcrandom0.13.3.2  9  1  7 
Rasterific0.6.1  8  3  5 
diagramscontrib1.3.0.5  6  6  0 
logdomain0.10.2.1  5  0  5 
repaalgorithms3.4.0.1  5  3  2 
rasterificsvg0.2.3.1  4  2  2 
sbv4.4  4  2  2 
clustering0.2.1  3  1  2 
erf2.0.0.0  3  2  1 
hsignal0.2.7.1  3  2  0 
hyperloglog0.3.4  3  1  2 
integration0.2.1  3  1  2 
intervals0.7.1  3  2  1 
shake0.15.5  3  2  1 
Chartdiagrams1.5.1  2  2  0 
JuicyPixels3.2.6.1  2  2  0 
Yampa0.10.2  2  2  0 
YampaSynth0.2  2  1  1 
diagramsrasterific1.3.1.3  2  1  1 
faybase0.20.0.1  2  1  1 
histogramfill0.8.4.1  2  0  2 
parsec3.1.9  2  0  2 
smoothie0.4.0.2  2  2  0 
Octree0.5.4.2  1  1  0 
ad4.2.4  1  1  0 
approximate0.2.2.1  1  1  0 
cryptorandom0.0.9  1  1  0 
diagramscairo1.3.0.3  1  1  0 
diagramssvg1.3.1.4  1  1  0 
dice0.1  1  0  1 
forcelayout0.4.0.2  1  1  0 
gipeda0.1.2.1  1  0  1 
hakyll4.7.2.3  1  0  1 
hashtables1.2.0.2  1  1  0 
hmatrix0.16.1.5  1  0  1 
hscolour1.23  1  0  1 
metrics0.3.0.2  1  1  0 
<! table created with the sqlite code:
select A.dbgComments,A.q,B.q,C.q from ( (select distinct dbgComments,count() as q from StabilizerResults as A join (select distinct dbgComments,resid from DbgInfo) as B where A.id=B.resid group by B.dbgComments ) as A left outer join (select distinct dbgComments,count() as q from StabilizerResults as A join (select distinct dbgComments,resid from DbgInfo) as B where A.id=B.resid and errinerrout>0 group by B.dbgComments ) as B on A.dbgComments=B.dbgComments ) left outer join (select distinct dbgComments,count(*) as q from StabilizerResults as A join (select distinct dbgComments,resid from DbgInfo) as B where A.id=B.resid and errinerrout<=0 group by B.dbgComments ) as C on A.dbgComments=C.dbgComments group by A.dbgComments order by A.q desc ; >
The easiest way to find the offending code in each package is to compile the package using the Herbie plugin.
Known Bugs
There are no known bugs when compiling programs that use the SubHask numeric prelude.
The standard Prelude is only partially supported.
In particular, the Herbie plugin is able to extract mathematical expressions correctly and will print the stabilized version to stdout.
But the plugin can only substitute the stabilized version on polymorphic expressions, and does not perform the substitution on nonpolymorphic ones.
The problem is that the solveWantedsTcM
function (called within the getDictionary
function inside of Herbie/CoreManip.hs) is unable to find the Num
dictionary for Float
and Double
types.
I have no idea why this is happening, and I'd be very happy to accept pull requests that fix the issue :)