timeseries-julia-python

random julia and python scripts analyzing stock timeseries data

git clone https://9o.is/git/timeseries-julia-python.git

quickcheck.jl

(3105B)


      1 # A Julia implementation of QuickCheck, a specification-based tester
      2 #
      3 # QuickCheck was originally written for Haskell by Koen Claessen and John Hughes
      4 # http://www.cse.chalmers.se/~rjmh/QuickCheck/
      5 
      6 module QuickCheck
      7 
      8 export property
      9 export condproperty
     10 export quantproperty
     11 
     12 function lambda_arg_types(f::Function)
     13     if !isa(f.code, LambdaStaticData)
     14         error("You must supply either an anonymous function with typed arguments or an array of argument types.")
     15     end
     16     [eval(var.args[2]) for var in Base.uncompressed_ast(f.code).args[1]]
     17 end
     18 
     19 # Simple properties
     20 function property(prop::Function, typs::Vector, ntests)
     21     arggens = [size -> generator(typ, size) for typ in typs]
     22     quantproperty(prop, typs, ntests, arggens...)
     23 end
     24 property(prop::Function, typs::Vector) = property(prop, typs, 100)
     25 property(prop::Function, ntests) = property(prop, lambda_arg_types(prop), ntests)
     26 property(prop::Function) = property(prop, 100)
     27 
     28 # Conditional properties
     29 function condproperty(prop::Function, typs::Vector, ntests, maxtests, argconds...)
     30     arggens = [size -> generator(typ, size) for typ in typs]
     31     check_property(prop, arggens, argconds, ntests, maxtests)
     32 end
     33 condproperty(prop::Function, args...) = condproperty(prop, lambda_arg_types(prop), args...)
     34 
     35 # Quantified properties (custom generators)
     36 function quantproperty(prop::Function, typs::Vector, ntests, arggens...)
     37     argconds = [(_...)->true for t in typs]
     38     check_property(prop, arggens, argconds, ntests, ntests)
     39 end
     40 quantproperty(prop::Function, args...) = quantproperty(prop, lambda_arg_types(prop), args...)
     41 
     42 function check_property(prop::Function, arggens, argconds, ntests, maxtests)
     43     totalTests = 0
     44     for i in 1:ntests
     45         goodargs = false
     46         args = {}
     47         while !goodargs
     48             totalTests += 1
     49             if totalTests > maxtests
     50                 println("Arguments exhausted after $i tests.")
     51                 return
     52             end
     53             args = [arggen(div(i,2)+3) for arggen in arggens]
     54             goodargs = all([cond(args...) for cond in argconds])
     55         end
     56         if !prop(args...)
     57             error("Falsifiable, after $i tests:\n$args")
     58         end
     59     end
     60     println("OK, passed $ntests tests.")
     61 end
     62 
     63 # Default generators for primitive types
     64 generator{T<:Unsigned}(::Type{T}, size) = convert(T, rand(1:size))
     65 generator{T<:Signed}(::Type{T}, size) = convert(T, rand(-size:size))
     66 generator{T<:FloatingPoint}(::Type{T}, size) = convert(T, (rand()-0.5).*size)
     67 # This won't generate interesting UTF-8, but doing that is a Hard Problem
     68 generator{T<:String}(::Type{T}, size) = convert(T, randstring(size))
     69 
     70 generator(::Type{Any}, size) = error("Property variables cannot by typed Any.")
     71 
     72 # Generator for array types
     73 function generator{T,n}(::Type{Array{T,n}}, size)
     74     dims = [rand(1:size) for i in 1:n]
     75     reshape([generator(T, size) for x in 1:prod(dims)], dims...)
     76 end
     77 
     78 # Generator for composite types
     79 function generator{C}(::Type{C}, size)
     80     if C.types == ()
     81         error("No generator defined for type $C.")
     82     end
     83     C([generator(T, size) for T in C.types]...)
     84 end
     85 
     86 end