Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Developer note #21

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ makedocs(
prettyurls = get(ENV, "CI", nothing) == "true",
),
sitename = "ExpressionTreeForge.jl",
pages = Any["Home" => "index.md", "Tutorial" => "tutorial.md", "Reference" => "reference.md"],
pages = Any["Home" => "index.md", "Tutorial" => "tutorial.md", "Reference" => "reference.md", "Developer note" => "developer_note.md"],
)

deploydocs(repo = "github.com/paraynaud/ExpressionTreeForge.jl.git", devbranch = "master")
54 changes: 51 additions & 3 deletions docs/src/developer_note.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,54 @@
# Developer note

## Code flexibility
The code architecture is developed such that every structure can be replaced by a new one as long as the new `struct` keep satisfying the mandatory methods of the interface (see the files `itf_<behavior>.jl`).
The code dynamically checks that the parameters of the interface methods are the expected structure satisfying the behavior.
This mechanism is called [Holy traits](https://ahsmart.com/pub/holy-traits-design-patterns-and-best-practice-book/#implementing_the_holy_traits_pattern), implemented in the several `tr_<behavior>.jl` files.
These files indicate the supported `struct`ures and gather the methods that can be applied indistinctly on it (mainly those of the interface).
In consequence, if all the methods required by an algorithm are from the trait, the algorithm will work for every supported `struct`ures.
That way, we don't rely on `abstract type` hierarchy, and we can apply algorithms to types that can't be a subtype of our `abstract type`s (ex: `Expr`).
This interface-trait philosophy is applied on the:
- operator/variable/constant nodes;
- implementations of tree;
- implementations of expression tree.

## How to add a new operator
Should be defined in `src/node_expr_tree/YourOperator.jl` alongside the other possible nodes.
Should overload every method of `src/node_expr_tree/itf_expr_node.jl`.
### Issue of interface/trait approach
The issue is that you have to implement for every supported `struct`ures all the interface methods, which grows up with time.
To keep the code consistent there are some internal structures that are certified for all the interface-trait methods (ex: `Type_expr_tree`, `Complete_expr_tree`).
In the worst case, you can interface your structure with `Type_expr_tree` and apply the methods directly on the results of the interfacing.

## Code organization
The source code is divided in four sub-repository:
- `src/type_expr/` gather types about the nodes of an expression tree.
It implements:
- internal types: `constant, linear, quadratic, cubic` or `more` non-linear;
- the convexity status: `constant, linear`, strictly `convex`, strictly `concave` or `unknown`.
- `src/tree/` is about classical tree behavior:
- implement `Type_node<:AbstractTree`, a node structure which can be used to build a tree;
- the expected methods that every tree should satisfy (interface `src/tree/itf_tree.jl` and `src/tree/tr_tree.`);
- an implementation of the interface for `Expr` (which can't be a subtype of `AbstractTree`);
- an algorithm printing every structure satisfying the tree interface.
- `src/node_expr_tree/` implement the supported operator nodes which are part of an expression tree:
- implement `plus, minus, power, times, frac, constant, variable, sin, cos, tan` node operators;
- the expected methods that every node should satisfy (interface `src/node_expr_tree/itf_expr_node.jl` and `src/node_expr_tree/tr_expr_node.jl`);
- methods to evaluate a node, its bounds or its convexity status.
- `src/expr_tree/` implements the supported expression tree and the methods that can be applied on it:
- the expected methods that every expression tree should satisfy (interface `src/expr_tree/itf_expr_tree.jl` and `src/expr_tree/tr_expr_tree.jl`);
- some implementation of expression trees;
- bounds propagation and convexity detection;
- algorithms applied onto expression trees: partial separability detection, evaluation of the derivatives (see the [tutorial](https://paraynaud.github.io/ExpressionTreeForge.jl/dev/tutorial/))

### How to add a new tree implementation
You must define your tree `src/tree/YourTree.jl` alongside the other possible tree interfaces.
You also have to overload most of the method of `src/tree/itf_tree.jl` and `src/tree/abs_tree.jl`.

### How to add a new operator node
You must define your operator `src/node_expr_tree/YourOperator.jl` alongside the other operator node interfaces.
You also have to overload most of the method of `src/node_expr_tree/itf_expr_node.jl`.

### How to add a new expression tree implementation
You must define your tree `src/expr_tree/YourExpressionTree.jl` alongside the other possible tree interfaces.
You also have to overload most of the method of `src/expr_tree/itf_expr_tree.jl` and `src/expr_tree/abs_expr_tree.jl`.

## Limits
For now, the internal expression trees structures `Type_expr_tree` and `Complete_expr_tree` are trees and not directed acyclic graphs.