# Solver

## Introduction

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.

## How it works?

The rules variable contains a list of transformation rules with this format:

`(...  "<rule_name>" =>  (    "<rule_description>"    <matching_expression>    <apply_condition>    <replacing_expression>  )  ...)`

Where:

• rule_name: is the name of the rule, usually the word "rule" followed by an index.
• rule_description: is a text that describes the purpose of the rule.
• matching_expression: is the matching expression to look up in the input expression. This expression may contain substitution variables (x? or x...) like those supported by the match function.
• apply_condition: is a boolean expression on the subtitution variables that must evaluate to true to do the replacement or false to continue searching for a match. This expression may also set new variables that could be referenced in the replacing expression.
• replacing_expression: is the expression that will replace the match found after dereferecing its substitution variables.

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 = 7

Then we should type this command:

`(reduceq (solve x (+ (* 2 x) b) 7))`
`(solved x (+ (* -0.5 b) 3.5))`
Top