packages feed

Probnet (empty) → 0.1.0.0

raw patch · 6 files changed

+283/−0 lines, 6 filesdep +basesetup-changed

Dependencies added: base

Files

+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for Probnet++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) 2021 Cobalt Technologies S.A++For commercial usage:++For commercial license usage send a email asking for permission and license terms to pedro@cobalt.tech++For investigation:++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Probnet.cabal view
@@ -0,0 +1,25 @@+-- Initial Probnet.cabal generated by cabal init.  For further+-- documentation, see http://haskell.org/cabal/users-guide/++name:                Probnet+version:             0.1.0.0+synopsis:            geometric extrapolation with error prediction for data sequences prediction+-- description:+homepage:            https://github.com/pedroelbanquero/geometric-extrapolation+license:             MIT+license-file:        LICENSE+author:              Vicent Nos+maintainer:          vnos@cobalt.tech,vnos@blackhole.consulting+copyright:           Cobalt Technologies S.A+category:            Math+build-type:          Simple+extra-source-files:  ChangeLog.md, README.md+cabal-version:       >=1.10++library+  exposed-modules:     Probnet+  -- other-modules:+  -- other-extensions:+  build-depends:       base >=4.11  && <=4.15+  hs-source-dirs:      ./+  default-language:    Haskell2010
+ Probnet.hs view
@@ -0,0 +1,76 @@+-- | Probnet 0.1.0.0+-- | Usage : probnet 1 [1,2,3,5,8,13]+-- | Result : [1,2,3,5,8,13,21]++module Probnet (+   percents,+   predict1, +   predict, +   probnet, +) where++import Data.List+import Data.Ratio -- for the case of inputs with Ratio or Rational list elements++-- | Element value of 'list' nearest to 'n'+nearnum :: RealFrac a => a -> [a] -> a+nearnum n = minimumBy nearer+   where+   nearer x y = compare (abs (x - n)) (abs (y - n))++-- | Ratios between consecutive elements (logarithmic differences). +percents :: RealFrac a => [a] -> [a]+percents dat = zipWith quotient dat (tail dat)+   +   where +   quotient y = (/ y)++-- | Get ratio element+ratio1 d f = percents d !! f++-- | This is to assume that the next ratio is close to that of the element +-- with the closest value to the last element; in case of monotonic data +-- (always increasing or always decreasing) it is the last ratio. +++predict1 :: RealFrac a => [a] -> a+predict1 dat  +   | l > lastper = (ratio1 (dat) (eleml+1)) * last dat +   | otherwise = (ratio1 dat eleml) * last dat+   where+   Just eleml = elemIndex ned dat+   ned = nearnum (last dat) (init dat)+   l = last $ init dat+   lastper = last dat +++-- | Generates new prediction+predict :: (Integral b, RealFrac a) => Int -> [a] -> [b]+predict layers dat +   | layers > 1   = predict (layers - 1) out -- execute next in the serie+   | otherwise    = fmap round out+   where+   out = [predict1 dat] ++-- | Generate new prediction with error prediction +probnet :: (Integral b, RealFrac a) => Int -> [a] -> [b]+probnet layers dat+   | layers > 1   = probnet (layers - 1) $ map (\x-> fromIntegral (round x)) out +   | otherwise    = fmap round out+   where+   out = dat ++ [(predict1 dat + prerr dat)]++-- | This is the next prediction for the difference between each +-- original element and its prediction based on previous elements+prerr :: RealFrac a => [a] -> a+prerr dat +   | last err == 0   = 0 +   | otherwise       = predict1 $ drop 2 err+   where  +   err   = zipWith subtract pred dat -- differences between elements and its predictions+   pred  = fmap predict1 $ inits dat -- 2 first inits have 0 and 1 elements, will be dropped++-- | Property of Cobalt Technologies Panamá+-- | Authors : Vicent Nos Ripolles (Main Author)+-- | Enrique Santos (Refactor Code)+
+ README.md view
@@ -0,0 +1,149 @@+# Probnet ++## Usage ++````haskell++ghci Probnet.hs++````++````haskell++> probnet 1 [1,2,3,5,8]++[1,2,3,5,8,13]++````++## Geometric Extrapolation of Integer Sequences with error prediction+++## The problem+++In many situations, we have finite sequences of integer values, and we would like to predict which would be the next one, or the next several ones, without the knowledge of the mathematical definition of the sequence. ++A solution based just on the available data has applications on the following areas, among others:++- time series forecasting+- uncertain prediction+- data modeling+- risk modeling+++## A geometric way of prediction +++### Simple base solution++We start with a simple geometric solution, that is to calculate the ratio (quotient) of the last value relative to the previous one, and apply it to the last value to calculate the next one. ++For example, if we have some values of the Fibonacci sequence: ++    fibo = [1,2,3,5,8,13]++we get the ratios of each element relative to its previous one: ++    percents fibo+    [2.0,1.5,1.6666666666666667,1.6,1.625]++Then, we predict the next element as the product of the last element by the last ratio: ++    13 * 1.625 = 21.125+++### Improving the result with the prediction of the error++We can get the predicted value for each subsequence of initial values of the original sequence. ++    drop 2 (inits fibo)+    [[1,2],[1,2,3],[1,2,3,5],[1,2,3,5,8],[1,2,3,5,8,13]]++    fmap predict1 it+    [4.0,4.5,8.333333333333334,12.8,21.125]++Then, we can calculate the difference between the predicted value and the real value. This way, we get a sequence of the errors, and we can calculate the predicted value of the next error, wich we will add to the simple prediction, notably improving the result. ++    err = zipWith subtract it (drop 2 fibo)+    [-1.0,0.5,-0.3333333333333339,0.1999999999999993]++    predict1 it+    -0.1333333333333331++    21.125 - 0.1333333333333331 = 20.991666666666667++We round the result to get the integer predicted value. +++### Sequences with quasi-cyclic pattern++When a sequence is not monothonic, we assume that it has a repetitive pattern, so that the ratio used for prediction will be the one of the element whose value is closest to the last element. ++For example, in the next sequence, the value closest to the last one is the first `3`, and the ratio of that position is `4/3`, so the predicted value will be `3*(4/3)`:++    percents [1,2,3,4,5,1,2,3,4,1,2,3]+    [2.0,1.5,1.3333333333333333,1.25,0.2,2.0,1.5,1.3333333333333333,0.25,2.0,1.5]++    predict1 [1,2,3,4,5,1,2,3,4,1,2,3]+    4.0+++### Recursive layers of predictions++Once we have predicted the next value of a sequence, we can append it to the original sequence and predict another element. We can do this as many times as we want. We call "layers" to the number of recursions. Then, if we apply 3 layers to our fibonacci secuence `fib = [1,2,3,5,8,13]`, we get 3 more values: ++    probnet 3 fibo+    [1,2,3,5,8,13,21,34,55]+++## Problems and limitations++The geometric way, that is, a way based on ratios of values, can only be valid for non-zero values, and is not suitable for sequences with negative and positive values. In that case it should be more appropiate the use of a usual diferential method, which can be very simmilar to the one presented here, but using diferences of elements instead of quotients of elements. ++The case of zero values is not solved here. The function will just return an error if any element is 0. +++## Tecnical details++### Data types++The type signature of the function is such that any `RealFrac` data type can be used for the values of the elements in the input sequence. The internal calculations will be done in that data type, preserving the precicion of it. ++For example, if the type is a 32 bit `Float`, the calculus would be made with about 21 decimal digits of precision, but if the input elements are `Rational`, the intermediate calculus would preserve infinite precision, until the rounding for the Ìnteger` output. That is the reason for importing `Data.Ratio`. ++    fibo = [1,2,3,5,8,13 :: Float]+    predic1 fibo+    21.125++    fibo = [1,2,3,5,8,13 :: Rational]+    predict1 fibo+    169 % 8++It also implies that the input sequence can not be of any `Integral` type, it must be previously converted to a `RealFrac` type by using, for example, `fromInteger` conversion function. It is done this way on the testing file `test-probnet.hs`. ++### Arithmetic equivalent method++It can be noticed that an arithmetic, instead of geometric, method for the extrapolation can be coded by just changing the `quotient` `sub-function in the `percents` function by the standard `subtract`, and the product (*) in the `predict1` function by addition (+).++Such method would not require that every element in the sequence be different than 0, and the method would be suitable for sequences with negative and positive values. +++## Testing++The file `test-probnet.hs` contains a function `testoeis` to bulk testing the function `probnet` against a range of OEIS sequences, giving the numbers after the 'A' on the OEIS sequence ID. ++    testoeis 1 20+    [("A3",[1,1,1,1,2,2,1,2,2,2,3,2,2,4,2,2,4,2,3,4,4,2,3,4,2,6,3,2,6,4,3,4,4,4,6,4,2,6,4,4,8,4,3,6,4,4,5,4,4,6,6,4,6,6,4,8,4,2,9,4,6,8,4,4,8,8,3,8,8,4,7,4,4,10,6,6,8,4,5,8,6,4,9,8,4,10,6,4,12,8,6,6,4,8,8,8,4,8,6,4]),("A12",[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])]++The testing is made using just the first 10 values for predicting the 11 one, and comparing it with the real 11th element, counting it as valid when both, predicted and real, are equal. ++++Author - Vicent Nos Ripolles++Dev Pedro S++Dev Enrique S++All rights are reserved for commercial purposes of any derivatives of this document and source code. 
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain