formulae v0.1.2 Formulae

A set of functions to deal with analytical formulae.

Summary

Functions

Guesses the binding this formula requires. FIXME: probably, more sophisticated way would be to analyze Macro.traverse

Revalidates the formula with bindings given

Curries the formula by substituting the known bindings into it

Evaluates normalized representation of formula

Returns a normalized ({:<, "sumOaSTS3E14CSMSb", 0}) representation for the formula given

Makes a valid (rigid) identifier out of AST

Checks if the given string represents the rigid identifier

Produces the normalized representation of formula. If the rho is an instance of Integer or Float, it’s left intact, otherwise it’s moved to the left side with negation

Makes a string representation of a formula out of it’s rigid implementation

Functions

bindings?(string, bindings \\ [])

Guesses the binding this formula requires. FIXME: probably, more sophisticated way would be to analyze Macro.traverse

Examples

iex> "a > 5" |> Formulae.bindings?
~w|a|a

iex> ":math.sin(a / (3.14 * b)) > c" |> Formulae.bindings?
~w|a b c|a
check(string, bindings \\ [])

Revalidates the formula with bindings given.

Examples

iex> "a > 5" |> Formulae.check([a: 6])
true

iex> "a > 5" |> Formulae.check([a: 3])
false

iex> "a > 5" |> Formulae.check
false
curry(input, bindings \\ [], opts \\ __ENV__)

Curries the formula by substituting the known bindings into it.

Example

iex> "(temp - time * 4) > speed / 3.14" |> Formulae.curry(temp: 7, speed: 3.14) |> Macro.to_string
"{7 - time * 4 - 1.0 > 0, {}}"
evaluate(input, binding \\ [], opts \\ [])

Evaluates normalized representation of formula.

Examples

iex> Formulae.evaluate(Formulae.unit("3 > 2"))
true

iex> Formulae.evaluate(Formulae.unit("3 < 2"))
false

iex> Formulae.evaluate(Formulae.unit("a < 2"), [a: 1])
true

iex> Formulae.evaluate(Formulae.unit("a > 2"), [a: 1])
false

# This test issues a warning about “variable "a" does not exist and is being expanded to "a()"”
iex> Formulae.evaluate(Formulae.unit("a < 2"), [])
** (Formulae.RunnerError) Formula failed to run (compile): undefined function a/0.

iex> Formulae.evaluate(Formulae.unit("a + 2 = 3"), [a: 1])
true

iex> Formulae.evaluate(Formulae.unit("a + 2 = 3"), [a: 2])
false

iex> Formulae.evaluate(Formulae.unit(~S|a = "3"|), [a: "3"])
true

iex> Formulae.evaluate(Formulae.unit(~S|a = "3"|), [a: 3])
false

iex> Formulae.evaluate(Formulae.unit(~S|a = "3"|), [a: "hello"])
false

iex> Formulae.evaluate("a + 2 = 3", [a: 2])
false

iex> Formulae.evaluate(~S|a = "3"|, [a: "3"])
true

iex> Formulae.evaluate(Formulae.unit("a_b_c_490000 > 2"), [a_b_c_490000: 3])
true
normalize(string)

Returns a normalized ({:<, "sumOaSTS3E14CSMSb", 0}) representation for the formula given.

Example

iex> "(temp - time * 4) > speed / 3.14" |> Formulae.normalize
{:>, {"tempSMStimeSTS4SMSspeedSDS3E14", "temp - time * 4 - speed / 3.14"}, 0}

iex> "hello < 3.14" |> Formulae.normalize
{:<, {"hello", "hello"}, 3.14}

iex> "HELLO < 3.14" |> Formulae.normalize
{:<, {"hello", "HELLO"}, 3.14}
rigid(ast)
rigid!(ast)

Makes a valid (rigid) identifier out of AST.

Examples

iex> “sum(a * 3.14) - b” |> Formulae.rigid! “sumOaSTS3E14CSMSb”

iex> “sum(a 3.14) - b ± 3” |> Formulae.rigid! ** (Formulae.SyntaxError) Formula [sum(a 3.14) - b ± 3] syntax is incorrect (symbols): NYI.

rigid?(string, strict \\ true)

Checks if the given string represents the rigid identifier.

Examples

iex> Formulae.rigid?("hello")
true

iex> Formulae.rigid?("HELLO")
false

iex> Formulae.rigid?("hello world!")
false

iex> Formulae.rigid?("sum0")
true

iex> Formulae.rigid?("sum(3.14 * 42)")
false
unit(input, env \\ [])

Produces the normalized representation of formula. If the rho is an instance of Integer or Float, it’s left intact, otherwise it’s moved to the left side with negation.

@todo Try to eval rho before guards; premature optimization

Examples

iex> Formulae.unit("3 > 2")
{:>, [], [3, 2]}

iex> Formulae.unit("3 - a > 2")
{:>, [], [{:-, [line: 1], [3, {:a, [line: 1], nil}]}, 2]}

iex> Formulae.unit("3 > A + 2")
{:>, [],
 [{:-, [context: Formulae, import: Kernel],
   [3, {:+, [line: 1], [{:__aliases__, [counter: 0, line: 1], [:A]}, 2]}]}, 0]}

iex> Formulae.unit("3 >= a + 2")
** (Formulae.SyntaxError) Formula [3 >= a + 2] syntax is incorrect (operation): “>=”.

iex> Formulae.unit("3 a > A + 2")
** (Formulae.SyntaxError) Formula [3 a > A + 2] syntax is incorrect (parsing): syntax error before: “a”.

iex> Formulae.unit("a + 2 = 3")
{:==, [], [{:+, [line: 1], [{:a, [line: 1], nil}, 2]}, 3]}

iex> Formulae.unit(~S|A = "3"|)
{:==, [], [{:__aliases__, [counter: 0, line: 1], [:A]}, "3"]}
unrigid!(var)

Makes a string representation of a formula out of it’s rigid implementation.

Examples

iex> “sumOaSTS3E14CSMSb” |> Formulae.unrigid! “sum(a 3.14) - b” iex> “sum(a 3.14) - b ± 3” |> Formulae.unrigid! * (Formulae.SyntaxError) Formula [sum(a 3.14) - b ± 3] syntax is incorrect (not_rigid): NYI.