From 7bac996836b35c945678039571d75f9ff2b46d77 Mon Sep 17 00:00:00 2001 From: Chris Rackauckas Date: Thu, 23 Jun 2022 15:01:19 -0400 Subject: [PATCH] format SciML Style --- .JuliaFormatter.toml | 1 + .github/workflows/FormatCheck.yml | 42 ++++++ docs/make.jl | 8 +- src/maps.jl | 243 ++++++++++++++---------------- src/parse.jl | 6 +- src/utils.jl | 4 +- test/parse.jl | 15 +- test/sys.jl | 2 +- test/utils.jl | 2 +- 9 files changed, 178 insertions(+), 145 deletions(-) create mode 100644 .JuliaFormatter.toml create mode 100644 .github/workflows/FormatCheck.yml diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..453925c --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1 @@ +style = "sciml" \ No newline at end of file diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml new file mode 100644 index 0000000..2a3517a --- /dev/null +++ b/.github/workflows/FormatCheck.yml @@ -0,0 +1,42 @@ +name: format-check + +on: + push: + branches: + - 'master' + - 'release-' + tags: '*' + pull_request: + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1] + julia-arch: [x86] + os: [ubuntu-latest] + steps: + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.julia-version }} + + - uses: actions/checkout@v1 + - name: Install JuliaFormatter and format + # This will use the latest version by default but you can set the version like so: + # + # julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.0"))' + run: | + julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))' + julia -e 'using JuliaFormatter; format(".", verbose=true)' + - name: Format check + run: | + julia -e ' + out = Cmd(`git diff --name-only`) |> read |> String + if out == "" + exit(0) + else + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) + end' diff --git a/docs/make.jl b/docs/make.jl index aae2ae9..e63d40d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,8 +1,6 @@ using Documenter, MathML -makedocs(sitename="My Documentation") +makedocs(sitename = "My Documentation") -deploydocs( - repo = "github.com/anandijain/MathML.jl.git", - devbranch = "main", -) \ No newline at end of file +deploydocs(repo = "github.com/anandijain/MathML.jl.git", + devbranch = "main") diff --git a/src/maps.jl b/src/maps.jl index 0c6c03a..2cf0d1b 100644 --- a/src/maps.jl +++ b/src/maps.jl @@ -1,130 +1,119 @@ # need to check the arities # units handling?? -applymap = Dict{String,Function}( - # eq sometimes needs to be ~ and sometimes needs to be =, not sure what the soln is - "eq" => x -> Symbolics.:~(x...), # arity 2, - "times" => Base.prod, # arity 2, but prod fine - # "prod" => Base.prod, - "divide" => x -> Base.:/(x...), - "power" => x -> Base.:^(x...), - "root" => custom_root, - "plus" => x -> Base.:+(x...), - "minus" => x -> Base.:-(x...), - - # comparison functions implemented using the Heaviside function - "lt" => x -> H(x[2] - x[1] - ϵ), - "leq" => x -> H(x[2] - x[1]), - "geq" => x -> H(x[1] - x[2]), - "gt" => x -> H(x[1] - x[2] - ϵ), - - # equal nodes are not part of the MathML specification and - # are generated by disambiguate_equality! - "equal" => x -> H(x[1] - x[2]) * H(x[2] - x[1]), - "neq" => x -> 1 - H(x[1] - x[2]) * H(x[2] - x[1]), - - # "lt" => x -> Base.foldl(Base.:<, x), - # "leq" => x -> Base.foldl(Base.:≤, x), - # "geq" => x -> Base.foldl(Base.:≥, x), - # "gt" => x -> Base.foldl(Base.:>, x), - - # "quotient" => x->Base.:div(x...), # broken, RoundingMode - "factorial" => x -> SpecialFunctions.gamma(1 .+ x[1]), - "max" => x -> Base.max(x...), - "min" => x -> Base.min(x...), - "rem" => x -> Base.:rem(x...), - "gcd" => x -> Base.:gcd(x...), - - "and" => x -> Base.:*(x...), - "or" => heaviside_or, - "xor" => x -> x[1]*(one(x[2])-x[2]) + (one(x[1])-x[1])*x[2], - "not" => x -> one(x[1]) - x[1], - - # "and" => x -> Base.:&(x...), - # "or" => Base.:|, - # "xor" => Base.:⊻, - # "not" => Base.:!, - - "abs" => x -> Base.abs(x...), - "conjugate" => Base.conj, - "arg" => Base.angle, - "real" => Base.real, - "imaginary" => Base.imag, - "lcm" => x -> Base.lcm(x...), - - "floor" => x -> x[1] - frac(x[1]), - "ceiling" => x -> x[1] - frac(x[1]) + one(x[1]), - "round" => x -> x[1] + 0.5 - frac(x[1] + 0.5), - - # "floor" => x -> Base.floor(x...), - # "ceiling" => x -> Base.ceil(x...), - # "round" => x -> Base.round(x...), - - "inverse" => Base.inv, - "compose" => x -> Base.:∘(x...), - "ident" => Base.identity, - "approx" => x -> Base.:≈(x...), - - "sin" => x -> Base.sin(x...), - "cos" => x -> Base.cos(x...), - "tan" => x -> Base.tan(x...), - "sec" => x -> Base.sec(x...), - "csc" => x -> Base.csc(x...), - "cot" => x -> Base.cot(x...), - "arcsin" => x -> Base.asin(x...), - "arccos" => x -> Base.acos(x...), - "arctan" => x -> Base.atan(x...), - "arcsec" => x -> Base.asec(x...), - "arccsc" => x -> Base.acsc(x...), - "arccot" => x -> Base.acot(x...), - "sinh" => x -> Base.sinh(x...), - "cosh" => x -> Base.cosh(x...), - "tanh" => x -> Base.tanh(x...), - "sech" => x -> Base.sech(x...), - "csch" => x -> Base.csch(x...), - "coth" => x -> Base.coth(x...), - "arcsinh" => x -> Base.asinh(x...), - "arccosh" => x -> Base.acosh(x...), - "arctanh" => x -> Base.atanh(x...), - "arcsech" => x -> Base.asech(x...), - "arccsch" => x -> Base.acsch(x...), - "arccoth" => x -> Base.acoth(x...), - - "exp" => x -> Base.exp(x...), - "log" => x -> Base.log10(x...), # todo handle - "ln" => x -> Base.log(x...), - - "mean" => Statistics.mean, - "sdev" => Statistics.std, - "variance" => Statistics.var, - "median" => Statistics.median, - # "mode" => Statistics.mode, # crazy mode isn't in Base - - "vector" => Base.identity, - "diff" => parse_diff, - "cn" => parse_diff, - # "apply" => x -> parse_apply(x) # this wont work because we pass the name which is string -) - -tagmap = Dict{String,Function}( - "cn" => parse_cn, - "ci" => parse_ci, - - "degree" => x -> parse_node(x.firstelement), # won't work for all cases - "bvar" => parse_bvar, # won't work for all cases - - "piecewise" => parse_piecewise, - - "apply" => parse_apply, - "math" => x -> map(parse_node, elements(x)), - "vector" => x -> map(parse_node, elements(x)), - "lambda" => parse_lambda, - - # MathML defined constants - "pi" => x -> π, - "exponentiale" => x -> ℯ, - "notanumber" => x -> NaN, - "infinity" => x -> Inf, - "true" => x -> true, - "false" => x -> false, -) +applymap = Dict{String, Function}( + # eq sometimes needs to be ~ and sometimes needs to be =, not sure what the soln is + "eq" => x -> Symbolics.:~(x...), # arity 2, + "times" => Base.prod, # arity 2, but prod fine + # "prod" => Base.prod, + "divide" => x -> Base.:/(x...), + "power" => x -> Base.:^(x...), + "root" => custom_root, + "plus" => x -> Base.:+(x...), + "minus" => x -> Base.:-(x...), + + # comparison functions implemented using the Heaviside function + "lt" => x -> H(x[2] - x[1] - ϵ), + "leq" => x -> H(x[2] - x[1]), + "geq" => x -> H(x[1] - x[2]), + "gt" => x -> H(x[1] - x[2] - ϵ), + + # equal nodes are not part of the MathML specification and + # are generated by disambiguate_equality! + "equal" => x -> H(x[1] - x[2]) * H(x[2] - x[1]), + "neq" => x -> 1 - H(x[1] - x[2]) * H(x[2] - x[1]), + + # "lt" => x -> Base.foldl(Base.:<, x), + # "leq" => x -> Base.foldl(Base.:≤, x), + # "geq" => x -> Base.foldl(Base.:≥, x), + # "gt" => x -> Base.foldl(Base.:>, x), + + # "quotient" => x->Base.:div(x...), # broken, RoundingMode + "factorial" => x -> SpecialFunctions.gamma(1 .+ x[1]), + "max" => x -> Base.max(x...), + "min" => x -> Base.min(x...), + "rem" => x -> Base.:rem(x...), + "gcd" => x -> Base.:gcd(x...), + "and" => x -> Base.:*(x...), + "or" => heaviside_or, + "xor" => x -> x[1] * (one(x[2]) - x[2]) + + (one(x[1]) - x[1]) * x[2], + "not" => x -> one(x[1]) - x[1], + + # "and" => x -> Base.:&(x...), + # "or" => Base.:|, + # "xor" => Base.:⊻, + # "not" => Base.:!, + + "abs" => x -> Base.abs(x...), + "conjugate" => Base.conj, + "arg" => Base.angle, + "real" => Base.real, + "imaginary" => Base.imag, + "lcm" => x -> Base.lcm(x...), + "floor" => x -> x[1] - frac(x[1]), + "ceiling" => x -> x[1] - frac(x[1]) + one(x[1]), + "round" => x -> x[1] + 0.5 - frac(x[1] + 0.5), + + # "floor" => x -> Base.floor(x...), + # "ceiling" => x -> Base.ceil(x...), + # "round" => x -> Base.round(x...), + + "inverse" => Base.inv, + "compose" => x -> Base.:∘(x...), + "ident" => Base.identity, + "approx" => x -> Base.:≈(x...), + "sin" => x -> Base.sin(x...), + "cos" => x -> Base.cos(x...), + "tan" => x -> Base.tan(x...), + "sec" => x -> Base.sec(x...), + "csc" => x -> Base.csc(x...), + "cot" => x -> Base.cot(x...), + "arcsin" => x -> Base.asin(x...), + "arccos" => x -> Base.acos(x...), + "arctan" => x -> Base.atan(x...), + "arcsec" => x -> Base.asec(x...), + "arccsc" => x -> Base.acsc(x...), + "arccot" => x -> Base.acot(x...), + "sinh" => x -> Base.sinh(x...), + "cosh" => x -> Base.cosh(x...), + "tanh" => x -> Base.tanh(x...), + "sech" => x -> Base.sech(x...), + "csch" => x -> Base.csch(x...), + "coth" => x -> Base.coth(x...), + "arcsinh" => x -> Base.asinh(x...), + "arccosh" => x -> Base.acosh(x...), + "arctanh" => x -> Base.atanh(x...), + "arcsech" => x -> Base.asech(x...), + "arccsch" => x -> Base.acsch(x...), + "arccoth" => x -> Base.acoth(x...), + "exp" => x -> Base.exp(x...), + "log" => x -> Base.log10(x...), # todo handle + "ln" => x -> Base.log(x...), "mean" => Statistics.mean, + "sdev" => Statistics.std, + "variance" => Statistics.var, + "median" => Statistics.median, + # "mode" => Statistics.mode, # crazy mode isn't in Base + + "vector" => Base.identity, + "diff" => parse_diff, + "cn" => parse_diff + # "apply" => x -> parse_apply(x) # this wont work because we pass the name which is string + ) + +tagmap = Dict{String, Function}("cn" => parse_cn, + "ci" => parse_ci, + "degree" => x -> parse_node(x.firstelement), # won't work for all cases + "bvar" => parse_bvar, # won't work for all cases + "piecewise" => parse_piecewise, "apply" => parse_apply, + "math" => x -> map(parse_node, elements(x)), + "vector" => x -> map(parse_node, elements(x)), + "lambda" => parse_lambda, + + # MathML defined constants + "pi" => x -> π, + "exponentiale" => x -> ℯ, + "notanumber" => x -> NaN, + "infinity" => x -> Inf, + "true" => x -> true, + "false" => x -> false) diff --git a/src/parse.jl b/src/parse.jl index 8a0b561..a2f4a93 100644 --- a/src/parse.jl +++ b/src/parse.jl @@ -96,7 +96,8 @@ function process_pieces(pieces, otherwise) node = pieces[1] c = parse_node.(elements(node)) return IfElse.ifelse(c[2] > 0.5, c[1], - length(pieces)==1 ? otherwise : process_pieces(pieces[2:end], otherwise)) + length(pieces) == 1 ? otherwise : + process_pieces(pieces[2:end], otherwise)) end """ @@ -107,7 +108,8 @@ parse an node into Symbolics form how to deal w apply within apply, need to ensure we've hit bottom """ function parse_apply(node) - node.name != "apply" && error("calling parse_apply requires the name of the element to be `apply`") + node.name != "apply" && + error("calling parse_apply requires the name of the element to be `apply`") elms = elements(node) cs = parse_node.(elms[2:end]) applymap[elms[1].name](cs) diff --git a/src/utils.jl b/src/utils.jl index 89e3d9c..9c8d105 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -91,4 +91,6 @@ end H(x) = IfElse.ifelse(x >= 0, one(x), zero(x)) const ϵ = eps(Float64) frac(x) = 0.5 - atan(cot(π * x)) / π -heaviside_or(x) = length(x) == 1 ? x[1] : x[1] + heaviside_or(x[2:end]) - x[1] * heaviside_or(x[2:end]) +function heaviside_or(x) + length(x) == 1 ? x[1] : x[1] + heaviside_or(x[2:end]) - x[1] * heaviside_or(x[2:end]) +end diff --git a/test/parse.jl b/test/parse.jl index 2603888..56e0eb3 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -30,7 +30,7 @@ str = """52""" @test isequal(MathML.parse_str(str), 500) str = """ 2 3.1415 """ -@test isapprox(MathML.parse_str(str), Complex(-2, 0), atol=1e-3) +@test isapprox(MathML.parse_str(str), Complex(-2, 0), atol = 1e-3) str = """ 12.3 5 """ @test isequal(MathML.parse_str(str), Complex(12.3, 5)) @@ -97,15 +97,14 @@ str = """ """ -@test isequal(MathML.parse_str(str), - IfElse.ifelse( - IfElse.ifelse(1. - t >= 0, 1, 0) > 0.5, - x * (y + a * z) * ((1.0 - (b * z))^-1), - x * y)) +@test isequal(MathML.parse_str(str), + IfElse.ifelse(IfElse.ifelse(1.0 - t >= 0, 1, 0) > 0.5, + x * (y + a * z) * ((1.0 - (b * z))^-1), + x * y)) # factorial str = "x" -@test isequal(MathML.parse_str(str), SpecialFunctions.gamma(1+x)) +@test isequal(MathML.parse_str(str), SpecialFunctions.gamma(1 + x)) str = "5" @test MathML.parse_str(str) == 120 @@ -261,7 +260,7 @@ str = """ f = parse_str(str) xml = parsexml(str).root g = parse_lambda(xml) -@test g(3,5) == f(3,5) == [243] +@test g(3, 5) == f(3, 5) == [243] @test isequal(f(x, y), [x^y]) # parse_apply with as firstelement problem diff --git a/test/sys.jl b/test/sys.jl index 3d82ff9..c08e353 100644 --- a/test/sys.jl +++ b/test/sys.jl @@ -3,4 +3,4 @@ fn = "test/data/lorenz.xml" xml = readxml(fn).root eqs = parse_node(xml) ODESystem(eqs) -@test !isnothing() # TODO \ No newline at end of file +@test !isnothing() # TODO diff --git a/test/utils.jl b/test/utils.jl index 7c12268..aa8e2e4 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -2,4 +2,4 @@ fn = "data/vinnakota_kemp_kushmeric_2006_exp45.cellml" doc = readxml(fn) docroot = doc.root maths = extract_mathml(fn) -@test length(maths) == 24 \ No newline at end of file +@test length(maths) == 24