One of the most important features of the Brain4it language is homoiconicity, which means that code and data are represented in the same way. Homoiconicity allows a program to manage code as easily as it manages data, so it can create or modify other programs or even change itself at runtime.
This module takes advantage of this feature to implement a transformation rule engine to solve mathematical equations algebraically.
The rules variable contains a list of transformation rules with this format:
(...
"<rule_name>" =>
(
"<rule_description>"
<matching_expression>
<apply_condition>
<replacing_expression>
)
...
)
Where:
Examples:
(...
"rule6" =>
(
"Redundant negative operator"
(- (- x?))
true
x?
)
...
"rule7" =>
(
"Join sum operators"
(+ a... (+ b...) c...)
true
(+ a... b... c...)
)
...
"rule10" =>
(
"Sum numbers"
(+ a... x? b... y? c...)
(if
(and
(= (type-of x?) "number")
(= (type-of y?) "number")
)
(do
(set match_map$/res (+ x? y?))
true
)
false
)
(+ res a... b... c...)
)
...
"rule16" =>
(
"Sum element twice"
(+ a... x? b... x? c...)
true
(+ a... b... c... (* 2 x?))
)
...
"rule28" =>
(
"Sort variables lexicografically"
(fn? a... x? y? b...)
(and
(or (= fn? +) (= fn? *))
(= (type-of x?) "reference")
(= (type-of y?) "reference")
(> (string x?) (string y?))
)
(fn? a... y? x? b...)
)
...
)
Usually, these transformation rules try to reduce or simplify the input expression.
The transformation engine is implemented by the apply_rules and apply_rule functions, that successively apply the rules of transformation on the input expression until it can no longer be transformed.
This module offers 4 functions to transform (reduce) a mathematical expression:
(reduce expr)
: where expr is evaluated before applying transformations. It returns the final reduced expression.(reducet expr)
: where expr is evaluated before applying transformations.
It returns a list of all the applied transformations.(reduceq expr)
: where expr is transformed without evaluation. It returns the final reduced expression.(reduceqt expr)
: where expr is transformed without evaluation. It returns a list of all the applied transformations.Examples:
(reduceq (* (+ 3 x) (* 2 x)))
(+ (* 2 (pow x 2)) (* 6 x))
(reduceqt (* (+ 3 x) (* 2 x)))
(
(* (+ 3 x) (* 2 x))
"Join product operators"
(* (+ 3 x) 2 x)
"Multiply sum terms (right)"
(* (+ (* 2 3) (* 2 (+ x))) x)
"Redundant sum operator"
(* (+ (* 2 3) (* 2 x)) x)
"Multiply numbers"
(* (+ (* 6) (* 2 x)) x)
"Redundant product operator"
(* (+ 6 (* 2 x)) x)
"Multiply sum terms (right)"
(* (+ (* x 6) (* x (+ (* 2 x)))))
"Redundant sum operator"
(* (+ (* x 6) (* x (* 2 x))))
"Redundant product operator"
(+ (* x 6) (* x (* 2 x)))
"Join product operators"
(+ (* x 6) (* x 2 x))
"Multiply element by itself"
(+ (* x 6) (* 2 (pow x 2)))
"Put number in front of expression in multiply"
(+ (* 6 x) (* 2 (pow x 2)))
"Sort terms by power (1 power)"
(+ (* 2 (pow x 2)) (* 6 x))
)
Solving an equation is a particular case of reduction. For example, if we want to solve this equation:
2 * x + b = 7Then we should type this command:
(reduceq (solve x (+ (* 2 x) b) 7))
(solved x (+ (* -0.5 b) 3.5))