diff --git a/dev/HerbConstraints/index.html b/dev/HerbConstraints/index.html index 1961cf5..76d1400 100644 --- a/dev/HerbConstraints/index.html +++ b/dev/HerbConstraints/index.html @@ -1,5 +1,5 @@ -HerbConstraints.jl · Herb.jl

HerbConstraints.jl Documentation

HerbConstraints.AbstractMatchNodeType
abstract type AbstractMatchNode

Tree structure to which rulenode trees can be matched. Consists of MatchNodes, which can match a specific RuleNode, and MatchVars, which is a variable that can be filled in with any RuleNode.

source
HerbConstraints.ComesAfterType
ComesAfter <: PropagatorConstraint

A ComesAfter constraint is a PropagatorConstraint containing the following:

  • rule::Int: A reference to a rule in the grammar
  • predecessors: A list of rules in the grammar

This Constraint enforces that the rule can only be applied if every rule in predecessors is used in the path from the root of the tree to the current hole in the order that they are given. Even though the rules must be in order, there might be other rules inbetween.

For example, consider the tree 1(a, 2(b, 3(c, d)))):

  • ComesAfter(4, [2, 3]) would enforce that rule 4 can only be used if 2 and 3 are used in the path from the root in that order. Therefore, only hole c and d can be filled with 4.
  • ComesAfter(4, [1, 3]) also allows c and d to be filled, since 1 and 3 are still used in the correct order. It does not matter that 2 is also used in the path to the root.
  • ComesAfter(4, [3, 2]) does not allow any hole to be filled with 4, since either the predecessors are either not in the path or in the wrong order for each of the holes.
source
HerbConstraints.ForbiddenType
Forbidden <: PropagatorConstraint

This [PropagatorConstraint] forbids any subtree that matches the pattern given by tree to be generated. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the Grammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical. Any rule in the domain that makes the match attempt successful is removed.

For example, consider the tree 1(a, 2(b, 3(c, 4)))):

  • Forbidden(MatchNode(3, [MatchNode(5), MatchNode(4)])) forbids c to be filled with 5.
  • Forbidden(MatchNode(3, [MatchVar(:v), MatchNode(4)])) forbids c to be filled, since a [MatchVar] can match any rule, thus making the match attempt successful for the entire domain of c. Therefore, this tree invalid.
  • Forbidden(MatchNode(3, [MatchVar(:v), MatchVar(:v)])) forbids c to be filled with 4, since that would make both assignments to v equal, which causes a successful match.
Warning

The Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.ForbiddenPathType
ForbiddenPath <: PropagatorConstraint

A [PropagatorConstraint] that forbids a certain derivation sequence. sequence defines the forbidden sequence. Each rule that would complete the sequence when expanding a Hole in an AbstractRuleNode tree is removed from the domain. The derivation sequence is the path from the root to the hole.

For example, consider the tree 1(a, 2(b, 3(c, d)))):

  • ForbiddenPath([1, 2, 4]) enforces that rule 4 cannot be applied at b, since it completes the sequence. However, it can be applied at a, c and d.
  • ForbiddenPath([3, 1]) enforces that rule 1 cannot be applied at c or d.
source
HerbConstraints.GrammarContextType
mutable struct GrammarContext

Structure used to track the context. Contains: - the expression being modified - the path to the hole that is being expanded, represented as a sequence of child indices. e.g., [2, 1] would point to the first child of the second child of the root. - a vector with local constraints that should be propagated upon expansion.

source
HerbConstraints.LocalConstraintType
abstract type LocalConstraint <: Constraint

Abstract type representing all local constraints. Local constraints correspond to a specific (partial) AbstractRuleNode tree. Each local constraint contains a path to a specific location in the tree. Each local constraint has an implementation of a propagate-function that takes

The propagate-function returns a tuple containing

Warning

By default, LocalConstraints are only propagated once. Constraints that have to be propagated more frequently should return themselves in the list of new local constraints.

source
HerbConstraints.LocalForbiddenType
LocalForbidden

Forbids the a subtree that matches the MatchNode tree to be generated at the location provided by the path. Use a Forbidden constraint for enforcing this throughout the entire search space.

source
HerbConstraints.LocalOrderedType

Enforces an order over two or more subtrees that fill the variables specified in order when the pattern is applied at the location given by path. Use an Ordered constraint for enforcing this throughout the entire search space.

source
HerbConstraints.MatchFailType
@enum MatchFail hardfail softfail

This enum is used for distinguishing between two types of failures when trying to match a RuleNode either with another RuleNode or with an AbstractMatchNode

  • Hardfail means that there is no match, and there is no way to fill in the holes to get a match.
  • Softfail means that there is no match, but there might be a way to fill the holes that results in a match.
source
HerbConstraints.MatchNodeType
struct MatchNode <: AbstractMatchNode

Match a specific rulenode, where the grammar rule index is rule_ind and children matches the children of the RuleNode. Example usage:

MatchNode(3, [MatchNode(1), MatchNode(2)])

This matches RuleNode(3, [RuleNode(1), RuleNode(2)])

source
HerbConstraints.MatchVarType
struct MatchVar <: AbstractMatchNode

Matches anything and assigns it to a variable. The ForbiddenTree constraint will not match if identical variable symbols match to different trees. Example usage:

MatchNode(3, [MatchVar(:x), MatchVar(:x)])

This matches RuleNode(3, [RuleNode(1), RuleNode(1)]), RuleNode(3, [RuleNode(2), RuleNode(2)]), etc.

source
HerbConstraints.OrderedType
Ordered <: PropagatorConstraint

A PropagatorConstraint that enforces a specific order in MatchVar assignments in the pattern defined by tree. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the Grammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical.

The order defines an order between the variable assignments. For example, if the order is [x, y], the constraint will require the assignment to x to be less than or equal to the assignment to y. The order is recursively defined by RuleNode indices. For more information, see Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode).

For example, consider the tree 1(a, 2(b, 3(c, 4)))):

  • Ordered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:v, :w]) removes every rule with an index of 5 or greater from the domain of c, since that would make the index of the assignment to v greater than the index of the assignment to w, violating the order.
  • Ordered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:w, :v]) removes every rule with an index of 4 or less from the domain of c, since that would make the index of the assignment to v less than the index of the assignment to w, violating the order.
Warning

The Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.PropagatorConstraintType
PropagatorConstraint <: Constraint

Abstract type representing all propagator constraints. Each propagator constraint has an implementation of a propagate-function that takes

The propagate-function returns a tuple containing

source
HerbConstraints.RequireOnLeftType

Rules have to be used in the specified order. That is, rule at index K can only be used if rules at indices [1...K-1] are used in the left subtree of the current expression

source
HerbConstraints.@csgrammar_annotatedMacro

@csgrammar_annotated Define an annotated grammar and return it as a ContextSensitiveGrammar. Allows for adding optional annotations per rule. As well as that, allows for adding optional labels per rule, which can be referenced in annotations. Syntax is backwards-compatible with @csgrammar. Examples:

g₁ = @csgrammar_annotated begin
+HerbConstraints.jl · Herb.jl

HerbConstraints.jl Documentation

HerbConstraints.AbstractMatchNodeType
abstract type AbstractMatchNode

Tree structure to which rulenode trees can be matched. Consists of MatchNodes, which can match a specific RuleNode, and MatchVars, which is a variable that can be filled in with any RuleNode.

source
HerbConstraints.ComesAfterType
ComesAfter <: PropagatorConstraint

A ComesAfter constraint is a PropagatorConstraint containing the following:

  • rule::Int: A reference to a rule in the grammar
  • predecessors: A list of rules in the grammar

This Constraint enforces that the rule can only be applied if every rule in predecessors is used in the path from the root of the tree to the current hole in the order that they are given. Even though the rules must be in order, there might be other rules inbetween.

For example, consider the tree 1(a, 2(b, 3(c, d)))):

  • ComesAfter(4, [2, 3]) would enforce that rule 4 can only be used if 2 and 3 are used in the path from the root in that order. Therefore, only hole c and d can be filled with 4.
  • ComesAfter(4, [1, 3]) also allows c and d to be filled, since 1 and 3 are still used in the correct order. It does not matter that 2 is also used in the path to the root.
  • ComesAfter(4, [3, 2]) does not allow any hole to be filled with 4, since either the predecessors are either not in the path or in the wrong order for each of the holes.
source
HerbConstraints.ConditionType
Condition <: PropagatorConstraint

This PropagatorConstraint forbids any subtree that matches the pattern defined by tree and where the RuleNode that is matched to the variable in the pattern violates the predicate given by the condition function.

The condition function takes a RuleNode tree and should return a Bool.

Warning

The Condition constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Condition can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.ForbiddenType
Forbidden <: PropagatorConstraint

This [PropagatorConstraint] forbids any subtree that matches the pattern given by tree to be generated. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the AbstractGrammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical. Any rule in the domain that makes the match attempt successful is removed.

For example, consider the tree 1(a, 2(b, 3(c, 4)))):

  • Forbidden(MatchNode(3, [MatchNode(5), MatchNode(4)])) forbids c to be filled with 5.
  • Forbidden(MatchNode(3, [MatchVar(:v), MatchNode(4)])) forbids c to be filled, since a [MatchVar] can match any rule, thus making the match attempt successful for the entire domain of c. Therefore, this tree invalid.
  • Forbidden(MatchNode(3, [MatchVar(:v), MatchVar(:v)])) forbids c to be filled with 4, since that would make both assignments to v equal, which causes a successful match.
Warning

The Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.ForbiddenPathType
ForbiddenPath <: PropagatorConstraint

A [PropagatorConstraint] that forbids a certain derivation sequence. sequence defines the forbidden sequence. Each rule that would complete the sequence when expanding a Hole in an AbstractRuleNode tree is removed from the domain. The derivation sequence is the path from the root to the hole.

For example, consider the tree 1(a, 2(b, 3(c, d)))):

  • ForbiddenPath([1, 2, 4]) enforces that rule 4 cannot be applied at b, since it completes the sequence. However, it can be applied at a, c and d.
  • ForbiddenPath([3, 1]) enforces that rule 1 cannot be applied at c or d.
source
HerbConstraints.GrammarContextType
mutable struct GrammarContext

Structure used to track the context. Contains: - the expression being modified - the path to the hole that is being expanded, represented as a sequence of child indices. e.g., [2, 1] would point to the first child of the second child of the root. - a vector with local constraints that should be propagated upon expansion.

source
HerbConstraints.LocalConditionType
LocalCondition <: LocalConstraint

Forbids any subtree that matches the pattern defined by tree and where the RuleNode that is matched to the variable in the pattern violates the predicate given by the condition function.

The condition function takes a RuleNode tree and should return a Bool.

This constraint is only enforced at the location defined by path. Use a Condition constraint for enforcing this throughout the entire search space.

source
HerbConstraints.LocalConstraintType
abstract type LocalConstraint <: Constraint

Abstract type representing all local constraints. Local constraints correspond to a specific (partial) AbstractRuleNode tree. Each local constraint contains a path to a specific location in the tree. Each local constraint has an implementation of a propagate-function that takes

The propagate-function returns a tuple containing

Warning

By default, LocalConstraints are only propagated once. Constraints that have to be propagated more frequently should return themselves in the list of new local constraints.

source
HerbConstraints.LocalForbiddenType
LocalForbidden

Forbids the a subtree that matches the MatchNode tree to be generated at the location provided by the path. Use a Forbidden constraint for enforcing this throughout the entire search space.

source
HerbConstraints.LocalOrderedType

Enforces an order over two or more subtrees that fill the variables specified in order when the pattern is applied at the location given by path. Use an Ordered constraint for enforcing this throughout the entire search space.

source
HerbConstraints.MatchFailType
@enum MatchFail hardfail softfail

This enum is used for distinguishing between two types of failures when trying to match a RuleNode either with another RuleNode or with an AbstractMatchNode

  • Hardfail means that there is no match, and there is no way to fill in the holes to get a match.
  • Softfail means that there is no match, but there might be a way to fill the holes that results in a match.
source
HerbConstraints.MatchNodeType
struct MatchNode <: AbstractMatchNode

Match a specific rulenode, where the grammar rule index is rule_ind and children matches the children of the RuleNode. Example usage:

MatchNode(3, [MatchNode(1), MatchNode(2)])

This matches RuleNode(3, [RuleNode(1), RuleNode(2)])

source
HerbConstraints.MatchVarType
struct MatchVar <: AbstractMatchNode

Matches anything and assigns it to a variable. The ForbiddenTree constraint will not match if identical variable symbols match to different trees. Example usage:

MatchNode(3, [MatchVar(:x), MatchVar(:x)])

This matches RuleNode(3, [RuleNode(1), RuleNode(1)]), RuleNode(3, [RuleNode(2), RuleNode(2)]), etc.

source
HerbConstraints.OrderedType
Ordered <: PropagatorConstraint

A PropagatorConstraint that enforces a specific order in MatchVar assignments in the pattern defined by tree. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the AbstractGrammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical.

The order defines an order between the variable assignments. For example, if the order is [x, y], the constraint will require the assignment to x to be less than or equal to the assignment to y. The order is recursively defined by RuleNode indices. For more information, see Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode).

For example, consider the tree 1(a, 2(b, 3(c, 4)))):

  • Ordered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:v, :w]) removes every rule with an index of 5 or greater from the domain of c, since that would make the index of the assignment to v greater than the index of the assignment to w, violating the order.
  • Ordered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:w, :v]) removes every rule with an index of 4 or less from the domain of c, since that would make the index of the assignment to v less than the index of the assignment to w, violating the order.
Warning

The Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.PropagatorConstraintType
PropagatorConstraint <: Constraint

Abstract type representing all propagator constraints. Each propagator constraint has an implementation of a propagate-function that takes

The propagate-function returns a tuple containing

source
HerbConstraints.RequireOnLeftType

Rules have to be used in the specified order. That is, rule at index K can only be used if rules at indices [1...K-1] are used in the left subtree of the current expression

source
HerbConstraints.@csgrammar_annotatedMacro

@csgrammar_annotated Define an annotated grammar and return it as a ContextSensitiveGrammar. Allows for adding optional annotations per rule. As well as that, allows for adding optional labels per rule, which can be referenced in annotations. Syntax is backwards-compatible with @csgrammar. Examples:

g₁ = @csgrammar_annotated begin
     Element = 1
     Element = x
     Element = Element + Element := commutative
@@ -18,4 +18,4 @@
                                                        forbidden_path([:addition, :one]) || forbidden_path([:one, :variable])
                                                     )
     multiplication:: Element = Element * Element := (commutative, transitive)
-end
source
Base.showMethod
Base.show(io::IO, node::MatchNode; separator=",", last_child::Bool=true)

Prints a found MatchNode given an and the respective children to IO.

source
Base.showMethod
Base.show(io::IO, node::MatchVar; separator=",", last_child::Bool=true)

Prints a matching variable assignment described by MatchVar to IO.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(expr::Expr, pattern::MatchNode, grammar::Grammar, j=0)

Internal function for matchnode2expr, recursively iterating over a matched pattern and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(typ::Symbol, pattern::MatchNode, grammar::Grammar, j=0)

Internal function for matchnode2expr, returning the matched translated symbol. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(typ::Symbol, pattern::MatchVar, grammar::Grammar, j=0)

Internal function for matchnode2expr. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(expr::Expr, pattern::MatchVar, grammar::Grammar, j=0)

Internal function for matchnode2expr, recursively iterating over a matched variable and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.

source
HerbConstraints._pattern_matchMethod
_pattern_match(rn::RuleNode, mn::MatchNode, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}

Tries to match RuleNode rn with MatchNode mn. Modifies the variable assignment dictionary vars. Returns nothing if the match is successful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)

source
HerbConstraints._pattern_matchMethod
_pattern_match(rn::RuleNode, mv::MatchVar, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}

Matching RuleNode rn with MatchVar mv. If the variable is already assigned, the rulenode is matched with the specific variable value. Returns nothing if the match is succesful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)

source
HerbConstraints._pattern_match_with_holeMethod
_pattern_match_with_hole(rn::RuleNode, mn::MatchNode, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}

Tries to match RuleNode rn with MatchNode mn and fill in the domain of the hole at hole_location. Returns if match is successful either:

  • The id for the node which fills the hole
  • A symbol for the variable that fills the hole
  • A tuple containing:
    • The variable that matched (the subtree containing) the hole
    • The location of the hole in this subtree

If the match is unsuccessful, it returns:

  • hardfail if there are no holes that can be filled in such a way that the match will become succesful
  • softfail if the match could become successful if the holes are filled in a certain way
source
HerbConstraints._pattern_match_with_holeMethod
_pattern_match_with_hole(rn::RuleNode, mv::MatchVar, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}

Tries to match RuleNode rn with MatchVar mv and fill in the domain of the hole at hole_location. If the variable name is already assigned in vars, the rulenode is matched with the hole. Otherwise the variable and the hole location are returned.

source
HerbConstraints._rulenode_match_with_holeMethod
_rulenode_match_with_hole(rn₁::RuleNode, rn₂::RuleNode, hole_location::Vector{Int})::Union{Int, MatchFail}

Matches two rulenodes. Returns how to fill in the hole in rn₁ to make it match rn₂ if:

  • rn₁ has a single hole at the provided location
  • rn₂ doesn't have any holes
  • rn₁ matches rn₂ apart from the single hole location.

If the match fails, it returns whether it is a softfail or a hardfail (see MatchFail docstring)

source
HerbConstraints.addparent!Method
addparent!(context::GrammarContext, parent::Int)

Adds a parent to the context. The parent is defined by the grammar rule id.

source
HerbConstraints.annotation2constraintMethod

Converts an annotation to a constraint. commutative: creates an Ordered constraint transitive: creates an (incorrect) Forbidden constraint forbidden_path(path::Vector{Union{Symbol, Int}}): creates a ForbiddenPath constraint with the original rule included ... || ...: creates a OneOf constraint (also works with ... || ... || ... et cetera, though not very performant)

source
HerbConstraints.make_smaller_or_equalMethod

Filters the domain of the hole at hole_location in rn₁ to make rn₁ be ordered before rn₂. Returns the filtered domain, and a boolean indicating if this constraint can be deleted.

source
HerbConstraints.matchnode2exprMethod
matchnode2expr(pattern::MatchNode, grammar::Grammar)

Converts a MatchNode tree into a Julia expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression.

source
HerbConstraints.matchnode2exprMethod
matchnode2expr(pattern::MatchVar, grammar::Grammar)

Converts a MatchVar into an expression by returning the variable directly. This is primarily useful for pretty-printing a pattern.

source
HerbConstraints.propagateMethod
propagate(c::Forbidden, g::Grammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}

Propagates the Forbidden constraint. It removes the rules from the domain that would complete the forbidden tree.

Warning

The Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.propagateMethod

Propagates the LocalForbidden constraint. It removes rules from the domain that would make the RuleNode at the given path match the pattern defined by the MatchNode.

source
HerbConstraints.propagateMethod

Propagates the LocalOrdered constraint. It removes rules from the domain that would violate the order of variables as defined in the constraint.

source
HerbConstraints.propagateMethod
propagate(c::Ordered, g::Grammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}

Propagates the Ordered constraint. Any rule that violates the order as defined by the contraint is removed from the domain.

Warning

The Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.propagateMethod

Propagates the RequireOnLeft constraint. It removes every element from the domain that does not have a necessary predecessor in the left subtree.

source

Index

+end
source
Base.showMethod
Base.show(io::IO, node::MatchNode; separator=",", last_child::Bool=true)

Prints a found MatchNode given an and the respective children to IO.

source
Base.showMethod
Base.show(io::IO, node::MatchVar; separator=",", last_child::Bool=true)

Prints a matching variable assignment described by MatchVar to IO.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(expr::Expr, pattern::MatchNode, grammar::AbstractGrammar, j=0)

Internal function for matchnode2expr, recursively iterating over a matched pattern and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(typ::Symbol, pattern::MatchNode, grammar::AbstractGrammar, j=0)

Internal function for matchnode2expr, returning the matched translated symbol. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(typ::Symbol, pattern::MatchVar, grammar::AbstractGrammar, j=0)

Internal function for matchnode2expr. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.

source
HerbConstraints._matchnode2exprFunction
_matchnode2expr(expr::Expr, pattern::MatchVar, grammar::AbstractGrammar, j=0)

Internal function for matchnode2expr, recursively iterating over a matched variable and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.

source
HerbConstraints._pattern_matchMethod
_pattern_match(rn::RuleNode, mn::MatchNode, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}

Tries to match RuleNode rn with MatchNode mn. Modifies the variable assignment dictionary vars. Returns nothing if the match is successful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)

source
HerbConstraints._pattern_matchMethod
_pattern_match(rn::RuleNode, mv::MatchVar, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}

Matching RuleNode rn with MatchVar mv. If the variable is already assigned, the rulenode is matched with the specific variable value. Returns nothing if the match is succesful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)

source
HerbConstraints._pattern_match_with_holeMethod
_pattern_match_with_hole(rn::RuleNode, mn::MatchNode, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}

Tries to match RuleNode rn with MatchNode mn and fill in the domain of the hole at hole_location. Returns if match is successful either:

  • The id for the node which fills the hole
  • A symbol for the variable that fills the hole
  • A tuple containing:
    • The variable that matched (the subtree containing) the hole
    • The location of the hole in this subtree

If the match is unsuccessful, it returns:

  • hardfail if there are no holes that can be filled in such a way that the match will become succesful
  • softfail if the match could become successful if the holes are filled in a certain way
source
HerbConstraints._pattern_match_with_holeMethod
_pattern_match_with_hole(rn::RuleNode, mv::MatchVar, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}

Tries to match RuleNode rn with MatchVar mv and fill in the domain of the hole at hole_location. If the variable name is already assigned in vars, the rulenode is matched with the hole. Otherwise the variable and the hole location are returned.

source
HerbConstraints._rulenode_match_with_holeMethod
_rulenode_match_with_hole(rn₁::RuleNode, rn₂::RuleNode, hole_location::Vector{Int})::Union{Int, MatchFail}

Matches two rulenodes. Returns how to fill in the hole in rn₁ to make it match rn₂ if:

  • rn₁ has a single hole at the provided location
  • rn₂ doesn't have any holes
  • rn₁ matches rn₂ apart from the single hole location.

If the match fails, it returns whether it is a softfail or a hardfail (see MatchFail docstring)

source
HerbConstraints.addparent!Method
addparent!(context::GrammarContext, parent::Int)

Adds a parent to the context. The parent is defined by the grammar rule id.

source
HerbConstraints.annotation2constraintMethod

Converts an annotation to a constraint. commutative: creates an Ordered constraint transitive: creates an (incorrect) Forbidden constraint forbidden_path(path::Vector{Union{Symbol, Int}}): creates a ForbiddenPath constraint with the original rule included ... || ...: creates a OneOf constraint (also works with ... || ... || ... et cetera, though not very performant)

source
HerbConstraints.make_smaller_or_equalMethod

Filters the domain of the hole at hole_location in rn₁ to make rn₁ be ordered before rn₂. Returns the filtered domain, and a boolean indicating if this constraint can be deleted.

source
HerbConstraints.matchnode2exprMethod
matchnode2expr(pattern::MatchNode, grammar::AbstractGrammar)

Converts a MatchNode tree into a Julia expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression.

source
HerbConstraints.matchnode2exprMethod
matchnode2expr(pattern::MatchVar, grammar::AbstractGrammar)

Converts a MatchVar into an expression by returning the variable directly. This is primarily useful for pretty-printing a pattern.

source
HerbConstraints.propagateMethod
propagate(c::Forbidden, g::AbstractGrammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}

Propagates the Forbidden constraint. It removes the rules from the domain that would complete the forbidden tree.

Warning

The Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.propagateMethod

Propagates the LocalForbidden constraint. It removes rules from the domain that would make the RuleNode at the given path match the pattern defined by the MatchNode.

source
HerbConstraints.propagateMethod

Propagates the LocalOrdered constraint. It removes rules from the domain that would violate the order of variables as defined in the constraint.

source
HerbConstraints.propagateMethod
propagate(c::Ordered, g::AbstractGrammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}

Propagates the Ordered constraint. Any rule that violates the order as defined by the contraint is removed from the domain.

Warning

The Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.

source
HerbConstraints.propagateMethod

Propagates the RequireOnLeft constraint. It removes every element from the domain that does not have a necessary predecessor in the left subtree.

source

Index

diff --git a/dev/HerbCore/index.html b/dev/HerbCore/index.html index 6e76ab3..fb42989 100644 --- a/dev/HerbCore/index.html +++ b/dev/HerbCore/index.html @@ -1,2 +1,2 @@ -HerbCore.jl Documentation · Herb.jl

HerbCore.jl Documentation

HerbCore.GrammarType
Grammar

Abstract type representing all grammars. It is assumed that all grammar structs have at least the following attributes:

  • rules::Vector{Any}: A list of RHS of rules (subexpressions).
  • types::Vector{Symbol}: A list of LHS of rules (types, all symbols).
  • isterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.
  • iseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.
  • bytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.
  • domains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.
  • childtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule.

If a rule is terminal, the corresponding list is empty.

  • log_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule.

If the grammar is non-probabilistic, the list can be nothing.

For concrete types, see ContextFreeGrammar and ContextSensitiveGrammar.

source
HerbCore.HoleType
Hole <: AbstractRuleNode

A Hole is a placeholder where certain rules from the grammar can still be applied. The domain of a Hole defines which rules can be applied. The domain is a bitvector, where the ith bit is set to true if the ith rule in the grammar can be applied.

source
HerbCore.RuleNodeType
RuleNode <: AbstractRuleNode

A RuleNode represents a node in an expression tree. Each node corresponds to a certain rule in the Grammar. A RuleNode consists of:

  • ind: The index of the rule in the Grammar which this node is representing.
  • _val: Field for storing immediately evaluated values
  • children: The children of this node in the expression tree
Compat

Evaluate immediately functionality is not yet supported by most of Herb.jl.

source
HerbCore.RuleNodeMethod
RuleNode(ind::Int, _val::Any)

Create a RuleNode for the Grammar rule with index ind, _val as immediately evaluated value and no children

Warning

Only use this constructor if you are absolutely certain that a rule is terminal and cannot have children. Use [RuleNode(ind::Int, grammar::Grammar)] for rules that might have children. In general, Holes should be used as a placeholder when the children of a node are not yet known.

Compat

Evaluate immediately functionality is not yet supported by most of Herb.jl.

source
Base.islessMethod
Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode)::Bool

Compares two RuleNodes. Returns true if the left RuleNode is less than the right RuleNode. Order is determined from the index of the RuleNodes. If both RuleNodes have the same index, a depth-first search is performed in both RuleNodes until nodes with a different index are found.

source
Base.lengthMethod
Base.length(root::RuleNode)

Return the number of nodes in the tree rooted at root. Holes don't count.

source
Base.lengthMethod
Base.length(root::RuleNode)

Return the number of nodes in the tree rooted at root. Holes don't count.

source
HerbCore.get_rulesequenceMethod
get_rulesequence(node::RuleNode, path::Vector{Int})

Extract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.

source
HerbCore.node_depthMethod
node_depth(root::AbstractRuleNode, node::AbstractRuleNode)::Int

Return the depth of node for an AbstractRuleNode tree rooted at root. Depth is 1 when root == node.

Warning

node must be a subtree of root in order for this function to work.

source
HerbCore.rulesonleftMethod
rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}

Finds all rules that are used in the left subtree defined by the path.

source
HerbCore.swap_nodeMethod
swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})

Replace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.

source
HerbCore.swap_nodeMethod
swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)

Replace child i of a node, a part of larger expr, with new_expr.

source

Index

+HerbCore.jl Documentation · Herb.jl

HerbCore.jl Documentation

HerbCore.AbstractGrammarType
AbstractGrammar

Abstract type representing all grammars. It is assumed that all grammar structs have at least the following attributes:

  • rules::Vector{Any}: A list of RHS of rules (subexpressions).
  • types::Vector{Symbol}: A list of LHS of rules (types, all symbols).
  • isterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.
  • iseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.
  • bytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.
  • domains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.
  • childtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule.

If a rule is terminal, the corresponding list is empty.

  • log_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule.

If the grammar is non-probabilistic, the list can be nothing.

For concrete types, see ContextSensitiveGrammar within the HerbGrammar module.

source
HerbCore.HoleType
Hole <: AbstractRuleNode

A Hole is a placeholder where certain rules from the grammar can still be applied. The domain of a Hole defines which rules can be applied. The domain is a bitvector, where the ith bit is set to true if the ith rule in the grammar can be applied.

source
HerbCore.RuleNodeType
RuleNode <: AbstractRuleNode

A RuleNode represents a node in an expression tree. Each node corresponds to a certain rule in the AbstractGrammar. A RuleNode consists of:

  • ind: The index of the rule in the AbstractGrammar which this node is representing.
  • _val: Field for storing immediately evaluated values
  • children: The children of this node in the expression tree
Compat

Evaluate immediately functionality is not yet supported by most of Herb.jl.

source
HerbCore.RuleNodeMethod
RuleNode(ind::Int, _val::Any)

Create a RuleNode for the AbstractGrammar rule with index ind, _val as immediately evaluated value and no children

Warning

Only use this constructor if you are absolutely certain that a rule is terminal and cannot have children. Use [RuleNode(ind::Int, grammar::AbstractGrammar)] for rules that might have children. In general, Holes should be used as a placeholder when the children of a node are not yet known.

Compat

Evaluate immediately functionality is not yet supported by most of Herb.jl.

source
Base.islessMethod
Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode)::Bool

Compares two RuleNodes. Returns true if the left RuleNode is less than the right RuleNode. Order is determined from the index of the RuleNodes. If both RuleNodes have the same index, a depth-first search is performed in both RuleNodes until nodes with a different index are found.

source
Base.lengthMethod
Base.length(root::RuleNode)

Return the number of nodes in the tree rooted at root. Holes don't count.

source
Base.lengthMethod
Base.length(root::RuleNode)

Return the number of nodes in the tree rooted at root. Holes don't count.

source
HerbCore.get_rulesequenceMethod
get_rulesequence(node::RuleNode, path::Vector{Int})

Extract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.

source
HerbCore.node_depthMethod
node_depth(root::AbstractRuleNode, node::AbstractRuleNode)::Int

Return the depth of node for an AbstractRuleNode tree rooted at root. Depth is 1 when root == node.

Warning

node must be a subtree of root in order for this function to work.

source
HerbCore.rulesonleftMethod
rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}

Finds all rules that are used in the left subtree defined by the path.

source
HerbCore.swap_nodeMethod
swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})

Replace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.

source
HerbCore.swap_nodeMethod
swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)

Replace child i of a node, a part of larger expr, with new_expr.

source

Index

diff --git a/dev/HerbData/index.html b/dev/HerbData/index.html index 7fbb5b2..0e5c61c 100644 --- a/dev/HerbData/index.html +++ b/dev/HerbData/index.html @@ -1,2 +1,2 @@ -HerbCore.jl · Herb.jl

HerbData.jl Documentation

HerbData.IOExampleType
struct IOExample <: Example

An input-output example. input is a Dict of {Symbol,Any} where the symbol represents a variable in a program. output can be anything.

source
HerbData.IOPExampleType
struct IOPExample <: Example

An input-output example with an associated program. ex is an IOExample. program is a program of arbitrary form. Please note that this is a pure container, and thus does not guarantee any checks on the validity of the program.

source
HerbData.read_IOPexamplesMethod
read_IOPexamples(filepath::AbstractString)::Vector{Tuple{IOPExample}

Reads serialized IO + program examples from disk after type checking.

source
HerbData.read_IOexamplesMethod
read_IOexamples(filepath::AbstractString)::Vector{IOExample}

Reads serialized IO examples from disk after type checking.

source
HerbData.readdataMethod
readdata(directory::AbstractString, lineparser::Function)::Vector{Problem}

Reads all files in the given directory and parses them line by line into an ExampleProblem using the given lineparser.

TODO: Turn this into an iterator that doesn't load all data into memory at initialization.

source
HerbData.readfileMethod
readfile(filepath::AbstractString, lineparser::Function)::Problem

Reads a file and parses every non-empty line using the line parser.

source
HerbData.write_IOPexamplesMethod
write_IOPexamples(filepath::AbstractString, examples::Vector{Tuple{IOExample, Any}})

Writes IO examples and the corresponding programs to disk by serializing them into a file using HDF5 checking for and appending the .xiop.

source
HerbData.write_IOexamplesMethod
write_IOexamples(filepath::AbstractString, examples::Vector{IOExample})

Writes IO examples to disk by serializing them into a file using HDF5 checking for and appending the .xio file ending.

source

Index

+HerbCore.jl · Herb.jl

HerbData.jl Documentation

HerbData.IOExampleType
struct IOExample <: Example

An input-output example. input is a Dict of {Symbol,Any} where the symbol represents a variable in a program. output can be anything.

source
HerbData.IOPExampleType
struct IOPExample <: Example

An input-output example with an associated program. ex is an IOExample. program is a program of arbitrary form. Please note that this is a pure container, and thus does not guarantee any checks on the validity of the program.

source
HerbData.read_IOPexamplesMethod
read_IOPexamples(filepath::AbstractString)::Vector{Tuple{IOPExample}

Reads serialized IO + program examples from disk after type checking.

source
HerbData.read_IOexamplesMethod
read_IOexamples(filepath::AbstractString)::Vector{IOExample}

Reads serialized IO examples from disk after type checking.

source
HerbData.readdataMethod
readdata(directory::AbstractString, lineparser::Function)::Vector{Problem}

Reads all files in the given directory and parses them line by line into an ExampleProblem using the given lineparser.

TODO: Turn this into an iterator that doesn't load all data into memory at initialization.

source
HerbData.readfileMethod
readfile(filepath::AbstractString, lineparser::Function)::Problem

Reads a file and parses every non-empty line using the line parser.

source
HerbData.write_IOPexamplesMethod
write_IOPexamples(filepath::AbstractString, examples::Vector{Tuple{IOExample, Any}})

Writes IO examples and the corresponding programs to disk by serializing them into a file using HDF5 checking for and appending the .xiop.

source
HerbData.write_IOexamplesMethod
write_IOexamples(filepath::AbstractString, examples::Vector{IOExample})

Writes IO examples to disk by serializing them into a file using HDF5 checking for and appending the .xio file ending.

source

Index

diff --git a/dev/HerbGrammar/index.html b/dev/HerbGrammar/index.html index db74473..a5ceb72 100644 --- a/dev/HerbGrammar/index.html +++ b/dev/HerbGrammar/index.html @@ -1,42 +1,22 @@ -HerbGrammar.jl · Herb.jl

HerbGrammar.jl Documentation

HerbGrammar.ContextFreeGrammarType
ContextFreeGrammar <: Grammar

Represents a context-free grammar and its production rules. Consists of:

  • rules::Vector{Any}: A list of RHS of rules (subexpressions).
  • types::Vector{Symbol}: A list of LHS of rules (types, all symbols).
  • isterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.
  • iseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.
  • bytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.
  • domains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.
  • childtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. If a rule is terminal, the corresponding list is empty.
  • log_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. If the grammar is non-probabilistic, the list can be nothing.

Use the @cfgrammar macro to create a ContextFreeGrammar object. Use the @pcfgrammar macro to create a ContextFreeGrammar object with probabilities. For context-sensitive grammars, see ContextSensitiveGrammar.

source
HerbGrammar.ContextSensitiveGrammarType
ContextSensitiveGrammar <: Grammar

Represents a context-sensitive grammar. Extends Grammar with constraints.

Consists of:

  • rules::Vector{Any}: A list of RHS of rules (subexpressions).
  • types::Vector{Symbol}: A list of LHS of rules (types, all symbols).
  • isterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.
  • iseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.
  • bytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.
  • domains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.
  • childtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. If a rule is terminal, the corresponding list is empty.
  • log_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. If the grammar is non-probabilistic, the list can be nothing.
  • constraints::Vector{Constraint}: A list of constraints that programs in this grammar have to abide.

Use the @csgrammar macro to create a ContextSensitiveGrammar object. Use the @pcsgrammar macro to create a ContextSensitiveGrammar object with probabilities. For context-free grammars, see ContextFreeGrammar.

source
HerbGrammar.NodeLocType

NodeLoc A helper struct that points to a node in the tree via its parent such that the child can be easily swapped out. If i is 0 the node pointed to is the root node and parent is the node itself.

source
HerbGrammar.@cfgrammarMacro
@cfgrammar

A macro for defining a ContextFreeGrammar.

Example usage:

grammar = @cfgrammar begin
+HerbGrammar.jl · Herb.jl

HerbGrammar.jl Documentation

HerbGrammar.ContextSensitiveGrammarType
ContextSensitiveGrammar <: AbstractGrammar

Represents a context-sensitive grammar. Extends AbstractGrammar with constraints.

Consists of:

  • rules::Vector{Any}: A list of RHS of rules (subexpressions).
  • types::Vector{Symbol}: A list of LHS of rules (types, all symbols).
  • isterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.
  • iseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.
  • bytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.
  • domains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.
  • childtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. If a rule is terminal, the corresponding list is empty.
  • log_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. If the grammar is non-probabilistic, the list can be nothing.
  • constraints::Vector{Constraint}: A list of constraints that programs in this grammar have to abide.

Use the @csgrammar macro to create a ContextSensitiveGrammar object. Use the @pcsgrammar macro to create a ContextSensitiveGrammar object with probabilities.

source
HerbGrammar.NodeLocType

NodeLoc A helper struct that points to a node in the tree via its parent such that the child can be easily swapped out. If i is 0 the node pointed to is the root node and parent is the node itself.

source
HerbGrammar.@csgrammarMacro
@csgrammar

A macro for defining a ContextSensitiveGrammar. Constraints can be added afterwards using the addconstraint! function.

Example usage:

grammar = @csgrammar begin
 	R = x
 	R = 1 | 2
 	R = R + R
-end

Syntax:

  • Literals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.
  • Variables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.
  • Functions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).
  • Combinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.
  • Iterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).

Related:

source
HerbGrammar.@csgrammarMacro
@csgrammar

A macro for defining a ContextSensitiveGrammar. Constraints can be added afterwards using the addconstraint! function.

Example usage:

grammar = @csgrammar begin
-	R = x
-	R = 1 | 2
-	R = R + R
-end

Syntax:

  • Literals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.
  • Variables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.
  • Functions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).
  • Combinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.
  • Iterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).

Related:

source
HerbGrammar.@pcfgrammarMacro
@pcfgrammar

A macro for defining a probabilistic ContextFreeGrammar.

Example usage:

grammar = @pcfgrammar begin
-	0.5 : R = x
-	0.3 : R = 1 | 2
-	0.2 : R = R + R
-end

Syntax:

The syntax of rules is identical to the syntax used by @cfgrammar:

  • Literals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.
  • Variables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.
  • Functions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).
  • Combinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.
  • Iterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).

Every rule is also prefixed with a probability. Rules and probabilities are separated using the : symbol. If multiple rules are defined on a single line, the probability is equally divided between the rules. The sum of probabilities for all rules of a certain non-terminal symbol should be equal to 1. The probabilities are automatically scaled if this isn't the case.

Related:

source
HerbGrammar.@pcsgrammarMacro
@pcsgrammar

A macro for defining a probabilistic ContextSensitiveGrammar.

Example usage:

grammar = @pcsgrammar begin
+end

Syntax:

  • Literals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.
  • Variables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.
  • Functions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).
  • Combinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.
  • Iterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).

Related:

source
HerbGrammar.@pcsgrammarMacro
@pcsgrammar

A macro for defining a probabilistic ContextSensitiveGrammar.

Example usage:

grammar = @pcsgrammar begin
 	0.5 : R = x
 	0.3 : R = 1 | 2
 	0.2 : R = R + R
-end

Syntax:

The syntax of rules is identical to the syntax used by @csgrammar:

  • Literals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.
  • Variables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.
  • Functions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).
  • Combinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.
  • Iterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).

Every rule is also prefixed with a probability. Rules and probabilities are separated using the : symbol. If multiple rules are defined on a single line, the probability is equally divided between the rules. The sum of probabilities for all rules of a certain non-terminal symbol should be equal to 1. The probabilities are automatically scaled if this isn't the case.

Related:

source
Base.getMethod

get(root::RuleNode, loc::NodeLoc) Obtain the node pointed to by loc.

source
Base.insert!Method

insert!(loc::NodeLoc, rulenode::RuleNode) Replaces the subtree pointed to by loc with the given rulenode.

source
HerbGrammar.add_rule!Method
add_rule!(g::Grammar, e::Expr)

Adds a rule to the grammar.

Usage:

	add_rule!(grammar, :("Real = Real + Real"))

The syntax is identical to the syntax of @csgrammar and @cfgrammar, but only single rules are supported.

Warning

Calls to this function are ignored if a rule is already in the grammar.

source
HerbGrammar.child_typesMethod
child_types(grammar::Grammar, rule_index::Int)

Returns the types of the children (nonterminals) of the production rule at rule_index.

source
HerbGrammar.child_typesMethod
child_types(grammar::Grammar, node::RuleNode)

Returns the list of child types (nonterminal symbols) in the production rule used by node.

source
HerbGrammar.cleanup_removed_rules!Method
cleanup_removed_rules!(g::Grammar)

Removes any placeholders for previously deleted rules. This means that indices get shifted.

Warning

When indices are shifted, this grammar can no longer be used to interpret AbstractRuleNode trees created before the call to this function. These trees become meaningless.

source
HerbGrammar.containedinMethod
containedin(vec1::Vector, vec2::Vector)

Checks if elements of vec1 are contained in vec2 in the same order (possibly with elements in between)

source
HerbGrammar.contains_returntypeFunction
contains_returntype(node::RuleNode, grammar::Grammar, sym::Symbol, maxdepth::Int=typemax(Int))

Returns true if the tree rooted at node contains at least one node at depth less than maxdepth with the given return type or nonterminal symbol.

source
HerbGrammar.expr2cfgrammarMethod
expr2cfgrammar(ex::Expr)::ContextFreeGrammar

A function for converting an Expr to a ContextFreeGrammar. If the expression is hardcoded, you should use the @cfgrammar macro. Only expressions in the correct format (see @cfgrammar) can be converted.

Example usage:

grammar = expr2cfgrammar(
-	begin
-		R = x
-		R = 1 | 2
-		R = R + R
-	end
-)
source
HerbGrammar.expr2csgrammarMethod
expr2csgrammar(ex::Expr)::ContextSensitiveGrammar

A function for converting an Expr to a ContextSensitiveGrammar. If the expression is hardcoded, you should use the @csgrammar macro. Only expressions in the correct format (see @csgrammar) can be converted.

Example usage:

grammar = expr2csgrammar(
+end

Syntax:

The syntax of rules is identical to the syntax used by @csgrammar:

  • Literals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.
  • Variables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.
  • Functions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).
  • Combinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.
  • Iterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).

Every rule is also prefixed with a probability. Rules and probabilities are separated using the : symbol. If multiple rules are defined on a single line, the probability is equally divided between the rules. The sum of probabilities for all rules of a certain non-terminal symbol should be equal to 1. The probabilities are automatically scaled if this isn't the case.

Related:

source
Base.getMethod

get(root::RuleNode, loc::NodeLoc) Obtain the node pointed to by loc.

source
Base.insert!Method

insert!(loc::NodeLoc, rulenode::RuleNode) Replaces the subtree pointed to by loc with the given rulenode.

source
HerbGrammar.add_rule!Method
add_rule!(g::AbstractGrammar, e::Expr)

Adds a rule to the grammar.

Usage:

	add_rule!(grammar, :("Real = Real + Real"))

The syntax is identical to the syntax of @csgrammar and @cfgrammar, but only single rules are supported.

Warning

Calls to this function are ignored if a rule is already in the grammar.

source
HerbGrammar.child_typesMethod
child_types(grammar::AbstractGrammar, rule_index::Int)

Returns the types of the children (nonterminals) of the production rule at rule_index.

source
HerbGrammar.child_typesMethod
child_types(grammar::AbstractGrammar, node::RuleNode)

Returns the list of child types (nonterminal symbols) in the production rule used by node.

source
HerbGrammar.cleanup_removed_rules!Method
cleanup_removed_rules!(g::AbstractGrammar)

Removes any placeholders for previously deleted rules. This means that indices get shifted.

Warning

When indices are shifted, this grammar can no longer be used to interpret AbstractRuleNode trees created before the call to this function. These trees become meaningless.

source
HerbGrammar.containedinMethod
containedin(vec1::Vector, vec2::Vector)

Checks if elements of vec1 are contained in vec2 in the same order (possibly with elements in between)

source
HerbGrammar.contains_returntypeFunction
contains_returntype(node::RuleNode, grammar::AbstractGrammar, sym::Symbol, maxdepth::Int=typemax(Int))

Returns true if the tree rooted at node contains at least one node at depth less than maxdepth with the given return type or nonterminal symbol.

source
HerbGrammar.expr2csgrammarMethod
expr2csgrammar(ex::Expr)::ContextSensitiveGrammar

A function for converting an Expr to a ContextSensitiveGrammar. If the expression is hardcoded, you should use the @csgrammar macro. Only expressions in the correct format (see @csgrammar) can be converted.

Example usage:

grammar = expr2csgrammar(
 	begin
 		R = x
 		R = 1 | 2
 		R = R + R
 	end
-)
source
HerbGrammar.expr2pcfgrammarMethod

Function for converting an Expr to a ContextFreeGrammar with probabilities. If the expression is hardcoded, you should use the @pcfgrammar macro. Only expressions in the correct format (see @pcfgrammar) can be converted.

Example usage:

grammar = expr2pcsgrammar(
-	begin
-		0.5 : R = x
-		0.3 : R = 1 | 2
-		0.2 : R = R + R
-	end
-)
source
HerbGrammar.expr2pcsgrammarMethod

Function for converting an Expr to a ContextSensitiveGrammar with probabilities. If the expression is hardcoded, you should use the @pcsgrammar macro. Only expressions in the correct format (see @pcsgrammar) can be converted.

Example usage:

grammar = expr2pcsgrammar(
 	begin
 		0.5 : R = x
 		0.3 : R = 1 | 2
 		0.2 : R = R + R
 	end
-)
source
HerbGrammar.get_domainMethod
get_domain(g::Grammar, type::Symbol)::BitVector

Returns the domain for the hole of a certain type as a BitVector of the same length as the number of rules in the grammar. Bit i is set to true iff rule i is of type type.

Info

Since this function can be intensively used when exploring a program space defined by a grammar, the outcomes of this function are precomputed and stored in the domains field in a Grammar.

source
HerbGrammar.get_domainMethod
get_domain(g::Grammar, rules::Vector{Int})::BitVector

Takes a domain rules defined as a vector of ints and converts it to a domain defined as a BitVector.

source
HerbGrammar.get_rulesequenceMethod
get_rulesequence(node::RuleNode, path::Vector{Int})

Extract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.

source
HerbGrammar.iscompleteMethod
iscomplete(grammar::Grammar, node::RuleNode)

Returns true if the expression represented by the RuleNode is a complete expression, meaning that it is fully defined and doesn't have any Holes.

source
HerbGrammar.isevalMethod
iseval(rule)

Returns true if the rule is the special evaluate immediately function, i.e., _()

Compat

evaluate immediately functionality is not yet supported by most of Herb.jl

source
HerbGrammar.isevalMethod
iseval(grammar::Grammar, index::Int)::Bool

Returns true if the production rule at rule_index contains the special _() eval function.

Compat

evaluate immediately functionality is not yet supported by most of Herb.jl

source
HerbGrammar.isevalMethod
iseval(grammar::Grammar)::Bool

Returns true if any production rules in grammar contain the special _() eval function.

Compat

evaluate immediately functionality is not yet supported by most of Herb.jl

source
HerbGrammar.isterminalMethod
isterminal(rule::Any, types::AbstractVector{Symbol})

Returns true if the rule is terminal, i.e., it does not contain any of the types in the provided vector. For example, :(x) is terminal, and :(1+1) is terminal, but :(Real + Real) is typically not.

source
HerbGrammar.isterminalMethod
isterminal(grammar::Grammar, rule_index::Int)::Bool

Returns true if the production rule at rule_index is terminal, i.e., does not contain any nonterminal symbols.

source
HerbGrammar.isterminalMethod
isterminal(grammar::Grammar, node::RuleNode)::Bool

Returns true if the production rule used by node is terminal, i.e., does not contain any nonterminal symbols.

source
HerbGrammar.isvariableMethod
isvariable(grammar::Grammar, node::RuleNode)::Bool

Returns true if the rule used by node represents a variable.

source
HerbGrammar.log_probabilityMethod
log_probability(grammar::Grammar, index::Int)::Real

Returns the log probability for the rule at index in the grammar.

Warning

If the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.

source
HerbGrammar.mindepthMethod
mindepth(grammar::Grammar, typ::Symbol, dmap::AbstractVector{Int})

Returns the minimum depth achievable for a given nonterminal symbol. The minimum depth is the depth of the lowest tree that can be made using typ as a start symbol. dmap can be obtained from mindepth_map.

source
HerbGrammar.mindepth_mapMethod
mindepth_map(grammar::Grammar)

Returns the minimum depth achievable for each production rule in the Grammar. In other words, this function finds the depths of the lowest trees that can be made using each of the available production rules as a root.

source
HerbGrammar.nchildrenMethod
nchildren(grammar::Grammar, rule_index::Int)::Int

Returns the number of children (nonterminals) of the production rule at rule_index.

source
HerbGrammar.nchildrenMethod
nchildren(grammar::Grammar, node::RuleNode)::Int

Returns the number of children in the production rule used by node.

source
HerbGrammar.probabilityMethod
probability(grammar::Grammar, index::Int)::Real

Return the probability for a rule in the grammar. Use log_probability whenever possible.

Warning

If the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.

source
HerbGrammar.read_cfgMethod
read_cfg(filepath::AbstractString)::ContextFreeGrammar

Reads a ContextFreeGrammar from the file provided in filepath.

Danger

Only open trusted grammars. Parts of the grammar can be passed to Julia's eval function.

source
HerbGrammar.read_csgMethod
read_csg(grammarpath::AbstractString, constraintspath::AbstractString)::ContextSensitiveGrammar

Reads a ContextSensitiveGrammar from the files at grammarpath and constraintspath. The grammar path may also point to a ContextFreeGrammar.

Danger

Only open trusted grammars. Parts of the grammar can be passed to Julia's eval function.

source
HerbGrammar.read_pcfgMethod
read_pcfg(filepath::AbstractString)::ContextFreeGrammar

Reads a probabilistic ContextFreeGrammar from a file provided in filepath.

Danger

Only open trusted grammars. Parts of the grammar can be passed to Julia's eval function.

source
HerbGrammar.read_pcsgMethod
read_pcsg(grammarpath::AbstractString, constraintspath::AbstractString)::ContextSensitiveGrammar

Reads a probabilistic ContextSensitiveGrammar from the files at grammarpath and constraintspath. The grammar path may also point to a ContextFreeGrammar.

Danger

Only open trusted grammars. Parts of the grammar can be passed to Julia's eval function.

source
HerbGrammar.remove_rule!Method
remove_rule!(g::Grammar, idx::Int)

Removes the rule corresponding to idx from the grammar. In order to avoid shifting indices, the rule is replaced with nothing, and all other data structures are updated accordingly.

source
HerbGrammar.return_typeMethod
return_type(grammar::Grammar, rule_index::Int)::Symbol

Returns the type of the production rule at rule_index.

source
HerbGrammar.return_typeMethod
return_type(grammar::Grammar, node::RuleNode)

Gives the return type or nonterminal symbol in the production rule used by node.

source
HerbGrammar.rulenode2exprMethod
rulenode2expr(rulenode::RuleNode, grammar::Grammar)

Converts a RuleNode into a Julia expression corresponding to the rule definitions in the grammar. The returned expression can be evaluated with Julia semantics using eval().

source
HerbGrammar.rulesoftypeMethod
rulesoftype(node::RuleNode, grammar::Grammar, ruletype::Symbol, ignoreNode::RuleNode)

Returns every rule of nonterminal symbol ruletype that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.

Warning

The ignoreNode must be a subtree of node for it to have an effect.

source
HerbGrammar.rulesoftypeMethod
rulesoftype(node::RuleNode, ruleset::Set{Int}, ignoreNode::RuleNode)

Returns every rule in the ruleset that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.

Warning

The ignoreNode must be a subtree of node for it to have an effect.

source
HerbGrammar.rulesonleftMethod
rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}

Finds all rules that are used in the left subtree defined by the path.

source
HerbGrammar.swap_nodeMethod
swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})

Replace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.

source
HerbGrammar.swap_nodeMethod
swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)

Replace child i of a node, a part of larger expr, with new_expr.

source

Index

+)
source
HerbGrammar.get_domainMethod
get_domain(g::AbstractGrammar, type::Symbol)::BitVector

Returns the domain for the hole of a certain type as a BitVector of the same length as the number of rules in the grammar. Bit i is set to true iff rule i is of type type.

Info

Since this function can be intensively used when exploring a program space defined by a grammar, the outcomes of this function are precomputed and stored in the domains field in a AbstractGrammar.

source
HerbGrammar.get_domainMethod
get_domain(g::AbstractGrammar, rules::Vector{Int})::BitVector

Takes a domain rules defined as a vector of ints and converts it to a domain defined as a BitVector.

source
HerbGrammar.get_rulesequenceMethod
get_rulesequence(node::RuleNode, path::Vector{Int})

Extract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.

source
HerbGrammar.iscompleteMethod
iscomplete(grammar::AbstractGrammar, node::RuleNode)

Returns true if the expression represented by the RuleNode is a complete expression, meaning that it is fully defined and doesn't have any Holes.

source
HerbGrammar.isevalMethod
iseval(grammar::AbstractGrammar, index::Int)::Bool

Returns true if the production rule at rule_index contains the special _() eval function.

Compat

evaluate immediately functionality is not yet supported by most of Herb.jl

source
HerbGrammar.isevalMethod
iseval(grammar::AbstractGrammar)::Bool

Returns true if any production rules in grammar contain the special _() eval function.

Compat

evaluate immediately functionality is not yet supported by most of Herb.jl

source
HerbGrammar.isevalMethod
iseval(rule)

Returns true if the rule is the special evaluate immediately function, i.e., _()

Compat

evaluate immediately functionality is not yet supported by most of Herb.jl

source
HerbGrammar.isterminalMethod
isterminal(grammar::AbstractGrammar, rule_index::Int)::Bool

Returns true if the production rule at rule_index is terminal, i.e., does not contain any nonterminal symbols.

source
HerbGrammar.isterminalMethod
isterminal(grammar::AbstractGrammar, node::RuleNode)::Bool

Returns true if the production rule used by node is terminal, i.e., does not contain any nonterminal symbols.

source
HerbGrammar.isterminalMethod
isterminal(rule::Any, types::AbstractVector{Symbol})

Returns true if the rule is terminal, i.e., it does not contain any of the types in the provided vector. For example, :(x) is terminal, and :(1+1) is terminal, but :(Real + Real) is typically not.

source
HerbGrammar.isvariableMethod
isvariable(grammar::AbstractGrammar, ind::Int, mod::Module)::Bool

Return true if the rule with index ind represents a variable.

Taking into account the symbols defined in the given module(s).

source
HerbGrammar.isvariableMethod
isvariable(grammar::AbstractGrammar, ind::Int)::Bool

Return true if the rule with index ind represents a variable.

source
HerbGrammar.isvariableMethod
isvariable(grammar::AbstractGrammar, node::RuleNode, mod::Module)::Bool

Return true if the rule used by node represents a variable.

Taking into account the symbols defined in the given module(s).

source
HerbGrammar.isvariableMethod
isvariable(grammar::AbstractGrammar, node::RuleNode)::Bool

Return true if the rule used by node represents a variable in a program (essentially, an input to the program)

source
HerbGrammar.log_probabilityMethod
log_probability(grammar::AbstractGrammar, index::Int)::Real

Returns the log probability for the rule at index in the grammar.

Warning

If the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.

source
HerbGrammar.merge_grammars!Method
merge_grammars!(merge_to::AbstractGrammar, merge_from::AbstractGrammar)

Adds all rules and constraints from merge_from to merge_to.

source
HerbGrammar.mindepthMethod
mindepth(grammar::AbstractGrammar, typ::Symbol, dmap::AbstractVector{Int})

Returns the minimum depth achievable for a given nonterminal symbol. The minimum depth is the depth of the lowest tree that can be made using typ as a start symbol. dmap can be obtained from mindepth_map.

source
HerbGrammar.mindepth_mapMethod
mindepth_map(grammar::AbstractGrammar)

Returns the minimum depth achievable for each production rule in the AbstractGrammar. In other words, this function finds the depths of the lowest trees that can be made using each of the available production rules as a root.

source
HerbGrammar.nchildrenMethod
nchildren(grammar::AbstractGrammar, rule_index::Int)::Int

Returns the number of children (nonterminals) of the production rule at rule_index.

source
HerbGrammar.nchildrenMethod
nchildren(grammar::AbstractGrammar, node::RuleNode)::Int

Returns the number of children in the production rule used by node.

source
HerbGrammar.probabilityMethod
probability(grammar::AbstractGrammar, index::Int)::Real

Return the probability for a rule in the grammar. Use log_probability whenever possible.

Warning

If the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.

source
HerbGrammar.read_csgFunction
read_csg(grammarpath::AbstractString, constraintspath::OptionalPath=nothing)::ContextSensitiveGrammar

Reads a ContextSensitiveGrammar from the files at grammarpath and constraintspath.

Danger

Only open trusted grammars. Parts of the grammar can be passed to Julia's eval function.

source
HerbGrammar.read_pcsgFunction
read_pcsg(grammarpath::AbstractString, constraintspath::OptionalPath=nothing)::ContextSensitiveGrammar

Reads a probabilistic ContextSensitiveGrammar from the files at grammarpath and constraintspath.

Danger

Only open trusted grammars. Parts of the grammar can be passed to Julia's eval function.

source
HerbGrammar.remove_rule!Method
remove_rule!(g::AbstractGrammar, idx::Int)

Removes the rule corresponding to idx from the grammar. In order to avoid shifting indices, the rule is replaced with nothing, and all other data structures are updated accordingly.

source
HerbGrammar.return_typeMethod
return_type(grammar::AbstractGrammar, rule_index::Int)::Symbol

Returns the type of the production rule at rule_index.

source
HerbGrammar.return_typeMethod
return_type(grammar::AbstractGrammar, node::RuleNode)

Gives the return type or nonterminal symbol in the production rule used by node.

source
HerbGrammar.rulenode2exprMethod
rulenode2expr(rulenode::RuleNode, grammar::AbstractGrammar)

Converts a RuleNode into a Julia expression corresponding to the rule definitions in the grammar. The returned expression can be evaluated with Julia semantics using eval().

source
HerbGrammar.rulesoftypeMethod
rulesoftype(node::RuleNode, grammar::AbstractGrammar, ruletype::Symbol, ignoreNode::RuleNode)

Returns every rule of nonterminal symbol ruletype that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.

Warning

The ignoreNode must be a subtree of node for it to have an effect.

source
HerbGrammar.rulesoftypeMethod
rulesoftype(node::RuleNode, ruleset::Set{Int}, ignoreNode::RuleNode)

Returns every rule in the ruleset that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.

Warning

The ignoreNode must be a subtree of node for it to have an effect.

source
HerbGrammar.rulesonleftMethod
rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}

Finds all rules that are used in the left subtree defined by the path.

source
HerbGrammar.swap_nodeMethod
swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})

Replace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.

source
HerbGrammar.swap_nodeMethod
swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)

Replace child i of a node, a part of larger expr, with new_expr.

source

Index

diff --git a/dev/HerbInterpret/index.html b/dev/HerbInterpret/index.html index 4cb8aa8..19fd102 100644 --- a/dev/HerbInterpret/index.html +++ b/dev/HerbInterpret/index.html @@ -1,4 +1,4 @@ -HerbInterpret.jl · Herb.jl

HerbInterpret.jl Documentation

HerbInterpret.evaluate_programMethod
evaluate_program(program::RuleNode, examples::Vector{<:Example}, grammar::Grammar, evaluation_function::Function)

Runs a program on the examples and returns tuples of actual desired output and the program's output

source
HerbInterpret.execute_on_examplesMethod
execute_on_examples(tab::SymbolTable, expr::Any, example_inputs::Vector{Dict{Symbol, Any}})::Vector{Any}

Executes a given expression on a set of inputs and returns the respective outputs. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source
HerbInterpret.interpretMethod
interpret(tab::SymbolTable, ex::Expr)

Evaluates an expression without compiling it. Uses AST and symbol lookups. Only supports :call and :(=) expressions at the moment.

Example usage:

tab = SymbolTable(:f => f, :x => x)
+HerbInterpret.jl · Herb.jl

HerbInterpret.jl Documentation

HerbInterpret.evaluate_programMethod
evaluate_program(program::RuleNode, examples::Vector{<:IOExample}, grammar::AbstractGrammar, evaluation_function::Function)

Runs a program on the examples and returns tuples of actual desired output and the program's output

source
HerbInterpret.execute_on_inputMethod
execute_on_input(grammar::AbstractGrammar, program::RuleNode, input::Dict{Symbol, T})::Any where T

Converts a RuleNode program into an expression using a given grammar, then evaluates this expression with a single input dictionary input and a symbol table derived from the grammar using execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T}).

Arguments

  • grammar::AbstractGrammar: A grammar object used to convert the RuleNode into an executable expression.
  • program::RuleNode: The program, represented as a RuleNode, to be converted and evaluated.
  • input::Dict{Symbol, T}: A dictionary providing input values for symbols used in the generated expression.

Returns

  • Any: The result of evaluating the generated expression with the given input dictionary.
source
HerbInterpret.execute_on_inputMethod
execute_on_input(grammar::AbstractGrammar, program::RuleNode, input::Vector{T})::Vector{Any} where T <: Dict{Symbol, <:Any}

Converts a RuleNode program into an expression using a given grammar, then evaluates this expression for each input dictionary in a vector input and a symbol table derived from the grammar using execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T}).

Arguments

  • grammar::AbstractGrammar: A grammar object used to convert the RuleNode into an executable expression.
  • program::RuleNode: The program, represented as a RuleNode, to be converted and evaluated.
  • input::Vector{T}: A vector of dictionaries, each providing input values for symbols used in the generated expression.

Returns

  • Vector{Any}: A vector containing the results of evaluating the generated expression for each input dictionary.
source
HerbInterpret.execute_on_inputMethod
execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T})::Any where T

Evaluates an expression expr within the context of a symbol table tab and a single input dictionary input. The input dictionary keys should match the symbols used in the expression, and their values are used during the expression's evaluation.

Arguments

  • tab::SymbolTable: A symbol table containing predefined symbols and their associated values or functions.
  • expr::Any: The expression to be evaluated. Can be any Julia expression that is valid within the context of the provided symbol table and input.
  • input::Dict{Symbol, T}: A dictionary where each key is a symbol used in the expression, and the value is the corresponding value to be used in the expression's evaluation. The type T can be any type.

Returns

  • Any: The result of evaluating the expression with the given symbol table and input dictionary.
Warning

This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source
HerbInterpret.execute_on_inputMethod
execute_on_input(tab::SymbolTable, expr::Any, input::Vector{T})::Vector{<:Any} where T <: Dict{Symbol, <:Any}

Wrapper around execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T}) to execute all inputs given as an array.

Arguments

  • tab::SymbolTable: A symbol table containing predefined symbols and their associated values or functions.
  • expr::Any: The expression to be evaluated for each input dictionary.
  • inputs::Vector{T}: A vector of dictionaries, each serving as an individual set of inputs for the expression's evaluation.

Returns

  • Vector{<:Any}: A vector containing the results of evaluating the expression for each input dictionary.
source
HerbInterpret.interpretMethod
interpret(tab::SymbolTable, ex::Expr)

Evaluates an expression without compiling it. Uses AST and symbol lookups. Only supports :call and :(=) expressions at the moment.

Example usage:

tab = SymbolTable(:f => f, :x => x)
 ex = :(f(x))
-interpret(tab, ex)

WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source
HerbInterpret.test_all_examplesMethod
test_all_examples(tab::SymbolTable, expr::Any, examples::Vector{Example})::Vector{Bool}

Runs the interpreter on all examples with the given input table and expression. The symbol table defines everything (functions, symbols) that are not input variables to the program to be synthesised. Returns a list of true/false values indicating if the expression satisfies the corresponding example. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source
HerbInterpret.test_examplesMethod
test_examples(tab::SymbolTable, expr::Any, examples::Vector{Example})::Bool

Evaluates all examples and returns true iff all examples pass. Shortcircuits as soon as an example is found for which the program doesn't work. Returns false if one of the examples produces an error.

source
HerbInterpret.test_with_inputMethod
test_with_input(tab::SymbolTable, expr::Any, input::Dict)

Interprets an expression or symbol with the given symboltable and the input. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source

Index

+interpret(tab, ex)

WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source
HerbInterpret.test_all_examplesMethod
test_all_examples(tab::SymbolTable, expr::Any, examples::Vector{IOExample})::Vector{Bool}
Warning

This function is deprecated. Please use execute_on_input instead.

Runs the interpreter on all examples with the given input table and expression. The symbol table defines everything (functions, symbols) that are not input variables to the program to be synthesised. Returns a list of true/false values indicating if the expression satisfies the corresponding example. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.

source
HerbInterpret.test_examplesMethod
test_examples(tab::SymbolTable, expr::Any, examples::Vector{IOExample})::Bool
Warning

This function is deprecated. Please use execute_on_input instead.

Evaluates all examples and returns true iff all examples pass. Shortcircuits as soon as an example is found for which the program doesn't work. Returns false if one of the examples produces an error.

source

Index

diff --git a/dev/HerbSearch/index.html b/dev/HerbSearch/index.html index 71b091c..ce371a3 100644 --- a/dev/HerbSearch/index.html +++ b/dev/HerbSearch/index.html @@ -1,32 +1,4 @@ -HerbSearch.jl · Herb.jl

HerbSearch.jl Documentation

HerbSearch.ContextSensitivePriorityEnumeratorType
mutable struct ContextSensitivePriorityEnumerator <: ExpressionIterator

Enumerates a context-free grammar starting at Symbol sym with respect to the grammar up to a given depth and a given size. The exploration is done using the given priority function for derivations, and the expand function for discovered nodes.

source
HerbSearch.ExpandFailureReasonType
@enum ExpandFailureReason limit_reached=1 already_complete=2

Representation of the different reasons why expanding a partial tree failed. Currently, there are two possible causes of the expansion failing:

  • limit_reached: The depth limit or the size limit of the partial tree would be violated by the expansion
  • already_complete: There is no hole left in the tree, so nothing can be expanded.
source
HerbSearch.GeneticSearchIteratorType
GeneticSearchIterator{FitnessFunction,CrossOverFunction,MutationFunction,SelectParentsFunction,EvaluationFunction} <: ExpressionIterator

Defines an ExpressionIterator using genetic search.

Consists of:

  • grammar::ContextSensitiveGrammar: the grammar to search over

  • examples::Vector{<:Example}: a collection of examples defining the specification

  • fitness::FitnessFunction: assigns a numerical value (fitness score) to each individual based on how closely it meets the desired objective

  • cross_over::CrossOverFunction: combines the program from two parent individuals to create one or more offspring individuals

  • mutation!::MutationFunction: mutates the program of an invididual

  • select_parents::SelectParentsFunction: selects two parents for the crossover

  • evaluation_function::EvaluationFunction: interpreter to evaluate the individual programs

  • start_symbol::Symbol: defines the start symbol from which the search should be started

  • population_size::Int64: number of inviduals in the population

  • mutation_probability::Float64: probability of mutation for each individual

  • maximum_initial_population_depth::Int64: maximum depth of trees when population is initialized

end

source
HerbSearch.PriorityQueueItemType
struct PriorityQueueItem

Represents an item in the priority enumerator priority queue. An item contains of:

  • tree: A partial AST
  • size: The size of the tree. This is a cached value which prevents having to traverse the entire tree each time the size is needed.
  • constraints: The local constraints that apply to this tree. These constraints are enforced each time the tree is modified.
source
HerbSearch.PropagateResultType
@enum PropagateResult tree_complete=1 tree_incomplete=2 tree_infeasible=3

Representation of the possible results of a constraint propagation. At the moment there are three possible outcomes:

  • tree_complete: The propagation was applied successfully and the tree does not contain any holes anymore. Thus no constraints can be applied anymore.
  • tree_incomplete: The propagation was applied successfully and the tree does contain more holes. Thus more constraints may be applied to further prune the respective domains.
  • tree_infeasible: The propagation was succesful, but there are holes with empty domains. Hence, the tree is now infeasible.
source
HerbSearch.StochasticSearchEnumeratorType
Base.@kwdef struct StochasticSearchEnumerator <: ExpressionIterator

A unified struct for the algorithms Metropolis Hastings, Very Large Scale Neighbourhood and Simulated Annealing. Each algorithm implements neighbourhood propose accept and temperature functions. Below the signiture of all this function is shown

Signatures


Returns a node location from the program that is the neighbourhood. It can also return other information using dict

neighbourhood(program::RuleNode, grammar::Grammar) -> (loc::NodeLocation, dict::Dict)

Proposes a list of programs using the location provided by neighbourhood and the dict.

propose(current_program, loc::NodeLocation, grammar::Grammar, max_depth::Int64, dict::Dict) -> Iter[RuleNode]

Based on the current program and possible cost and temperature it accepts the program or not. Usually we would always want to accept better programs but we might get stuck if we do so. That is why some implementations of the accept function accept with a probability costs that are worse. cost means how different are the outcomes of the program compared to the correct outcomes. The lower the cost the better the program performs on the examples. The cost is provided by the cost_function

accept(current_cost::Real, possible_cost::Real, temperature::Real) -> Bool

Returns the new temperature based on the previous temperature. Higher the temperature means that the algorithm will explore more.

temperature(previous_temperature::Real) -> Real

Returns the cost of the current program. It receives a list of tuples (expected, found) and gives back a cost.

cost_function(outcomes::Tuple{<:Number,<:Number}[]) -> Real

Fields

  • grammar::ContextSensitiveGrammar grammar that the algorithm uses
  • max_depth::Int64 = 5 maximum depth of the program to generate
  • examples::Vector{Example} example used to check the program
  • neighbourhood::Function
  • propose::Function
  • accept::Function
  • temperature::Function
  • cost_function::Function
  • start_symbol::Symbol the start symbol of the algorithm :Real or :Int
  • initial_temperature::Real = 1
  • evaluation_function::Function that evaluates the julia expressions

An iterator over all possible expressions of a grammar up to max_depth with start symbol sym.

source
Base.iterateMethod
Base.iterate(iter::ContextSensitivePriorityEnumerator, pq::DataStructures.PriorityQueue)

Describes the iteration for a given ContextSensitivePriorityEnumerator and a PriorityQueue over the grammar without enqueueing new items to the priority queue. Recursively returns the result for the priority queue.

source
Base.iterateMethod
Base.iterate(iter::ContextSensitivePriorityEnumerator)

Describes the iteration for a given ContextSensitivePriorityEnumerator over the grammar. The iteration constructs a PriorityQueue first and then prunes it propagating the active constraints. Recursively returns the result for the priority queue.

source
Base.iterateMethod
Base.iterate(iter::GeneticSearchIterator, current_state::GeneticIteratorState)

Iterates the search space using a genetic algorithm. Takes the iterator and the current state to mutate and crossover random inviduals. Returns the best program-so-far and the state of the iterator.

source
Base.iterateMethod
Base.iterate(iter::GeneticSearchIterator)

Iterates the search space using a genetic algorithm. First generates a population sampling random programs. Returns the best program-so-far, and the state of the iterator.

source
Base.iterateMethod
Base.iterate(iter::StochasticSearchEnumerator, current_state::IteratorState)

The algorithm that constructs the iterator of StochasticSearchEnumerator. It has the following structure:

  1. get a random node location -> location,dict = neighbourhood(current_program)
  2. call propose on the current program getting a list of possbile replacements in the node location
  3. iterate through all the possible replacements and perform the replacement in the current program
    1. accept the new program by modifying the next_program or reject the new program
  4. return the new next_program
source
Base.randFunction
rand(::Type{RuleNode}, grammar::Grammar, typ::Symbol, dmap::AbstractVector{Int}, max_depth::Int=10)

Generates a random RuleNode, i.e. an expression tree, of root type typ and maximum depth max_depth guided by a depth map dmap if possible.

source
Base.randFunction
rand(::Type{RuleNode}, grammar::Grammar, max_depth::Int=10)

Generates a random RuleNode of arbitrary type and maximum depth max_depth.

source
Base.randFunction
rand(::Type{RuleNode}, grammar::Grammar, typ::Symbol, max_depth::Int=10)

Generates a random RuleNode of return type typ and maximum depth max_depth.

source
HerbSearch._expandMethod
_expand(node::Hole, grammar::ContextSensitiveGrammar, ::Int, max_holes::Int, context::GrammarContext, hole_heuristic::Function, derivation_heuristic::Function)::Union{ExpandFailureReason, Vector{TreeConstraints}}

Expands a given hole that was found in _expand using the given derivation heuristic. Returns the list of discovered nodes in that order and with their respective constraints.

source
HerbSearch._expandMethod
_expand(root::RuleNode, grammar::ContextSensitiveGrammar, max_depth::Int, max_holes::Int, context::GrammarContext, hole_heuristic::Function, derivation_heuristic::Function)::Union{ExpandFailureReason, Vector{TreeConstraints}}

Recursive expand function used in multiple enumeration techniques. Expands one hole/undefined leaf of the given RuleNode tree found using the given hole heuristic. If the expansion was successful, returns a list of new trees and a list of lists of hole locations, corresponding to the holes of each newly expanded tree. Returns nothing if tree is already complete (i.e. contains no holes). Returns an empty list if the tree is partial (i.e. contains holes), but they could not be expanded because of the depth limit.

source
HerbSearch._find_next_complete_treeMethod
_find_next_complete_tree(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, priority_function::Function, expand_function::Function, pq::PriorityQueue)::Union{Tuple{RuleNode, PriorityQueue}, Nothing}

Takes a priority queue and returns the smallest AST from the grammar it can obtain from the queue or by (repeatedly) expanding trees that are in the queue. Returns nothing if there are no trees left within the depth limit.

source
HerbSearch.best_acceptMethod
best_accept(current_cost::Real, next_cost::Real, temperature)

Returns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns false.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the temperature; not used.
source
HerbSearch.calculate_costMethod
calculate_cost(program::RuleNode, cost_function::Function, examples::AbstractVector{Example}, grammar::Grammar, evaluation_function::Function)

Returns the cost of the program using the examples and the cost_function. It first convert the program to an expression and evaluates it on all the examples using HerbInterpret.evaluate_program.

source
HerbSearch.const_temperatureMethod
const_temperature(current_temperature)

Returns the temperature unchanged. This function is used by Metropolis Hastings and Very Large Neighbourhood Search algorithms.

Arguments

  • current_temperature::Real: the current temperature of the search.
source
HerbSearch.constructNeighbourhoodMethod
constructNeighbourhood(current_program::RuleNode, grammar::Grammar)

The neighbourhood node location is chosen at random. The dictionary is nothing.

Arguments

  • current_program::RuleNode: the current program.
  • grammar::Grammar: the grammar.
source
HerbSearch.constructNeighbourhoodRuleSubsetMethod
constructNeighbourhoodRuleSubset(current_program::RuleNode, grammar::Grammar)

The neighbourhood node location is chosen at random. The dictionary is contains one entry with key "rule_subset" and value of type Vector{Any} being a random subset of grammar rules.

Arguments

  • current_program::RuleNode: the current program.
  • grammar::Grammar: the grammar.
source
HerbSearch.count_expressionsMethod
count_expressions(iter::ExpressionIterator)

Counts and returns the number of possible expressions in the expression iterator. The Iterator is not modified.

source
HerbSearch.count_expressionsMethod
count_expressions(grammar::Grammar, max_depth::Int, max_size::Int, sym::Symbol)

Counts and returns the number of possible expressions of a grammar up to max_depth with start symbol sym.

source
HerbSearch.crossover_swap_children_1Method
crossover_swap_children_1(parent1::RuleNode, parent2::RuleNode)

Performs a random crossover of two parents of type RuleNode. The subprograms are swapped and only one altered parent program is returned.

source
HerbSearch.crossover_swap_children_2Method
crossover_swap_children_2(parent1::RuleNode, parent2::RuleNode)

Performs a random crossover of two parents of type RuleNode. The subprograms are swapped and both altered parent programs are returned.

source
HerbSearch.decreasing_temperatureMethod
decreasing_temperature(percentage::Real)

Returns a function that produces a temperature decreased by percentage%. This function is used by the Simmulated Annealing algorithm.

Arguments

  • percentage::Real: the percentage to decrease the temperature by.
source
HerbSearch.default_error_functionMethod
default_error_function(old_error, output, expected_output)

Default error function for search_best.

- old_error         - The existing total error
-- output            - The actual output of the evaluator
-- expected_output   - The expected output for the example

The default function returns 0 if the outputs match and 1 otherwise.

source
HerbSearch.default_fitnessMethod
default_fitness(program, results)

Defines the default fitness function taking the program and its results. Results are a vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}. As we are looking for individuals with the highest fitness function, the error is inverted.

source
HerbSearch.enumerate_neighbours_proposeMethod
enumerate_neighbours_propose(enumeration_depth::Int64)

The return function is a function that produces a list with all the subprograms with depth at most enumeration_depth.

Arguments

  • enumeration_depth::Int64: the maximum enumeration depth.
source
HerbSearch.get_best_programMethod
get_best_program(population::Array{RuleNode}, iter:: GeneticSearchIterator)::RuleNode

Returns the best program within the population with respect to the fitness function.

source
HerbSearch.get_bfs_enumeratorFunction
get_bfs_enumerator(grammar::ContextFreeGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator

Returns a breadth-first search enumerator given a ContextFreeGrammar. Returns trees in the grammar in increasing order of size.

source
HerbSearch.get_bfs_enumeratorFunction
get_bfs_enumerator(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator

Returns a breadth-first search enumerator given a ContextSensitiveGrammar. Returns trees in the grammar in increasing order of size.

source
HerbSearch.get_dfs_enumeratorFunction
get_dfs_enumerator(grammar::ContextFreeGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator

Returns a depth-first search enumerator given a ContextFreeGrammar. Returns trees in the grammar in decreasing order of size.

source
HerbSearch.get_dfs_enumeratorFunction
get_dfs_enumerator(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator

Returns a depth-first search enumerator given a ContextSensitiveGrammar. Returns trees in the grammar in decreasing order of size.

source
HerbSearch.get_genetic_enumeratorMethod
get_genetic_enumerator(examples; fitness_function = HerbSearch.default_fitness, initial_population_size = 10, maximum_initial_population_depth = 3, mutation_probability = 0.1, cross_over = HerbSearch.crossover_swap_children_2, select_parents = HerbSearch.select_fitness_proportional_parents, evaluation_function::Function=HerbInterpret.test_with_input)

Returns a GeneticSearchIterator given a grammar. The iterator is fitted against the examples provided evaluated using the fitness function. All other arguments are hyperparameters for the genetic search procedure.

source
HerbSearch.get_mh_enumeratorFunction
get_mh_enumerator(examples::AbstractArray{<:Example}, cost_function::Function, evaluation_function::Function=HerbInterpret.test_with_input)

Returns an enumerator that runs according to the Metropolis Hastings algorithm.

  • examples : array of examples
  • cost_function : cost function to evaluate the programs proposed
  • evaluation_function : evaluation function that evaluates the program generated and produces an output

The propose function is randomfillpropose and the accept function is probabilistic. The temperature value of the algorithm remains constant over time.

source
HerbSearch.get_most_likely_first_enumeratorFunction
get_most_likely_first_enumerator(grammar::ContextFreeGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator

Returns an enumerator that enumerates expressions in the grammar in decreasing order of probability. Only use this function with probabilistic grammars.

source
HerbSearch.get_most_likely_first_enumeratorFunction
get_most_likely_first_enumerator(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator

Returns an enumerator that enumerates expressions in the grammar in decreasing order of probability. Only use this function with probabilistic grammars.

source
HerbSearch.get_sa_enumeratorFunction
get_sa_enumerator(examples, cost_function, initial_temperature=1, temperature_decreasing_factor = 0.99, evaluation_function::Function=HerbInterpret.test_with_input)

Returns an enumerator that runs according to the Very Large Scale Neighbourhood Search algorithm.

  • examples : array of examples
  • cost_function : cost function to evaluate the programs proposed
  • initial_temperature : the starting temperature of the algorithm
  • temperature_decreasing_factor : the decreasing factor of the temperature of the time
  • evaluation_function : evaluation function that evaluates the program generated and produces an output

The propose function is random_fill_propose (the same as for Metropolis Hastings). The accept function is probabilistic but takes into account the tempeerature too.

source
HerbSearch.get_vlsn_enumeratorFunction
get_vlsn_enumerator(examples, cost_function, enumeration_depth = 2, evaluation_function::Function=HerbInterpret.test_with_input)

Returns an enumerator that runs according to the Very Large Scale Neighbourhood Search algorithm.

  • examples : array of examples
  • cost_function : cost function to evaluate the programs proposed
  • enumeration_depth : the enumeration depth to search for a best program at a time
  • evaluation_function : evaluation function that evaluates the program generated and produces an output

The propose function consists of all possible programs of the given enumeration_depth. The accept function accepts the program with the lowest cost according to the cost_function. The temperature value of the algorithm remains constant over time.

source
HerbSearch.heuristic_leftmostMethod
heuristic_leftmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes, where the left-most hole always gets considered first. Returns a HoleReference once a hole is found. This is the default option for enumerators.

source
HerbSearch.heuristic_randomMethod
heuristic_random(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes, where random holes get chosen randomly using random exploration. Returns a HoleReference once a hole is found.

source
HerbSearch.heuristic_rightmostMethod
heuristic_rightmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes, where the right-most hole always gets considered first. Returns a HoleReference once a hole is found.

source
HerbSearch.heuristic_smallest_domainMethod
heuristic_smallest_domain(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over all available holes in the unfinished AST, by considering the size of their respective domains. A domain here describes the number of possible derivations with respect to the constraints. Returns a HoleReference once a hole is found.

source
HerbSearch.mean_squared_errorMethod
mean_squared_error(results::AbstractVector{Tuple{<:Number,<:Number}})

Returns the mean squared error of results.

Arguments

  • results<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.
source
HerbSearch.misclassificationMethod
misclassification(results::AbstractVector{Tuple{<:Number,<:Number}})

Returns the amount of misclassified examples, i.e. how many tuples with non-matching entries are there in results.

Arguments

  • results<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.
source
HerbSearch.most_likely_priority_functionMethod
most_likely_priority_function(g::ContextSensitiveGrammar, tree::AbstractRuleNode, ::Union{Real, Tuple{Vararg{Real}}})

Calculates logit for all possible derivations for a node in a tree and returns them.

source
HerbSearch.mse_error_functionMethod
mse_error_function(old_error, output, expected_output)

Mean squared error function for search_best.

- old_error         - The existing total error
-- output            - The actual output of the evaluator
-- expected_output   - The expected output for the example

The function build the mean squared error from output and expected_output`.

source
HerbSearch.mutate_random!Function
mutate_random!(program::RuleNode, grammar::Grammar, max_depth::Int64 = 2)

Mutates the given program by inserting a randomly generated sub-program at a random location.

source
HerbSearch.probabilistic_acceptMethod
probabilistic_accept(current_cost::Real, next_cost::Real, temperature::Real)

Probabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program. Returns True if the new program is accepted, False otherwise.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the temperature; not used.
source
HerbSearch.probabilistic_accept_with_temperatureMethod
probabilistic_accept_with_temperature(current_cost::Real, next_cost::Real, temperature::Real)

Returns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns true with the probability equal to:

\[1 / (1 + exp(delta / temperature))\]

In any other case, returns false.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the temperature of the search.
source
HerbSearch.probabilistic_accept_with_temperature_fractionMethod
probabilistic_accept_with_temperature_fraction(current_cost::Real, program_to_consider_cost::Real, temperature::Real)

Probabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program multiplied by the temperature. Returns True if the new program is accepted, False otherwise.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the current temperature
source
HerbSearch.propagate_constraintsFunction
function propagate_constraints(root::AbstractRuleNode, grammar::ContextSensitiveGrammar, local_constraints::Set{LocalConstraint}, max_holes::Int, filled_hole::Union{HoleReference, Nothing}=nothing)::Tuple{PropagateResult, Set{LocalConstraint}}

Propagates a set of local constraints recursively to all children of a given root node. As propagate_constraints gets often called when a hole was just filled, filled_hole helps keeping track to propagate the constraints to relevant nodes, e.g. children of filled_hole. max_holes makes sure that max_size of Base.iterate is not violated. The function returns the PropagateResult and the set of relevant LocalConstraints.

source
HerbSearch.random_fill_proposeMethod
random_fill_propose(current_program, neighbourhood_node_loc, grammar, max_depth, dict)

Returns a list with only one proposed, completely random, subprogram.

Arguments

  • current_program::RuleNode: the current program.
  • neighbourhood_node_loc::NodeLoc: the location of the program to replace.
  • grammar::Grammar: the grammar used to create programs.
  • max_depth::Int: the maximum depth of the resulting programs.
  • dmap::AbstractVector{Int} : the minimum possible depth to reach for each rule
  • dict::Dict{String, Any}: the dictionary with additional arguments; not used.
source
HerbSearch.searchMethod
search(g::Grammar, problem::Problem, start::Symbol; evaluator::Function=test_with_input, enumerator::Function=get_bfs_enumerator, max_depth::Union{Int, Nothing}=nothing, max_size::Union{Int, Nothing}=nothing, max_time::Union{Int, Nothing}=nothing, max_enumerations::Union{Int, Nothing}=nothing, allow_evaluation_errors::Bool=false, mod::Module=Main)::Union{Any, Nothing}

Searches for a program by calling search_rulenode starting from Symbol start guided by enumerator and Grammar trying to satisfy the higher-order constraints in form of input/output examples defined in the Problem. This is the heart of the Herb's search for satisfying programs. Returns the found program when the evaluation calculated using evaluator is successful.

source
HerbSearch.search_bestMethod
search_best(g::Grammar, problem::Problem, start::Symbol; evaluator::Function=test_with_input, enumerator::Function=get_bfs_enumerator, error_function::Function=default_error_function, max_depth::Union{Int, Nothing}=nothing, max_size::Union{Int, Nothing}=nothing, max_time::Union{Int, Nothing}=nothing, max_enumerations::Union{Int, Nothing}=nothing, allow_evaluation_errors::Bool=false, mod::Module=Main)::Tuple{Any, Real}

Searches the grammar for the program that satisfies the maximum number of examples in the problem. The evaluator should be a function that takes a SymbolTable, expression and a dictionary with input variable assignments and returns the output of the expression.

- g                 - The grammar that defines the search space
-- problem           - The problem definition with IO examples
-- start             - The start symbol in the grammar
-- evaluator         - The evaluation function. Takes a SymbolTable, expression and a dictionary with 
-                      input variable assignments and returns the output of the expression.
-- enumerator        - A constructor for the enumerator that should be used in the search
-- error_function    - The error function. Takes the existing total error, the actual output of the evaluator 
-                      and the expected value for the example.
-- max_depth         - The maximum depth of the search
-- max_time          - The maximum time allowed for the search in seconds
-- max_enumerations  - The maximum number of programs to enumerate and test
-- allow_evaluation_errors - Whether the search should crash if an exception is thrown in the evaluation
-- mod               - A module containing definitions for the functions in the grammar that do not exist in Main

Returns a tuple with the best found program so far and the error. Can be considerably slower than search due to having to evaluate each expression on each example.

source
HerbSearch.search_rulenodeMethod
search_rulenode(g::Grammar, problem::Problem, start::Symbol; evaluator::Function=test_with_input, enumerator::Function=get_bfs_enumerator, max_depth::Union{Int, Nothing}=nothing, max_size::Union{Int, Nothing}=nothing, max_time::Union{Int, Nothing}=nothing, max_enumerations::Union{Int, Nothing}=nothing, allow_evaluation_errors::Bool=false, mod::Module=Main)::Union{Tuple{RuleNode, Any}, Nothing}

Searches the grammar for the program that satisfies the maximum number of examples in the problem.

    - g                 - The grammar that defines the search space
-    - problem           - The problem definition with IO examples
-    - start             - The start symbol in the grammar
-    - evaluator         - The evaluation function. Takes a SymbolTable, expression and a dictionary with 
-                          input variable assignments and returns the output of the expression.
-    - enumerator        - A constructor for the enumerator that should be used in the search
-    - max_depth         - The maximum depth of the search
-    - max_size          - The maximum number of nodes for ASTs in the search
-    - max_time          - The maximum time allowed for the search in seconds
-    - max_enumerations  - The maximum number of programs to enumerate and test'
-    - allow_evaluation_errors - Whether the search should crash if an exception is thrown in the evaluation
-    - mod               - A module containing definitions for the functions in the grammar that do not exist in Main
-Returns a tuple of the rulenode and the expression of the solution program once it has been found, 
-or nothing otherwise.
source
HerbSearch.select_chromosomeMethod
select_chromosome(population::Array{RuleNode}, fitness_array::Array{<:Real})::RuleNode

Selects a chromosome (individual) from the population based on a fitness array. The function uses a fitness-proportionate selection strategy, often referred to as "roulette wheel" selection. Assumes fitness_array to be normalized already.

source
HerbSearch.select_fitness_proportional_parentsMethod
select_fitness_proportional_parents(population::Array{RuleNode}, fitness_array::Array{<:Real})::Tuple{RuleNode,RuleNode}

Selects two parent chromosomes (individuals) from a population based on fitness-proportionate selection. The selected parents can be used for genetic crossover in the next steps of the algorithm.

source
StatsBase.sampleFunction
sample(::Type{NodeLoc}, root::RuleNode, maxdepth::Int=typemax(Int))

Uniformly selects a random node in the tree no deeper than maxdepth using reservoir sampling. Returns a NodeLoc that specifies the location using its parent so that the subtree can be replaced.

source
StatsBase.sampleFunction
sample(::Type{NodeLoc}, root::RuleNode, typ::Symbol, grammar::Grammar)

Uniformly selects a random node in the tree of a given type, specified using its parent such that the subtree can be replaced. Returns a NodeLoc.

source
StatsBase.sampleFunction
sample(root::RuleNode, typ::Symbol, grammar::Grammar, maxdepth::Int=typemax(Int))

Uniformly samples a random node from the tree limited to maxdepth.

source
StatsBase.sampleFunction
sample(root::RuleNode, typ::Symbol, grammar::Grammar,
-                      maxdepth::Int=typemax(Int))

Uniformly selects a random node of the given return type typ limited by maxdepth.

source

The HerbSearch package takes care of all operations related to searching for the desired program. This includes

  • the functionality to sample a certain program given a grammar,
  • the implementation of several heuristic functions,
  • searching for a program that satisfies the specification, and
  • implementations of several search algorithms in terms of how they enumerate the search space
    • Breadth-First Search
    • Depth-First Search
    • Metropolis Hastings
    • Very Large Scale Neighbourhood Search
    • Simulated Annealing
    • Genetic Search

Index

+HerbSearch.jl · Herb.jl

HerbSearch.jl Documentation

HerbSearch.BFSIteratorType
@programiterator BFSIterator() <: TopDownIterator

Returns a breadth-first iterator given a grammar and a starting symbol. Returns trees in the grammar in increasing order of size. Inherits all stop-criteria from TopDownIterator.

source
HerbSearch.DFSIteratorType
@programiterator DFSIterator() <: TopDownIterator

Returns a depth-first search enumerator given a grammar and a starting symbol. Returns trees in the grammar in decreasing order of size. Inherits all stop-criteria from TopDownIterator.

source
HerbSearch.ExpandFailureReasonType
@enum ExpandFailureReason limit_reached=1 already_complete=2

Representation of the different reasons why expanding a partial tree failed. Currently, there are two possible causes of the expansion failing:

  • limit_reached: The depth limit or the size limit of the partial tree would be violated by the expansion
  • already_complete: There is no hole left in the tree, so nothing can be expanded.
source
HerbSearch.GeneticSearchIteratorType
GeneticSearchIterator{FitnessFunction,CrossOverFunction,MutationFunction,SelectParentsFunction,EvaluationFunction} <: ProgramIterator

Defines an ProgramIterator using genetic search.

Consists of:

  • examples::Vector{<:IOExample}: a collection of examples defining the specification

  • evaluation_function::EvaluationFunction: interpreter to evaluate the individual programs

  • population_size::Int64: number of inviduals in the population

  • mutation_probability::Float64: probability of mutation for each individual

  • maximum_initial_population_depth::Int64: maximum depth of trees when population is initialized

end

source
HerbSearch.MHSearchIteratorType
MHSearchIterator(examples::AbstractArray{<:IOExample}, cost_function::Function, evaluation_function::Function=HerbInterpret.execute_on_input)

Returns an enumerator that runs according to the Metropolis Hastings algorithm.

  • spec : array of examples
  • cost_function : cost function to evaluate the programs proposed
  • evaluation_function : evaluation function that evaluates the program generated and produces an output

The propose function is randomfillpropose and the accept function is probabilistic. The temperature value of the algorithm remains constant over time.

source
HerbSearch.MLFSIteratorType
@programiterator MLFSIterator() <: TopDownIterator

Iterator that enumerates expressions in the grammar in decreasing order of probability (Only use this iterator with probabilistic grammars). Inherits all stop-criteria from TopDownIterator.

source
HerbSearch.PriorityQueueItemType
struct PriorityQueueItem

Represents an item in the priority enumerator priority queue. An item contains of:

  • tree: A partial AST
  • size: The size of the tree. This is a cached value which prevents having to traverse the entire tree each time the size is needed.
  • constraints: The local constraints that apply to this tree. These constraints are enforced each time the tree is modified.
source
HerbSearch.ProgramIteratorType
abstract type ProgramIterator

Generic iterator for all possible search strategies. All iterators are expected to have the following fields:

  • grammar::ContextSensitiveGrammar: the grammar to search over
  • sym::Symbol: defines the start symbol from which the search should be started
  • max_depth::Int: maximum depth of program trees
  • max_size::Int: maximum number of AbstractRuleNodes of program trees
  • max_time::Int: maximum time the iterator may take
  • max_enumerations::Int: maximum number of enumerations
source
HerbSearch.PropagateResultType
@enum PropagateResult tree_complete=1 tree_incomplete=2 tree_infeasible=3

Representation of the possible results of a constraint propagation. At the moment there are three possible outcomes:

  • tree_complete: The propagation was applied successfully and the tree does not contain any holes anymore. Thus no constraints can be applied anymore.
  • tree_incomplete: The propagation was applied successfully and the tree does contain more holes. Thus more constraints may be applied to further prune the respective domains.
  • tree_infeasible: The propagation was succesful, but there are holes with empty domains. Hence, the tree is now infeasible.
source
HerbSearch.SASearchIteratorType
SASearchIterator(spec, cost_function, initial_temperature=1, temperature_decreasing_factor = 0.99, evaluation_function::Function=HerbInterpret.execute_on_input)

Returns an enumerator that runs according to the Simulated Annealing Search algorithm.

  • spec : array of examples
  • cost_function : cost function to evaluate the programs proposed
  • initial_temperature : the starting temperature of the algorithm
  • temperature_decreasing_factor : the decreasing factor of the temperature of the time
  • evaluation_function : evaluation function that evaluates the program generated and produces an output

The propose function is random_fill_propose (the same as for Metropolis Hastings). The accept function is probabilistic but takes into account the tempeerature too.

source
HerbSearch.StochasticSearchIteratorType
abstract type StochasticSearchIterator <: ProgramIterator

A unified abstract type for the algorithms Metropolis Hastings, Very Large Scale Neighbourhood and Simulated Annealing. Each algorithm implements neighbourhood, propose, accept and temperature functions. Below the signatures of each function is shown.

Signatures


Returns a node location from the program that is the neighbourhood. It can also return other information using dict

neighbourhood(iter::T, current_program::RuleNode) where T <: StochasticSearchIterator -> (loc::NodeLocation, dict::Dict)

Proposes a list of programs using the location provided by neighbourhood and the dict.

propose(iter::T, current_program::RuleNode, neighbourhood_node_loc::NodeLoc, dmap::AbstractVector{Int}, dict::Union{Nothing,Dict{String,Any}}) where T <: StochasticSearchIterator -> Iter[RuleNode]

Based on the current program and possible cost and temperature it accepts the program or not. Usually we would always want to accept better programs but we might get stuck if we do so. That is why some implementations of the accept function accept with a probability costs that are worse. cost means how different are the outcomes of the program compared to the correct outcomes. The lower the cost the better the program performs on the examples. The cost is provided by the cost_function

accept(::T, currentcost::Real, nextcost::Real, temperature::Real) where T <: StochasticSearchIterator -> Bool

Returns the new temperature based on the previous temperature. Higher the temperature means that the algorithm will explore more.

temperature(::T, current_temperature::Real) where T <: StochasticSearchIterator -> Real

Returns the cost of the current program. It receives a list of tuples (expected, found) and gives back a cost.

cost_function(outcomes::Tuple{<:Number,<:Number}[]) -> Real

Fields

  • grammar::ContextSensitiveGrammar grammar that the algorithm uses

  • sym::Symbol the start symbol of the algorithm :Real or :Int

  • examples::Vector{IOExample} example used to check the program

  • cost_function::Function

  • initial_temperature::Real = 1

  • evaluation_function::Function that evaluates the julia expressions

An iterator over all possible expressions of a grammar up to maxdepth with start symbol sym. Also inherits all stop criteria like `maxdepthfromProgramIterator`.

source
HerbSearch.SynthResultType
@enum SynthResult optimal_program=1 suboptimal_program=2

Representation of the possible results of the synth procedure. At the moment there are two possible outcomes:

  • optimal_program: The synthesized program satisfies the entire program specification.
  • suboptimal_program: The synthesized program does not satisfy the entire program specification, but got the best score from the evaluator.
source
HerbSearch.TopDownIteratorType
mutable struct TopDownIterator <: ProgramIterator

Enumerates a context-free grammar starting at Symbol sym with respect to the grammar up to a given depth and a given size. The exploration is done using the given priority function for derivations, and the expand function for discovered nodes. Concrete iterators may overload the following methods:

  • priority_function
  • derivation_heuristic
  • hole_heuristic
source
HerbSearch.VLSNSearchIteratorType
VLSNSearchIterator(spec, cost_function, enumeration_depth = 2, evaluation_function::Function=HerbInterpret.execute_on_input) = StochasticSearchIterator(

Returns an iterator that runs according to the Very Large Scale Neighbourhood Search algorithm.

  • spec : array of examples
  • cost_function : cost function to evaluate the programs proposed
  • vlsn_neighbourhood_depth : the enumeration depth to search for a best program at a time
  • evaluation_function : evaluation function that evaluates the program generated and produces an output

The propose function consists of all possible programs of the given enumeration_depth. The accept function accepts the program with the lowest cost according to the cost_function. The temperature value of the algorithm remains constant over time.

source
HerbSearch.@programiteratorMacro
@programiterator

Canonical way of creating a program iterator. The macro automatically declares the expected fields listed in the ProgramIterator documentation. Syntax accepted by the macro is as follows (anything enclosed in square brackets is optional): @programiterator [mutable] <IteratorName>( <arg₁>, ..., <argₙ> ) [<: <SupertypeIterator>] Note that the macro emits an assertion that the SupertypeIterator is a subtype of ProgramIterator which otherwise throws an ArgumentError. If no supertype is given, the new iterator extends ProgramIterator directly. Each <argᵢ> may be (almost) any expression valid in a struct declaration, and they must be comma separated. One known exception is that an inner constructor must always be given using the extended function <name>(...) ... end syntax. The mutable keyword determines whether the declared struct is mutable.

source
Base.iterateMethod
Base.iterate(iter::GeneticSearchIterator, current_state::GeneticIteratorState)

Iterates the search space using a genetic algorithm. Takes the iterator and the current state to mutate and crossover random inviduals. Returns the best program-so-far and the state of the iterator.

source
Base.iterateMethod
Base.iterate(iter::GeneticSearchIterator)

Iterates the search space using a genetic algorithm. First generates a population sampling random programs. Returns the best program-so-far, and the state of the iterator.

source
Base.iterateMethod
Base.iterate(iter::StochasticSearchIterator, current_state::IteratorState)

The algorithm that constructs the iterator of StochasticSearchIterator. It has the following structure:

  1. get a random node location -> location,dict = neighbourhood(current_program)
  2. call propose on the current program getting a list of possbile replacements in the node location
  3. iterate through all the possible replacements and perform the replacement in the current program
  4. accept the new program by modifying the next_program or reject the new program
  5. return the new next_program
source
Base.iterateMethod
Base.iterate(iter::TopDownIterator, pq::DataStructures.PriorityQueue)

Describes the iteration for a given TopDownIterator and a PriorityQueue over the grammar without enqueueing new items to the priority queue. Recursively returns the result for the priority queue.

source
Base.iterateMethod
Base.iterate(iter::TopDownIterator)

Describes the iteration for a given TopDownIterator over the grammar. The iteration constructs a PriorityQueue first and then prunes it propagating the active constraints. Recursively returns the result for the priority queue.

source
Base.randFunction
rand(::Type{RuleNode}, grammar::AbstractGrammar, typ::Symbol, max_depth::Int=10)

Generates a random RuleNode of return type typ and maximum depth max_depth.

source
Base.randFunction
rand(::Type{RuleNode}, grammar::AbstractGrammar, typ::Symbol, dmap::AbstractVector{Int}, max_depth::Int=10)

Generates a random RuleNode, i.e. an expression tree, of root type typ and maximum depth max_depth guided by a depth map dmap if possible.

source
Base.randFunction
rand(::Type{RuleNode}, grammar::AbstractGrammar, max_depth::Int=10)

Generates a random RuleNode of arbitrary type and maximum depth max_depth.

source
HerbSearch._calculate_costMethod
_calculate_cost(program::RuleNode, cost_function::Function, spec::AbstractVector{IOExample}, grammar::AbstractGrammar, evaluation_function::Function)

Returns the cost of the program using the examples and the cost_function. It first convert the program to an expression and evaluates it on all the examples.

source
HerbSearch._expandMethod
_expand(node::Hole, grammar::ContextSensitiveGrammar, ::Int, max_holes::Int, context::GrammarContext, iter::TopDownIterator)::Union{ExpandFailureReason, Vector{TreeConstraints}}

Expands a given hole that was found in _expand using the given derivation heuristic. Returns the list of discovered nodes in that order and with their respective constraints.

source
HerbSearch._expandMethod
_expand(root::RuleNode, grammar::ContextSensitiveGrammar, max_depth::Int, max_holes::Int, context::GrammarContext, iter::TopDownIterator)::Union{ExpandFailureReason, Vector{TreeConstraints}}

Recursive expand function used in multiple enumeration techniques. Expands one hole/undefined leaf of the given RuleNode tree found using the given hole heuristic. If the expansion was successful, returns a list of new trees and a list of lists of hole locations, corresponding to the holes of each newly expanded tree. Returns nothing if tree is already complete (i.e. contains no holes). Returns an empty list if the tree is partial (i.e. contains holes), but they could not be expanded because of the depth limit.

source
HerbSearch._find_next_complete_treeMethod
_find_next_complete_tree(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, pq::PriorityQueue, iter::TopDownIterator)::Union{Tuple{RuleNode, PriorityQueue}, Nothing}

Takes a priority queue and returns the smallest AST from the grammar it can obtain from the queue or by (repeatedly) expanding trees that are in the queue. Returns nothing if there are no trees left within the depth limit.

source
HerbSearch.best_acceptMethod
best_accept(current_cost::Real, next_cost::Real, temperature::Real)

Returns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns false.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the temperature; not used.
source
HerbSearch.const_temperatureMethod
const_temperature(current_temperature::Real)

Returns the temperature unchanged. This function is used by Metropolis Hastings and Very Large Neighbourhood Search algorithms.

Arguments

  • current_temperature::Real: the current temperature of the search.
source
HerbSearch.constructNeighbourhoodMethod
constructNeighbourhood(current_program::RuleNode, grammar::AbstractGrammar)

The neighbourhood node location is chosen at random. The dictionary is nothing.

Arguments

  • current_program::RuleNode: the current program.
  • grammar::AbstractGrammar: the grammar.
source
HerbSearch.constructNeighbourhoodRuleSubsetMethod
constructNeighbourhoodRuleSubset(current_program::RuleNode, grammar::AbstractGrammar)

The neighbourhood node location is chosen at random. The dictionary is contains one entry with key "rule_subset" and value of type Vector{Any} being a random subset of grammar rules.

Arguments

  • current_program::RuleNode: the current program.
  • grammar::AbstractGrammar: the grammar.
source
HerbSearch.count_expressionsMethod
count_expressions(grammar::AbstractGrammar, max_depth::Int, max_size::Int, sym::Symbol)

Counts and returns the number of possible expressions of a grammar up to max_depth with start symbol sym.

source
HerbSearch.count_expressionsMethod
count_expressions(iter::ProgramIterator)

Counts and returns the number of possible expressions in the expression iterator. The Iterator is not modified.

source
HerbSearch.cross_overMethod
cross_over(::GeneticSearchIterator, parent_1::RuleNode, parent_2::RuleNode)

Combines the program from two parent individuals to create one or more offspring individuals.

source
HerbSearch.crossover_swap_children_1Method
crossover_swap_children_1(parent_1::RuleNode, parent_2::RuleNode)

Performs a random crossover of two parents of type RuleNode. The subprograms are swapped and only one altered parent program is returned.

source
HerbSearch.crossover_swap_children_2Method
crossover_swap_children_2(parent_1::RuleNode, parent_2::RuleNode)

Performs a random crossover of two parents of type RuleNode. The subprograms are swapped and both altered parent programs are returned.

source
HerbSearch.decreasing_temperatureMethod
decreasing_temperature(percentage::Real)

Returns a function that produces a temperature decreased by percentage%. This function is used by the Simmulated Annealing algorithm.

Arguments

  • percentage::Real: the percentage to decrease the temperature by.
source
HerbSearch.default_fitnessMethod
default_fitness(program, results)

Defines the default fitness function taking the program and its results. Results are a vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}. As we are looking for individuals with the highest fitness function, the error is inverted.

source
HerbSearch.derivation_heuristicMethod
derivation_heuristic(::TopDownIterator, nodes::Vector{RuleNode}, ::GrammarContext)::Vector{AbstractRuleNode}

Returns an ordered sublist of nodes, based on which ones are most promising to fill the hole at the given context.

  • nodes::Vector{RuleNode}: a list of nodes the hole can be filled with
  • context::GrammarContext: holds the location of the to be filled hole
source
HerbSearch.enumerate_neighbours_proposeMethod
enumerate_neighbours_propose(enumeration_depth::Int64)

The return function is a function that produces a list with all the subprograms with depth at most enumeration_depth.

Arguments

  • enumeration_depth::Int64: the maximum enumeration depth.
source
HerbSearch.evaluateMethod
evaluate(problem::Problem{Vector{IOExample}}, expr::Any, tab::SymbolTable; allow_evaluation_errors::Bool=false)

Evaluate the expression on the examples.

Optional parameters:

- `shortcircuit` - Whether to stop evaluating after finding single example fails, to speed up the [synth](@ref) procedure. If true, the returned score is an underapproximation of the actual score.
+- `allow_evaluation_errors` - Whether the search should continue if an exception is thrown in the evaluation or throw the error

Returns a score in the interval [0, 1]

source
HerbSearch.extractnameMethod
extractname(ex)

Extracts the name of a field declaration, otherwise throws an ArgumentError. A field declaration is of the form <name>[::<type>]

source
HerbSearch.fitnessMethod
fitness(::GeneticSearchIterator, program, results)

Assigns a numerical value (fitness score) to each individual based on how closely it meets the desired objective.

source
HerbSearch.get_best_programMethod
get_best_program(population::Array{RuleNode}, iter::GeneticSearchIterator)::RuleNode

Returns the best program within the population with respect to the fitness function.

source
HerbSearch.heuristic_leftmostMethod
heuristic_leftmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes, where the left-most hole always gets considered first. Returns a HoleReference once a hole is found. This is the default option for enumerators.

source
HerbSearch.heuristic_randomMethod
heuristic_random(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes, where random holes get chosen randomly using random exploration. Returns a HoleReference once a hole is found.

source
HerbSearch.heuristic_rightmostMethod
heuristic_rightmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes, where the right-most hole always gets considered first. Returns a HoleReference once a hole is found.

source
HerbSearch.heuristic_smallest_domainMethod
heuristic_smallest_domain(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over all available holes in the unfinished AST, by considering the size of their respective domains. A domain here describes the number of possible derivations with respect to the constraints. Returns a HoleReference once a hole is found.

source
HerbSearch.hole_heuristicMethod
hole_heuristic(::TopDownIterator, node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}

Defines a heuristic over holes. Returns a HoleReference once a hole is found.

source
HerbSearch.mean_squared_errorMethod
mean_squared_error(results::AbstractVector{Tuple{<:Number,<:Number}})

Returns the mean squared error of results.

Arguments

  • results<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.
source
HerbSearch.misclassificationMethod
misclassification(results::AbstractVector{Tuple{<:Number,<:Number}})

Returns the amount of misclassified examples, i.e. how many tuples with non-matching entries are there in results.

Arguments

  • results<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.
source
HerbSearch.mutate!Function
mutate!(::GeneticSearchIterator, program::RuleNode, grammar::AbstractGrammar, max_depth::Int = 2)

Mutates the program of an invididual.

source
HerbSearch.mutate_random!Function
mutate_random!(program::RuleNode, grammar::AbstractGrammar, max_depth::Int64 = 2)

Mutates the given program by inserting a randomly generated sub-program at a random location.

source
HerbSearch.priority_functionMethod
priority_function(::BFSIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})

Assigns priority such that the search tree is traversed like in a BFS manner

source
HerbSearch.priority_functionMethod
priority_function(::DFSIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})

Assigns priority such that the search tree is traversed like in a DFS manner

source
HerbSearch.priority_functionMethod
priority_function(::MLFSIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})

Calculates logit for all possible derivations for a node in a tree and returns them.

source
HerbSearch.priority_functionMethod
priority_function(::TopDownIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})

Assigns a priority value to a tree that needs to be considered later in the search. Trees with the lowest priority value are considered first.

  • g: The grammar used for enumeration
  • tree: The tree that is about to be stored in the priority queue
  • parent_value: The priority value of the parent PriorityQueueItem
source
HerbSearch.probabilistic_acceptMethod
probabilistic_accept(current_cost::Real, next_cost::Real, temperature::Real)

Probabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program. Returns True if the new program is accepted, False otherwise.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the temperature; not used.
source
HerbSearch.probabilistic_accept_with_temperatureMethod
probabilistic_accept_with_temperature(current_cost::Real, next_cost::Real, temperature::Real)

Returns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns true with the probability equal to:

\[1 / (1 + exp(delta / temperature))\]

In any other case, returns false.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the temperature of the search.
source
HerbSearch.probabilistic_accept_with_temperature_fractionMethod
probabilistic_accept_with_temperature_fraction(current_cost::Real, program_to_consider_cost::Real, temperature::Real)

Probabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program multiplied by the temperature. Returns True if the new program is accepted, False otherwise.

Arguments

  • current_cost::Real: the cost of the current program.
  • next_cost::Real: the cost of the proposed program.
  • temperature::Real: the current temperature
source
HerbSearch.processkwarg!Method
processkwarg!(keywords::Vector{Expr}, ex::Union{Expr, Symbol})

Checks if ex has a default value specified, if so it returns only the field declaration, and pushes ex to keywords. Otherwise it returns ex

source
HerbSearch.propagate_constraintsFunction
function propagate_constraints(root::AbstractRuleNode, grammar::ContextSensitiveGrammar, local_constraints::Set{LocalConstraint}, max_holes::Int, filled_hole::Union{HoleReference, Nothing}=nothing)::Tuple{PropagateResult, Set{LocalConstraint}}

Propagates a set of local constraints recursively to all children of a given root node. As propagate_constraints gets often called when a hole was just filled, filled_hole helps keeping track to propagate the constraints to relevant nodes, e.g. children of filled_hole. max_holes makes sure that max_size of Base.iterate is not violated. The function returns the PropagateResult and the set of relevant LocalConstraints.

source
HerbSearch.random_fill_proposeMethod
random_fill_propose(current_program::RuleNode, neighbourhood_node_loc::NodeLoc, grammar::AbstractGrammar, max_depth::Int, dmap::AbstractVector{Int}, dict::Union{Nothing,Dict{String,Any}})

Returns a list with only one proposed, completely random, subprogram.

Arguments

  • current_program::RuleNode: the current program.
  • neighbourhood_node_loc::NodeLoc: the location of the program to replace.
  • grammar::AbstractGrammar: the grammar used to create programs.
  • max_depth::Int: the maximum depth of the resulting programs.
  • dmap::AbstractVector{Int} : the minimum possible depth to reach for each rule
  • dict::Dict{String, Any}: the dictionary with additional arguments; not used.
source
HerbSearch.select_chromosomeMethod
select_chromosome(population::Array{RuleNode}, fitness_array::Array{<:Real})::RuleNode

Selects a chromosome (individual) from the population based on a fitness array. The function uses a fitness-proportionate selection strategy, often referred to as "roulette wheel" selection. Assumes fitness_array to be normalized already.

source
HerbSearch.select_fitness_proportional_parentsMethod
select_fitness_proportional_parents(population::Array{RuleNode}, fitness_array::Array{<:Real})::Tuple{RuleNode,RuleNode}

Selects two parent chromosomes (individuals) from a population based on fitness-proportionate selection. The selected parents can be used for genetic crossover in the next steps of the algorithm.

source
HerbSearch.select_parentsMethod
select_parents(::GeneticSearchIterator, population::Array{RuleNode}, fitness_array::Array{<:Real})

Selects two parents for the crossover.

source
HerbSearch.synthMethod
synth(problem::Problem, iterator::ProgramIterator; shortcircuit::Bool=true, allow_evaluation_errors::Bool=false, mod::Module=Main)::Union{Tuple{RuleNode, SynthResult}, Nothing}

Synthesize a program that satisfies the maximum number of examples in the problem. - problem - The problem definition with IO examples - iterator - The iterator that will be used - shortcircuit - Whether to stop evaluating after finding a single example that fails, to speed up the synth procedure. If true, the returned score is an underapproximation of the actual score. - allowevaluationerrors - Whether the search should crash if an exception is thrown in the evaluation - mod - A module containing definitions for the functions in the grammar that do not exist in Main

Returns a tuple of the rulenode representing the solution program and a synthresult that indicates if that program is optimal. synth uses evaluate which returns a score in the interval [0, 1] and checks whether that score reaches 1. If not it will return the best program so far, with the proper flag

source
StatsBase.sampleFunction
sample(::Type{NodeLoc}, root::RuleNode, typ::Symbol, grammar::AbstractGrammar)

Uniformly selects a random node in the tree of a given type, specified using its parent such that the subtree can be replaced. Returns a NodeLoc.

source
StatsBase.sampleFunction
sample(root::RuleNode, typ::Symbol, grammar::AbstractGrammar,
+                      maxdepth::Int=typemax(Int))

Uniformly selects a random node of the given return type typ limited by maxdepth.

source
StatsBase.sampleFunction
sample(::Type{NodeLoc}, root::RuleNode, maxdepth::Int=typemax(Int))

Uniformly selects a random node in the tree no deeper than maxdepth using reservoir sampling. Returns a NodeLoc that specifies the location using its parent so that the subtree can be replaced.

source
StatsBase.sampleFunction
sample(root::RuleNode, typ::Symbol, grammar::AbstractGrammar, maxdepth::Int=typemax(Int))

Uniformly samples a random node from the tree limited to maxdepth.

source

The HerbSearch package takes care of all operations related to searching for the desired program. This includes

  • the functionality to sample a certain program given a grammar,
  • the implementation of several heuristic functions,
  • searching for a program that satisfies the specification, and
  • implementations of several search algorithms in terms of how they enumerate the search space
    • Breadth-First Search
    • Depth-First Search
    • Metropolis Hastings
    • Very Large Scale Neighbourhood Search
    • Simulated Annealing
    • Genetic Search

Index

diff --git a/dev/concepts/index.html b/dev/concepts/index.html index a5233b2..796338b 100644 --- a/dev/concepts/index.html +++ b/dev/concepts/index.html @@ -1,2 +1,2 @@ -Architecture and core concepts · Herb.jl
+Architecture and core concepts · Herb.jl
diff --git a/dev/get_started/index.html b/dev/get_started/index.html index f101223..f06de98 100644 --- a/dev/get_started/index.html +++ b/dev/get_started/index.html @@ -1,11 +1,14 @@ -Getting Started · Herb.jl

Getting Started

You can either paste this code into the Julia REPL or into a seperate file, e.g. get_started.jl followed by julia get_started.jl.

To begin, we need to import all needed packages using

using HerbGrammar, HerbData, HerbSearch, HerbInterpret

To define a program synthesis problem, we need a grammar and specification.

First, a grammar can be constructed using the @cfgrammar macro included in HerbGrammar. Alternatively, we can use the @csgrammar macro, which will be shown later on in the tutorial when we use constraints.

Here, we describe a simple integer arithmetic example, that can add and multiply an input variable x or the integers 1,2, using

g = @cfgrammar begin
+Getting Started · Herb.jl

Getting Started

You can either paste this code into the Julia REPL or into a seperate file, e.g. get_started.jl followed by julia get_started.jl.

To begin, we need to import all needed packages using

using HerbGrammar, HerbSpecification, HerbSearch, HerbInterpret

To define a program synthesis problem, we need a grammar and specification.

First, a grammar can be constructed using the @cfgrammar macro included in HerbGrammar. Alternatively, we can use the @csgrammar macro, which will be shown later on in the tutorial when we use constraints.

Here, we describe a simple integer arithmetic example, that can add and multiply an input variable x or the integers 1,2, using

g = @cfgrammar begin
     Number = |(1:2)
     Number = x
     Number = Number + Number
     Number = Number * Number
-end

Second, the problem specification can be provided using e.g. input/output examples using HerbData. Inputs are provided as a Dict assigning values to variables, and outputs as arbitrary values. The problem itself is then a list of IOExamples using

problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])

The problem is given now, let us search for a solution with HerbSearch. For now we will just use the default parameters searching for a satisfying program over the grammar, given the problem and a starting symbol using

solution = search(g, problem, :Number, max_depth=3)
-println(solution)

There are various ways to adapt the search technique to your needs. Please have a look at the search documentation.

Eventually, we want to test our solution on some other inputs using HerbInterpret. We transform our grammar g to a Julia expression with Symboltable(g), add our solution and the input, assigning the value 6 to the variable x.

output = test_with_input(SymbolTable(g), solution, Dict(:x => 6))
+end

Second, the problem specification can be provided using e.g. input/output examples using HerbData. Inputs are provided as a Dict assigning values to variables, and outputs as arbitrary values. The problem itself is then a list of IOExamples using

problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])

The problem is given now, let us search for a solution with HerbSearch. For now we will just use the default parameters searching for a satisfying program over the grammar, given the problem and a starting symbol using

iterator = BFSIterator(g₁, :Number, max_depth=5)
+solution, flag = synth(problem, iterator)
+println(solution)

There are various ways to adapt the search technique to your needs. Please have a look at the search documentation.

Eventually, we want to test our solution on some other inputs using HerbInterpret. We transform our grammar g to a Julia expression with Symboltable(g), add our solution and the input, assigning the value 6 to the variable x.

program = rulenode2expr(solution, g) # should yield 2*6+1
+
+output = execute_on_input(SymbolTable(g), program, Dict(:x => 6)) 
 println(output)

Just like that we tackled (almost) all modules of Herb.jl.

Where to go from here?

See our other tutorials!

The full code example

using HerbSearch, HerbData, HerbInterpret, HerbGrammar
 
 # define our very simple context-free grammar
@@ -18,6 +21,11 @@
 end
 
 problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])
-solution = search(g, problem, :Number, max_depth=3)
+iterator = BFSIterator(g₁, :Number, max_depth=5)
+
+solution, flag = synth(problem, iterator)
+program = rulenode2expr(solution, g) # should yield 2*6 +1 
 
-test_with_input(SymbolTable(g), solution, Dict(:x => 6))
+output = execute_on_input(SymbolTable(g), program, Dict(:x => 6)) +println(output) +
diff --git a/dev/index.html b/dev/index.html index 0e5a448..c30e86a 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Herb.jl · Herb.jl

Herb.jl

A library for defining and efficiently solving program synthesis tasks in Julia.

Why Herb.jl?

When writing research software we almost always investigate highly specific properties or algorithms of our domain, leading to us building the tools from scratch over and over again. The very same holds for the field of program synthesis: Tools are hard to run, benchmarks are hard to get and prepare, and its hard to adapt our existing code to a novel idea.

Herb.jl will take care of this for you and helps you defining, solving and extending your program synthesis problems.

Herb.jl provides...

  • a unified and universal framework for program synthesis
  • Herb.jl allows you to describe all sorts of program synthesis problems using context-free grammars
  • a number of state-of-the-art benchmarks and solvers already implemented and usable out-of-the-box

Herb.jl's sub-packages provide fast and easily extendable implementations of

  • various static and dynamic search strategies,
  • learning search strategies, sampling techniques and more,
  • constraint formulation and propagation,
  • easy grammar formulation and usage,
  • wide-range of usable program interpreters and languages + the possibility to use your own, and
  • efficient data formulation.

Why Julia?

Julia is a perfect fit for program synthesis due to numerous reasons. Starting from scientific reasons like speed of execution and composability over to practical reasons like speed of writing Julia code. For a full ode on why to use Julia, please see the WhyJulia manifesto.

Sub-Modules

Herb's functionality is distributed among several sub-packages:

Basics

Advanced content

+Herb.jl · Herb.jl

Herb.jl

A library for defining and efficiently solving program synthesis tasks in Julia.

Why Herb.jl?

When writing research software we almost always investigate highly specific properties or algorithms of our domain, leading to us building the tools from scratch over and over again. The very same holds for the field of program synthesis: Tools are hard to run, benchmarks are hard to get and prepare, and its hard to adapt our existing code to a novel idea.

Herb.jl will take care of this for you and helps you defining, solving and extending your program synthesis problems.

Herb.jl provides...

  • a unified and universal framework for program synthesis
  • Herb.jl allows you to describe all sorts of program synthesis problems using context-free grammars
  • a number of state-of-the-art benchmarks and solvers already implemented and usable out-of-the-box

Herb.jl's sub-packages provide fast and easily extendable implementations of

  • various static and dynamic search strategies,
  • learning search strategies, sampling techniques and more,
  • constraint formulation and propagation,
  • easy grammar formulation and usage,
  • wide-range of usable program interpreters and languages + the possibility to use your own, and
  • efficient data formulation.

Why Julia?

Julia is a perfect fit for program synthesis due to numerous reasons. Starting from scientific reasons like speed of execution and composability over to practical reasons like speed of writing Julia code. For a full ode on why to use Julia, please see the WhyJulia manifesto.

Sub-Modules

Herb's functionality is distributed among several sub-packages:

Basics

Advanced content

diff --git a/dev/install/index.html b/dev/install/index.html index 6e54fb4..6f45f5e 100644 --- a/dev/install/index.html +++ b/dev/install/index.html @@ -1,4 +1,4 @@ Installation Guide · Herb.jl

Installation Guide

Before installing Herb.jl, ensure that you have a running Julia distribution installed (Julia version 1.7 and above were tested).

Thanks to Julia's package management, installing Herb.jl is very straighforward. Activate the default Julia REPL using

julia

or from within one of your projects using

julia --project=.

From the Julia REPL run

]
 add Herb

or instead running

import Pkg
-Pkg.add("Herb")

which will both install all dependencies automatically.

For later convenience we can also add the respective dependencies to our project, so that we do not have to write Herb.HerbGrammar every time.

] add HerbConstraints HerbCore HerbData HerbInterpret HerbGrammar HerbSearch

And just like this you are done! Welcome to Herb.jl!

+Pkg.add("Herb")

which will both install all dependencies automatically.

For later convenience we can also add the respective dependencies to our project, so that we do not have to write Herb.HerbGrammar every time.

] add HerbConstraints HerbCore HerbData HerbInterpret HerbGrammar HerbSearch

And just like this you are done! Welcome to Herb.jl!

diff --git a/dev/search/index.html b/dev/search/index.html index 9a573fc..ab90899 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · Herb.jl

Loading search...

    +Search · Herb.jl

    Loading search...

      diff --git a/dev/search_index.js b/dev/search_index.js index 86af64a..3a3bdb1 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"install/#Installation-Guide","page":"Installation Guide","title":"Installation Guide","text":"","category":"section"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"Before installing Herb.jl, ensure that you have a running Julia distribution installed (Julia version 1.7 and above were tested). ","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"Thanks to Julia's package management, installing Herb.jl is very straighforward. Activate the default Julia REPL using","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"julia","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"or from within one of your projects using","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"julia --project=.","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"From the Julia REPL run ","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"]\nadd Herb","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"or instead running","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"import Pkg\nPkg.add(\"Herb\")","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"which will both install all dependencies automatically.","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"For later convenience we can also add the respective dependencies to our project, so that we do not have to write Herb.HerbGrammar every time.","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"] add HerbConstraints HerbCore HerbData HerbInterpret HerbGrammar HerbSearch","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"And just like this you are done! Welcome to Herb.jl!","category":"page"},{"location":"concepts/#Architecture-and-core-concepts","page":"Architecture and core concepts","title":"Architecture and core concepts","text":"","category":"section"},{"location":"HerbSearch/#HerbSearch_docs","page":"HerbSearch.jl","title":"HerbSearch.jl Documentation","text":"","category":"section"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"CurrentModule=HerbSearch","category":"page"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"Modules = [HerbSearch]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbSearch/#HerbSearch.ContextSensitivePriorityEnumerator","page":"HerbSearch.jl","title":"HerbSearch.ContextSensitivePriorityEnumerator","text":"mutable struct ContextSensitivePriorityEnumerator <: ExpressionIterator\n\nEnumerates a context-free grammar starting at Symbol sym with respect to the grammar up to a given depth and a given size. The exploration is done using the given priority function for derivations, and the expand function for discovered nodes.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.ExpandFailureReason","page":"HerbSearch.jl","title":"HerbSearch.ExpandFailureReason","text":"@enum ExpandFailureReason limit_reached=1 already_complete=2\n\nRepresentation of the different reasons why expanding a partial tree failed. Currently, there are two possible causes of the expansion failing:\n\nlimit_reached: The depth limit or the size limit of the partial tree would be violated by the expansion\nalready_complete: There is no hole left in the tree, so nothing can be expanded.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.ExpressionIterator","page":"HerbSearch.jl","title":"HerbSearch.ExpressionIterator","text":"abstract type ExpressionIterator\n\nAbstract super-type for all possible enumerators.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.GeneticSearchIterator","page":"HerbSearch.jl","title":"HerbSearch.GeneticSearchIterator","text":"GeneticSearchIterator{FitnessFunction,CrossOverFunction,MutationFunction,SelectParentsFunction,EvaluationFunction} <: ExpressionIterator\n\nDefines an ExpressionIterator using genetic search. \n\nConsists of:\n\ngrammar::ContextSensitiveGrammar: the grammar to search over\nexamples::Vector{<:Example}: a collection of examples defining the specification \nfitness::FitnessFunction: assigns a numerical value (fitness score) to each individual based on how closely it meets the desired objective\ncross_over::CrossOverFunction: combines the program from two parent individuals to create one or more offspring individuals\nmutation!::MutationFunction: mutates the program of an invididual\nselect_parents::SelectParentsFunction: selects two parents for the crossover\nevaluation_function::EvaluationFunction: interpreter to evaluate the individual programs\nstart_symbol::Symbol: defines the start symbol from which the search should be started\npopulation_size::Int64: number of inviduals in the population\nmutation_probability::Float64: probability of mutation for each individual\nmaximum_initial_population_depth::Int64: maximum depth of trees when population is initialized \n\nend\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.PriorityQueueItem","page":"HerbSearch.jl","title":"HerbSearch.PriorityQueueItem","text":"struct PriorityQueueItem\n\nRepresents an item in the priority enumerator priority queue. An item contains of:\n\ntree: A partial AST\nsize: The size of the tree. This is a cached value which prevents having to traverse the entire tree each time the size is needed.\nconstraints: The local constraints that apply to this tree. These constraints are enforced each time the tree is modified.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.PriorityQueueItem-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.PriorityQueueItem","text":"PriorityQueueItem(tree::AbstractRuleNode, size::Int)\n\nConstructs PriorityQueueItem given only a tree and the size, but no constraints.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.PropagateResult","page":"HerbSearch.jl","title":"HerbSearch.PropagateResult","text":"@enum PropagateResult tree_complete=1 tree_incomplete=2 tree_infeasible=3\n\nRepresentation of the possible results of a constraint propagation. At the moment there are three possible outcomes:\n\ntree_complete: The propagation was applied successfully and the tree does not contain any holes anymore. Thus no constraints can be applied anymore.\ntree_incomplete: The propagation was applied successfully and the tree does contain more holes. Thus more constraints may be applied to further prune the respective domains.\ntree_infeasible: The propagation was succesful, but there are holes with empty domains. Hence, the tree is now infeasible.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.StochasticSearchEnumerator","page":"HerbSearch.jl","title":"HerbSearch.StochasticSearchEnumerator","text":"Base.@kwdef struct StochasticSearchEnumerator <: ExpressionIterator\n\nA unified struct for the algorithms Metropolis Hastings, Very Large Scale Neighbourhood and Simulated Annealing. Each algorithm implements neighbourhood propose accept and temperature functions. Below the signiture of all this function is shown\n\nSignatures\n\n\n\nReturns a node location from the program that is the neighbourhood. It can also return other information using dict\n\nneighbourhood(program::RuleNode, grammar::Grammar) -> (loc::NodeLocation, dict::Dict)\n\n\n\nProposes a list of programs using the location provided by neighbourhood and the dict.\n\npropose(current_program, loc::NodeLocation, grammar::Grammar, max_depth::Int64, dict::Dict) -> Iter[RuleNode]\n\n\n\nBased on the current program and possible cost and temperature it accepts the program or not. Usually we would always want to accept better programs but we might get stuck if we do so. That is why some implementations of the accept function accept with a probability costs that are worse. cost means how different are the outcomes of the program compared to the correct outcomes. The lower the cost the better the program performs on the examples. The cost is provided by the cost_function\n\naccept(current_cost::Real, possible_cost::Real, temperature::Real) -> Bool\n\n\n\nReturns the new temperature based on the previous temperature. Higher the temperature means that the algorithm will explore more.\n\ntemperature(previous_temperature::Real) -> Real\n\n\n\nReturns the cost of the current program. It receives a list of tuples (expected, found) and gives back a cost.\n\ncost_function(outcomes::Tuple{<:Number,<:Number}[]) -> Real\n\n\n\nFields\n\ngrammar::ContextSensitiveGrammar grammar that the algorithm uses\nmax_depth::Int64 = 5 maximum depth of the program to generate\nexamples::Vector{Example} example used to check the program\nneighbourhood::Function \npropose::Function\naccept::Function\ntemperature::Function\ncost_function::Function\nstart_symbol::Symbol the start symbol of the algorithm :Real or :Int\ninitial_temperature::Real = 1 \nevaluation_function::Function that evaluates the julia expressions\n\nAn iterator over all possible expressions of a grammar up to max_depth with start symbol sym.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#Base.iterate-Tuple{ContextSensitivePriorityEnumerator, DataStructures.PriorityQueue}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::ContextSensitivePriorityEnumerator, pq::DataStructures.PriorityQueue)\n\nDescribes the iteration for a given ContextSensitivePriorityEnumerator and a PriorityQueue over the grammar without enqueueing new items to the priority queue. Recursively returns the result for the priority queue.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{ContextSensitivePriorityEnumerator}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::ContextSensitivePriorityEnumerator)\n\nDescribes the iteration for a given ContextSensitivePriorityEnumerator over the grammar. The iteration constructs a PriorityQueue first and then prunes it propagating the active constraints. Recursively returns the result for the priority queue.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{HerbSearch.GeneticSearchIterator, HerbSearch.GeneticIteratorState}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::GeneticSearchIterator, current_state::GeneticIteratorState)\n\nIterates the search space using a genetic algorithm. Takes the iterator and the current state to mutate and crossover random inviduals. Returns the best program-so-far and the state of the iterator.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{HerbSearch.GeneticSearchIterator}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::GeneticSearchIterator)\n\nIterates the search space using a genetic algorithm. First generates a population sampling random programs. Returns the best program-so-far, and the state of the iterator.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{HerbSearch.StochasticSearchEnumerator, HerbSearch.IteratorState}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::StochasticSearchEnumerator, current_state::IteratorState)\n\nThe algorithm that constructs the iterator of StochasticSearchEnumerator. It has the following structure:\n\nget a random node location -> location,dict = neighbourhood(current_program)\ncall propose on the current program getting a list of possbile replacements in the node location \niterate through all the possible replacements and perform the replacement in the current program \naccept the new program by modifying the next_program or reject the new program\nreturn the new next_program\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.rand","page":"HerbSearch.jl","title":"Base.rand","text":"rand(::Type{RuleNode}, grammar::Grammar, typ::Symbol, dmap::AbstractVector{Int}, max_depth::Int=10)\n\nGenerates a random RuleNode, i.e. an expression tree, of root type typ and maximum depth max_depth guided by a depth map dmap if possible.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#Base.rand-2","page":"HerbSearch.jl","title":"Base.rand","text":"rand(::Type{RuleNode}, grammar::Grammar, max_depth::Int=10)\n\nGenerates a random RuleNode of arbitrary type and maximum depth max_depth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#Base.rand-3","page":"HerbSearch.jl","title":"Base.rand","text":"rand(::Type{RuleNode}, grammar::Grammar, typ::Symbol, max_depth::Int=10)\n\nGenerates a random RuleNode of return type typ and maximum depth max_depth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch._expand-Tuple{Hole, ContextSensitiveGrammar, Int64, Int64, GrammarContext, Function, Function}","page":"HerbSearch.jl","title":"HerbSearch._expand","text":"_expand(node::Hole, grammar::ContextSensitiveGrammar, ::Int, max_holes::Int, context::GrammarContext, hole_heuristic::Function, derivation_heuristic::Function)::Union{ExpandFailureReason, Vector{TreeConstraints}}\n\nExpands a given hole that was found in _expand using the given derivation heuristic. Returns the list of discovered nodes in that order and with their respective constraints.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch._expand-Tuple{RuleNode, ContextSensitiveGrammar, Int64, Int64, GrammarContext, Function, Function}","page":"HerbSearch.jl","title":"HerbSearch._expand","text":"_expand(root::RuleNode, grammar::ContextSensitiveGrammar, max_depth::Int, max_holes::Int, context::GrammarContext, hole_heuristic::Function, derivation_heuristic::Function)::Union{ExpandFailureReason, Vector{TreeConstraints}}\n\nRecursive expand function used in multiple enumeration techniques. Expands one hole/undefined leaf of the given RuleNode tree found using the given hole heuristic. If the expansion was successful, returns a list of new trees and a list of lists of hole locations, corresponding to the holes of each newly expanded tree. Returns nothing if tree is already complete (i.e. contains no holes). Returns an empty list if the tree is partial (i.e. contains holes), but they could not be expanded because of the depth limit.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch._find_next_complete_tree-Tuple{ContextSensitiveGrammar, Int64, Int64, Function, Function, DataStructures.PriorityQueue}","page":"HerbSearch.jl","title":"HerbSearch._find_next_complete_tree","text":"_find_next_complete_tree(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, priority_function::Function, expand_function::Function, pq::PriorityQueue)::Union{Tuple{RuleNode, PriorityQueue}, Nothing}\n\nTakes a priority queue and returns the smallest AST from the grammar it can obtain from the queue or by (repeatedly) expanding trees that are in the queue. Returns nothing if there are no trees left within the depth limit.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.best_accept-Tuple{Real, Real, Any}","page":"HerbSearch.jl","title":"HerbSearch.best_accept","text":"best_accept(current_cost::Real, next_cost::Real, temperature)\n\nReturns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns false.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the temperature; not used.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.calculate_cost-Tuple{RuleNode, Function, AbstractVector{Example}, Grammar, Function}","page":"HerbSearch.jl","title":"HerbSearch.calculate_cost","text":"calculate_cost(program::RuleNode, cost_function::Function, examples::AbstractVector{Example}, grammar::Grammar, evaluation_function::Function)\n\nReturns the cost of the program using the examples and the cost_function. It first convert the program to an expression and evaluates it on all the examples using HerbInterpret.evaluate_program.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.const_temperature-Tuple{Any}","page":"HerbSearch.jl","title":"HerbSearch.const_temperature","text":"const_temperature(current_temperature)\n\nReturns the temperature unchanged. This function is used by Metropolis Hastings and Very Large Neighbourhood Search algorithms.\n\nArguments\n\ncurrent_temperature::Real: the current temperature of the search.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.constructNeighbourhood-Tuple{RuleNode, Grammar}","page":"HerbSearch.jl","title":"HerbSearch.constructNeighbourhood","text":"constructNeighbourhood(current_program::RuleNode, grammar::Grammar)\n\nThe neighbourhood node location is chosen at random. The dictionary is nothing.\n\nArguments\n\ncurrent_program::RuleNode: the current program.\ngrammar::Grammar: the grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.constructNeighbourhoodRuleSubset-Tuple{RuleNode, Grammar}","page":"HerbSearch.jl","title":"HerbSearch.constructNeighbourhoodRuleSubset","text":"constructNeighbourhoodRuleSubset(current_program::RuleNode, grammar::Grammar)\n\nThe neighbourhood node location is chosen at random. The dictionary is contains one entry with key \"rule_subset\" and value of type Vector{Any} being a random subset of grammar rules.\n\nArguments\n\ncurrent_program::RuleNode: the current program.\ngrammar::Grammar: the grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.count_expressions-Tuple{ExpressionIterator}","page":"HerbSearch.jl","title":"HerbSearch.count_expressions","text":"count_expressions(iter::ExpressionIterator)\n\nCounts and returns the number of possible expressions in the expression iterator. The Iterator is not modified.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.count_expressions-Tuple{Grammar, Int64, Int64, Symbol}","page":"HerbSearch.jl","title":"HerbSearch.count_expressions","text":"count_expressions(grammar::Grammar, max_depth::Int, max_size::Int, sym::Symbol)\n\nCounts and returns the number of possible expressions of a grammar up to max_depth with start symbol sym.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.crossover_swap_children_1-Tuple{RuleNode, RuleNode}","page":"HerbSearch.jl","title":"HerbSearch.crossover_swap_children_1","text":"crossover_swap_children_1(parent1::RuleNode, parent2::RuleNode)\n\nPerforms a random crossover of two parents of type RuleNode. The subprograms are swapped and only one altered parent program is returned.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.crossover_swap_children_2-Tuple{RuleNode, RuleNode}","page":"HerbSearch.jl","title":"HerbSearch.crossover_swap_children_2","text":"crossover_swap_children_2(parent1::RuleNode, parent2::RuleNode)\n\nPerforms a random crossover of two parents of type RuleNode. The subprograms are swapped and both altered parent programs are returned.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.decreasing_temperature-Tuple{Real}","page":"HerbSearch.jl","title":"HerbSearch.decreasing_temperature","text":"decreasing_temperature(percentage::Real)\n\nReturns a function that produces a temperature decreased by percentage%. This function is used by the Simmulated Annealing algorithm.\n\nArguments\n\npercentage::Real: the percentage to decrease the temperature by.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.default_error_function-Tuple{Any, Any, Any}","page":"HerbSearch.jl","title":"HerbSearch.default_error_function","text":"default_error_function(old_error, output, expected_output)\n\nDefault error function for search_best.\n\n- old_error - The existing total error\n- output - The actual output of the evaluator\n- expected_output - The expected output for the example\n\nThe default function returns 0 if the outputs match and 1 otherwise.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.default_fitness-Tuple{Any, Any}","page":"HerbSearch.jl","title":"HerbSearch.default_fitness","text":"default_fitness(program, results)\n\nDefines the default fitness function taking the program and its results. Results are a vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}. As we are looking for individuals with the highest fitness function, the error is inverted. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.enumerate_neighbours_propose-Tuple{Int64}","page":"HerbSearch.jl","title":"HerbSearch.enumerate_neighbours_propose","text":"enumerate_neighbours_propose(enumeration_depth::Int64)\n\nThe return function is a function that produces a list with all the subprograms with depth at most enumeration_depth.\n\nArguments\n\nenumeration_depth::Int64: the maximum enumeration depth.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.get_best_program-Tuple{Array{RuleNode}, HerbSearch.GeneticSearchIterator}","page":"HerbSearch.jl","title":"HerbSearch.get_best_program","text":"get_best_program(population::Array{RuleNode}, iter:: GeneticSearchIterator)::RuleNode\n\nReturns the best program within the population with respect to the fitness function.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.get_bfs_enumerator","page":"HerbSearch.jl","title":"HerbSearch.get_bfs_enumerator","text":"get_bfs_enumerator(grammar::ContextFreeGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator\n\nReturns a breadth-first search enumerator given a ContextFreeGrammar. Returns trees in the grammar in increasing order of size. \n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_bfs_enumerator-2","page":"HerbSearch.jl","title":"HerbSearch.get_bfs_enumerator","text":"get_bfs_enumerator(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator\n\nReturns a breadth-first search enumerator given a ContextSensitiveGrammar. Returns trees in the grammar in increasing order of size. \n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_dfs_enumerator","page":"HerbSearch.jl","title":"HerbSearch.get_dfs_enumerator","text":"get_dfs_enumerator(grammar::ContextFreeGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator\n\nReturns a depth-first search enumerator given a ContextFreeGrammar. Returns trees in the grammar in decreasing order of size.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_dfs_enumerator-2","page":"HerbSearch.jl","title":"HerbSearch.get_dfs_enumerator","text":"get_dfs_enumerator(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator\n\nReturns a depth-first search enumerator given a ContextSensitiveGrammar. Returns trees in the grammar in decreasing order of size.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_genetic_enumerator-Tuple{Any}","page":"HerbSearch.jl","title":"HerbSearch.get_genetic_enumerator","text":"get_genetic_enumerator(examples; fitness_function = HerbSearch.default_fitness, initial_population_size = 10, maximum_initial_population_depth = 3, mutation_probability = 0.1, cross_over = HerbSearch.crossover_swap_children_2, select_parents = HerbSearch.select_fitness_proportional_parents, evaluation_function::Function=HerbInterpret.test_with_input)\n\nReturns a GeneticSearchIterator given a grammar. The iterator is fitted against the examples provided evaluated using the fitness function. All other arguments are hyperparameters for the genetic search procedure.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.get_mh_enumerator","page":"HerbSearch.jl","title":"HerbSearch.get_mh_enumerator","text":"get_mh_enumerator(examples::AbstractArray{<:Example}, cost_function::Function, evaluation_function::Function=HerbInterpret.test_with_input)\n\nReturns an enumerator that runs according to the Metropolis Hastings algorithm.\n\nexamples : array of examples\ncost_function : cost function to evaluate the programs proposed\nevaluation_function : evaluation function that evaluates the program generated and produces an output \n\nThe propose function is randomfillpropose and the accept function is probabilistic. The temperature value of the algorithm remains constant over time. \n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_most_likely_first_enumerator","page":"HerbSearch.jl","title":"HerbSearch.get_most_likely_first_enumerator","text":"get_most_likely_first_enumerator(grammar::ContextFreeGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator\n\nReturns an enumerator that enumerates expressions in the grammar in decreasing order of probability. Only use this function with probabilistic grammars.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_most_likely_first_enumerator-2","page":"HerbSearch.jl","title":"HerbSearch.get_most_likely_first_enumerator","text":"get_most_likely_first_enumerator(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, sym::Symbol, hole_heuristic::Function=heuristic_leftmost, derivation_heuristic::Function=(a,_) -> a)::ContextSensitivePriorityEnumerator\n\nReturns an enumerator that enumerates expressions in the grammar in decreasing order of probability. Only use this function with probabilistic grammars.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_sa_enumerator","page":"HerbSearch.jl","title":"HerbSearch.get_sa_enumerator","text":"get_sa_enumerator(examples, cost_function, initial_temperature=1, temperature_decreasing_factor = 0.99, evaluation_function::Function=HerbInterpret.test_with_input)\n\nReturns an enumerator that runs according to the Very Large Scale Neighbourhood Search algorithm.\n\nexamples : array of examples\ncost_function : cost function to evaluate the programs proposed\ninitial_temperature : the starting temperature of the algorithm\ntemperature_decreasing_factor : the decreasing factor of the temperature of the time\nevaluation_function : evaluation function that evaluates the program generated and produces an output \n\nThe propose function is random_fill_propose (the same as for Metropolis Hastings). The accept function is probabilistic but takes into account the tempeerature too.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.get_vlsn_enumerator","page":"HerbSearch.jl","title":"HerbSearch.get_vlsn_enumerator","text":"get_vlsn_enumerator(examples, cost_function, enumeration_depth = 2, evaluation_function::Function=HerbInterpret.test_with_input)\n\nReturns an enumerator that runs according to the Very Large Scale Neighbourhood Search algorithm.\n\nexamples : array of examples\ncost_function : cost function to evaluate the programs proposed\nenumeration_depth : the enumeration depth to search for a best program at a time\nevaluation_function : evaluation function that evaluates the program generated and produces an output \n\nThe propose function consists of all possible programs of the given enumeration_depth. The accept function accepts the program with the lowest cost according to the cost_function. The temperature value of the algorithm remains constant over time. \n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.heuristic_leftmost-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_leftmost","text":"heuristic_leftmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes, where the left-most hole always gets considered first. Returns a HoleReference once a hole is found. This is the default option for enumerators.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_random-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_random","text":"heuristic_random(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes, where random holes get chosen randomly using random exploration. Returns a HoleReference once a hole is found.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_rightmost-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_rightmost","text":"heuristic_rightmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes, where the right-most hole always gets considered first. Returns a HoleReference once a hole is found. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_smallest_domain-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_smallest_domain","text":"heuristic_smallest_domain(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over all available holes in the unfinished AST, by considering the size of their respective domains. A domain here describes the number of possible derivations with respect to the constraints. Returns a HoleReference once a hole is found. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.mean_squared_error-Tuple{T} where T<:(AbstractVector{<:Tuple{Number, Number}})","page":"HerbSearch.jl","title":"HerbSearch.mean_squared_error","text":"mean_squared_error(results::AbstractVector{Tuple{<:Number,<:Number}})\n\nReturns the mean squared error of results.\n\nArguments\n\nresults<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.misclassification-Tuple{T} where T<:(AbstractVector{<:Tuple{Number, Number}})","page":"HerbSearch.jl","title":"HerbSearch.misclassification","text":"misclassification(results::AbstractVector{Tuple{<:Number,<:Number}})\n\nReturns the amount of misclassified examples, i.e. how many tuples with non-matching entries are there in results.\n\nArguments\n\nresults<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.most_likely_priority_function-Tuple{ContextSensitiveGrammar, AbstractRuleNode, Union{Real, Tuple{Vararg{Real}}}}","page":"HerbSearch.jl","title":"HerbSearch.most_likely_priority_function","text":"most_likely_priority_function(g::ContextSensitiveGrammar, tree::AbstractRuleNode, ::Union{Real, Tuple{Vararg{Real}}})\n\nCalculates logit for all possible derivations for a node in a tree and returns them.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.mse_error_function-Tuple{Any, Any, Any}","page":"HerbSearch.jl","title":"HerbSearch.mse_error_function","text":"mse_error_function(old_error, output, expected_output)\n\nMean squared error function for search_best.\n\n- old_error - The existing total error\n- output - The actual output of the evaluator\n- expected_output - The expected output for the example\n\nThe function build the mean squared error from output and expected_output`.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.mutate_random!","page":"HerbSearch.jl","title":"HerbSearch.mutate_random!","text":"mutate_random!(program::RuleNode, grammar::Grammar, max_depth::Int64 = 2)\n\nMutates the given program by inserting a randomly generated sub-program at a random location.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.probabilistic_accept-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.probabilistic_accept","text":"probabilistic_accept(current_cost::Real, next_cost::Real, temperature::Real)\n\nProbabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program. Returns True if the new program is accepted, False otherwise.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the temperature; not used.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.probabilistic_accept_with_temperature-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.probabilistic_accept_with_temperature","text":"probabilistic_accept_with_temperature(current_cost::Real, next_cost::Real, temperature::Real)\n\nReturns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns true with the probability equal to: \n\n1 (1 + exp(delta temperature))\n\nIn any other case, returns false.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the temperature of the search.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.probabilistic_accept_with_temperature_fraction-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.probabilistic_accept_with_temperature_fraction","text":"probabilistic_accept_with_temperature_fraction(current_cost::Real, program_to_consider_cost::Real, temperature::Real)\n\nProbabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program multiplied by the temperature. Returns True if the new program is accepted, False otherwise.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the current temperature \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.propagate_constraints","page":"HerbSearch.jl","title":"HerbSearch.propagate_constraints","text":"function propagate_constraints(root::AbstractRuleNode, grammar::ContextSensitiveGrammar, local_constraints::Set{LocalConstraint}, max_holes::Int, filled_hole::Union{HoleReference, Nothing}=nothing)::Tuple{PropagateResult, Set{LocalConstraint}}\n\nPropagates a set of local constraints recursively to all children of a given root node. As propagate_constraints gets often called when a hole was just filled, filled_hole helps keeping track to propagate the constraints to relevant nodes, e.g. children of filled_hole. max_holes makes sure that max_size of Base.iterate is not violated. The function returns the PropagateResult and the set of relevant LocalConstraints.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.random_fill_propose-Tuple{RuleNode, NodeLoc, Grammar, Int64, AbstractVector{Int64}, Union{Nothing, Dict{String, Any}}}","page":"HerbSearch.jl","title":"HerbSearch.random_fill_propose","text":"random_fill_propose(current_program, neighbourhood_node_loc, grammar, max_depth, dict)\n\nReturns a list with only one proposed, completely random, subprogram.\n\nArguments\n\ncurrent_program::RuleNode: the current program.\nneighbourhood_node_loc::NodeLoc: the location of the program to replace.\ngrammar::Grammar: the grammar used to create programs.\nmax_depth::Int: the maximum depth of the resulting programs.\ndmap::AbstractVector{Int} : the minimum possible depth to reach for each rule\ndict::Dict{String, Any}: the dictionary with additional arguments; not used.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.search-Tuple{Grammar, Problem, Symbol}","page":"HerbSearch.jl","title":"HerbSearch.search","text":"search(g::Grammar, problem::Problem, start::Symbol; evaluator::Function=test_with_input, enumerator::Function=get_bfs_enumerator, max_depth::Union{Int, Nothing}=nothing, max_size::Union{Int, Nothing}=nothing, max_time::Union{Int, Nothing}=nothing, max_enumerations::Union{Int, Nothing}=nothing, allow_evaluation_errors::Bool=false, mod::Module=Main)::Union{Any, Nothing}\n\nSearches for a program by calling search_rulenode starting from Symbol start guided by enumerator and Grammar trying to satisfy the higher-order constraints in form of input/output examples defined in the Problem. This is the heart of the Herb's search for satisfying programs. Returns the found program when the evaluation calculated using evaluator is successful.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.search_best-Tuple{Grammar, Problem, Symbol}","page":"HerbSearch.jl","title":"HerbSearch.search_best","text":"search_best(g::Grammar, problem::Problem, start::Symbol; evaluator::Function=test_with_input, enumerator::Function=get_bfs_enumerator, error_function::Function=default_error_function, max_depth::Union{Int, Nothing}=nothing, max_size::Union{Int, Nothing}=nothing, max_time::Union{Int, Nothing}=nothing, max_enumerations::Union{Int, Nothing}=nothing, allow_evaluation_errors::Bool=false, mod::Module=Main)::Tuple{Any, Real}\n\nSearches the grammar for the program that satisfies the maximum number of examples in the problem. The evaluator should be a function that takes a SymbolTable, expression and a dictionary with input variable assignments and returns the output of the expression.\n\n- g - The grammar that defines the search space\n- problem - The problem definition with IO examples\n- start - The start symbol in the grammar\n- evaluator - The evaluation function. Takes a SymbolTable, expression and a dictionary with \n input variable assignments and returns the output of the expression.\n- enumerator - A constructor for the enumerator that should be used in the search\n- error_function - The error function. Takes the existing total error, the actual output of the evaluator \n and the expected value for the example.\n- max_depth - The maximum depth of the search\n- max_time - The maximum time allowed for the search in seconds\n- max_enumerations - The maximum number of programs to enumerate and test\n- allow_evaluation_errors - Whether the search should crash if an exception is thrown in the evaluation\n- mod - A module containing definitions for the functions in the grammar that do not exist in Main\n\nReturns a tuple with the best found program so far and the error. Can be considerably slower than search due to having to evaluate each expression on each example.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.search_rulenode-Tuple{Grammar, Problem, Symbol}","page":"HerbSearch.jl","title":"HerbSearch.search_rulenode","text":"search_rulenode(g::Grammar, problem::Problem, start::Symbol; evaluator::Function=test_with_input, enumerator::Function=get_bfs_enumerator, max_depth::Union{Int, Nothing}=nothing, max_size::Union{Int, Nothing}=nothing, max_time::Union{Int, Nothing}=nothing, max_enumerations::Union{Int, Nothing}=nothing, allow_evaluation_errors::Bool=false, mod::Module=Main)::Union{Tuple{RuleNode, Any}, Nothing}\n\nSearches the grammar for the program that satisfies the maximum number of examples in the problem.\n\n - g - The grammar that defines the search space\n - problem - The problem definition with IO examples\n - start - The start symbol in the grammar\n - evaluator - The evaluation function. Takes a SymbolTable, expression and a dictionary with \n input variable assignments and returns the output of the expression.\n - enumerator - A constructor for the enumerator that should be used in the search\n - max_depth - The maximum depth of the search\n - max_size - The maximum number of nodes for ASTs in the search\n - max_time - The maximum time allowed for the search in seconds\n - max_enumerations - The maximum number of programs to enumerate and test'\n - allow_evaluation_errors - Whether the search should crash if an exception is thrown in the evaluation\n - mod - A module containing definitions for the functions in the grammar that do not exist in Main\nReturns a tuple of the rulenode and the expression of the solution program once it has been found, \nor nothing otherwise.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.select_chromosome-Tuple{Array{RuleNode}, Array{<:Real}}","page":"HerbSearch.jl","title":"HerbSearch.select_chromosome","text":"select_chromosome(population::Array{RuleNode}, fitness_array::Array{<:Real})::RuleNode\n\nSelects a chromosome (individual) from the population based on a fitness array. The function uses a fitness-proportionate selection strategy, often referred to as \"roulette wheel\" selection. Assumes fitness_array to be normalized already.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.select_fitness_proportional_parents-Tuple{Array{RuleNode}, Array{<:Real}}","page":"HerbSearch.jl","title":"HerbSearch.select_fitness_proportional_parents","text":"select_fitness_proportional_parents(population::Array{RuleNode}, fitness_array::Array{<:Real})::Tuple{RuleNode,RuleNode}\n\nSelects two parent chromosomes (individuals) from a population based on fitness-proportionate selection. The selected parents can be used for genetic crossover in the next steps of the algorithm.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.validate_iterator-Tuple{Any}","page":"HerbSearch.jl","title":"HerbSearch.validate_iterator","text":"validate_iterator(iter)\n\nValidates the parameters of the iterator\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#StatsBase.sample","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(::Type{NodeLoc}, root::RuleNode, maxdepth::Int=typemax(Int))\n\nUniformly selects a random node in the tree no deeper than maxdepth using reservoir sampling. Returns a NodeLoc that specifies the location using its parent so that the subtree can be replaced.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#StatsBase.sample-2","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(::Type{NodeLoc}, root::RuleNode, typ::Symbol, grammar::Grammar)\n\nUniformly selects a random node in the tree of a given type, specified using its parent such that the subtree can be replaced. Returns a NodeLoc.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#StatsBase.sample-3","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(root::RuleNode, typ::Symbol, grammar::Grammar, maxdepth::Int=typemax(Int))\n\nUniformly samples a random node from the tree limited to maxdepth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#StatsBase.sample-4","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(root::RuleNode, typ::Symbol, grammar::Grammar,\n maxdepth::Int=typemax(Int))\n\nUniformly selects a random node of the given return type typ limited by maxdepth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"The HerbSearch package takes care of all operations related to searching for the desired program. This includes","category":"page"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"the functionality to sample a certain program given a grammar,\nthe implementation of several heuristic functions,\nsearching for a program that satisfies the specification, and\nimplementations of several search algorithms in terms of how they enumerate the search space\nBreadth-First Search \nDepth-First Search \nMetropolis Hastings \nVery Large Scale Neighbourhood Search \nSimulated Annealing\nGenetic Search","category":"page"},{"location":"HerbSearch/#Index","page":"HerbSearch.jl","title":"Index","text":"","category":"section"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"","category":"page"},{"location":"HerbCore/#HerbCore_docs","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"","category":"section"},{"location":"HerbCore/","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"CurrentModule=HerbCore","category":"page"},{"location":"HerbCore/","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"Modules = [HerbCore]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbCore/#HerbCore.AbstractRuleNode","page":"HerbCore.jl Documentation","title":"HerbCore.AbstractRuleNode","text":"AbstractRuleNode\n\nAbstract type for representing expression trees. Expression trees consist of RuleNodes and Holes.\n\nA RuleNode represents a certain production rule in the Grammar.\nA Hole is a placeholder where certain rules in the grammar still can be applied. \n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.Constraint","page":"HerbCore.jl Documentation","title":"HerbCore.Constraint","text":"Represents a constraint for a ContextSensitiveGrammar. Concrete implementations can be found in HerbConstraints.jl.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.Grammar","page":"HerbCore.jl Documentation","title":"HerbCore.Grammar","text":"Grammar\n\nAbstract type representing all grammars. It is assumed that all grammar structs have at least the following attributes:\n\nrules::Vector{Any}: A list of RHS of rules (subexpressions).\ntypes::Vector{Symbol}: A list of LHS of rules (types, all symbols).\nisterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.\niseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.\nbytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.\ndomains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.\nchildtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. \n\nIf a rule is terminal, the corresponding list is empty.\n\nlog_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. \n\nIf the grammar is non-probabilistic, the list can be nothing.\n\nFor concrete types, see ContextFreeGrammar and ContextSensitiveGrammar.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.Hole","page":"HerbCore.jl Documentation","title":"HerbCore.Hole","text":"Hole <: AbstractRuleNode\n\nA Hole is a placeholder where certain rules from the grammar can still be applied. The domain of a Hole defines which rules can be applied. The domain is a bitvector, where the ith bit is set to true if the ith rule in the grammar can be applied. \n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.HoleReference","page":"HerbCore.jl Documentation","title":"HerbCore.HoleReference","text":"HoleReference\n\nContains a hole and the path to the hole from the root of the tree.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.RuleNode","page":"HerbCore.jl Documentation","title":"HerbCore.RuleNode","text":"RuleNode <: AbstractRuleNode\n\nA RuleNode represents a node in an expression tree. Each node corresponds to a certain rule in the Grammar. A RuleNode consists of:\n\nind: The index of the rule in the Grammar which this node is representing.\n_val: Field for storing immediately evaluated values\nchildren: The children of this node in the expression tree\n\ncompat: Compat\nEvaluate immediately functionality is not yet supported by most of Herb.jl.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.RuleNode-Tuple{Int64, Any}","page":"HerbCore.jl Documentation","title":"HerbCore.RuleNode","text":"RuleNode(ind::Int, _val::Any)\n\nCreate a RuleNode for the Grammar rule with index ind, _val as immediately evaluated value and no children\n\nwarning: Warning\nOnly use this constructor if you are absolutely certain that a rule is terminal and cannot have children. Use [RuleNode(ind::Int, grammar::Grammar)] for rules that might have children. In general, Holes should be used as a placeholder when the children of a node are not yet known. \n\ncompat: Compat\nEvaluate immediately functionality is not yet supported by most of Herb.jl.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.RuleNode-Tuple{Int64, Vector{AbstractRuleNode}}","page":"HerbCore.jl Documentation","title":"HerbCore.RuleNode","text":"RuleNode(ind::Int, children::Vector{AbstractRuleNode})\n\nCreate a RuleNode for the Grammar rule with index ind and children as subtrees.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Base.isless-Tuple{AbstractRuleNode, AbstractRuleNode}","page":"HerbCore.jl Documentation","title":"Base.isless","text":"Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode)::Bool\n\nCompares two RuleNodes. Returns true if the left RuleNode is less than the right RuleNode. Order is determined from the index of the RuleNodes. If both RuleNodes have the same index, a depth-first search is performed in both RuleNodes until nodes with a different index are found.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Base.length-Tuple{Hole}","page":"HerbCore.jl Documentation","title":"Base.length","text":"Base.length(root::RuleNode)\n\nReturn the number of nodes in the tree rooted at root. Holes don't count.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Base.length-Tuple{RuleNode}","page":"HerbCore.jl Documentation","title":"Base.length","text":"Base.length(root::RuleNode)\n\nReturn the number of nodes in the tree rooted at root. Holes don't count.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.contains_hole-Tuple{RuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.contains_hole","text":"contains_hole(rn::RuleNode) = any(contains_hole(c) for c ∈ rn.children)\n\nChecks if an AbstractRuleNode tree contains a Hole.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.depth-Tuple{RuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.depth","text":"depth(root::RuleNode)::Int\n\nReturn the depth of the AbstractRuleNode tree rooted at root. Holes don't count towards the depth.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.get_node_at_location-Tuple{RuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.get_node_at_location","text":"get_node_at_location(root::RuleNode, location::Vector{Int})\n\nRetrieves a RuleNode at the given location by reference. \n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.get_rulesequence-Tuple{RuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.get_rulesequence","text":"get_rulesequence(node::RuleNode, path::Vector{Int})\n\nExtract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.node_depth-Tuple{AbstractRuleNode, AbstractRuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.node_depth","text":"node_depth(root::AbstractRuleNode, node::AbstractRuleNode)::Int\n\nReturn the depth of node for an AbstractRuleNode tree rooted at root. Depth is 1 when root == node.\n\nwarning: Warning\nnode must be a subtree of root in order for this function to work.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.rulesoftype-Tuple{RuleNode, Set{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.rulesoftype","text":"rulesoftype(node::RuleNode, ruleset::Set{Int})\n\nReturns every rule in the ruleset that is also used in the AbstractRuleNode tree.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.rulesonleft-Tuple{RuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.rulesonleft","text":"rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}\n\nFinds all rules that are used in the left subtree defined by the path.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.swap_node-Tuple{AbstractRuleNode, AbstractRuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.swap_node","text":"swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})\n\nReplace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.swap_node-Tuple{RuleNode, RuleNode, Int64, RuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.swap_node","text":"swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)\n\nReplace child i of a node, a part of larger expr, with new_expr.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Index","page":"HerbCore.jl Documentation","title":"Index","text":"","category":"section"},{"location":"HerbCore/","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"","category":"page"},{"location":"HerbGrammar/#HerbGrammar_docs","page":"HerbGrammar.jl","title":"HerbGrammar.jl Documentation","text":"","category":"section"},{"location":"HerbGrammar/","page":"HerbGrammar.jl","title":"HerbGrammar.jl","text":"CurrentModule=HerbGrammar","category":"page"},{"location":"HerbGrammar/","page":"HerbGrammar.jl","title":"HerbGrammar.jl","text":"Modules = [HerbGrammar]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbGrammar/#HerbGrammar.ContextFreeGrammar","page":"HerbGrammar.jl","title":"HerbGrammar.ContextFreeGrammar","text":"ContextFreeGrammar <: Grammar\n\nRepresents a context-free grammar and its production rules. Consists of:\n\nrules::Vector{Any}: A list of RHS of rules (subexpressions).\ntypes::Vector{Symbol}: A list of LHS of rules (types, all symbols).\nisterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.\niseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.\nbytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.\ndomains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.\nchildtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. If a rule is terminal, the corresponding list is empty.\nlog_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. If the grammar is non-probabilistic, the list can be nothing.\n\nUse the @cfgrammar macro to create a ContextFreeGrammar object. Use the @pcfgrammar macro to create a ContextFreeGrammar object with probabilities. For context-sensitive grammars, see ContextSensitiveGrammar.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.ContextSensitiveGrammar","page":"HerbGrammar.jl","title":"HerbGrammar.ContextSensitiveGrammar","text":"ContextSensitiveGrammar <: Grammar\n\nRepresents a context-sensitive grammar. Extends Grammar with constraints.\n\nConsists of:\n\nrules::Vector{Any}: A list of RHS of rules (subexpressions).\ntypes::Vector{Symbol}: A list of LHS of rules (types, all symbols).\nisterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.\niseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.\nbytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.\ndomains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.\nchildtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. If a rule is terminal, the corresponding list is empty.\nlog_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. If the grammar is non-probabilistic, the list can be nothing.\nconstraints::Vector{Constraint}: A list of constraints that programs in this grammar have to abide.\n\nUse the @csgrammar macro to create a ContextSensitiveGrammar object. Use the @pcsgrammar macro to create a ContextSensitiveGrammar object with probabilities. For context-free grammars, see ContextFreeGrammar.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.NodeLoc","page":"HerbGrammar.jl","title":"HerbGrammar.NodeLoc","text":"NodeLoc A helper struct that points to a node in the tree via its parent such that the child can be easily swapped out. If i is 0 the node pointed to is the root node and parent is the node itself.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.SymbolTable","page":"HerbGrammar.jl","title":"HerbGrammar.SymbolTable","text":"SymbolTable(grammar::Grammar, mod::Module=Main)\n\nReturns a SymbolTable populated with a mapping from symbols in the Grammar to symbols in module mod or Main, if defined.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.SymbolTable-2","page":"HerbGrammar.jl","title":"HerbGrammar.SymbolTable","text":"SymbolTable\n\nData structure for mapping terminal symbols in the Grammar to their Julia interpretation.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.@cfgrammar-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.@cfgrammar","text":"@cfgrammar\n\nA macro for defining a ContextFreeGrammar. \n\nExample usage:\n\ngrammar = @cfgrammar begin\n\tR = x\n\tR = 1 | 2\n\tR = R + R\nend\n\nSyntax:\n\nLiterals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.\nVariables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.\nFunctions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).\nCombinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.\nIterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).\n\nRelated:\n\n@csgrammar uses the same syntax to create ContextSensitiveGrammars.\n@pcfgrammar uses a similar syntax to create probabilistic ContextFreeGrammars.\n\n\n\n\n\n","category":"macro"},{"location":"HerbGrammar/#HerbGrammar.@csgrammar-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.@csgrammar","text":"@csgrammar\n\nA macro for defining a ContextSensitiveGrammar. Constraints can be added afterwards using the addconstraint! function.\n\nExample usage:\n\ngrammar = @csgrammar begin\n\tR = x\n\tR = 1 | 2\n\tR = R + R\nend\n\nSyntax:\n\nLiterals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.\nVariables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.\nFunctions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).\nCombinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.\nIterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).\n\nRelated:\n\n@cfgrammar uses the same syntax to create ContextFreeGrammars.\n@pcsgrammar uses a similar syntax to create probabilistic ContextSensitiveGrammars.\n\n\n\n\n\n","category":"macro"},{"location":"HerbGrammar/#HerbGrammar.@pcfgrammar-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.@pcfgrammar","text":"@pcfgrammar\n\nA macro for defining a probabilistic ContextFreeGrammar. \n\nExample usage:\n\ngrammar = @pcfgrammar begin\n\t0.5 : R = x\n\t0.3 : R = 1 | 2\n\t0.2 : R = R + R\nend\n\nSyntax:\n\nThe syntax of rules is identical to the syntax used by @cfgrammar:\n\nLiterals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.\nVariables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.\nFunctions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).\nCombinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.\nIterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).\n\nEvery rule is also prefixed with a probability. Rules and probabilities are separated using the : symbol. If multiple rules are defined on a single line, the probability is equally divided between the rules. The sum of probabilities for all rules of a certain non-terminal symbol should be equal to 1. The probabilities are automatically scaled if this isn't the case.\n\nRelated:\n\n@pcsgrammar uses the same syntax to create probabilistic ContextSensitiveGrammars.\n@cfgrammar uses a similar syntax to create non-probabilistic ContextFreeGrammars.\n\n\n\n\n\n","category":"macro"},{"location":"HerbGrammar/#HerbGrammar.@pcsgrammar-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.@pcsgrammar","text":"@pcsgrammar\n\nA macro for defining a probabilistic ContextSensitiveGrammar. \n\nExample usage:\n\ngrammar = @pcsgrammar begin\n\t0.5 : R = x\n\t0.3 : R = 1 | 2\n\t0.2 : R = R + R\nend\n\nSyntax:\n\nThe syntax of rules is identical to the syntax used by @csgrammar:\n\nLiterals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.\nVariables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.\nFunctions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).\nCombinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.\nIterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).\n\nEvery rule is also prefixed with a probability. Rules and probabilities are separated using the : symbol. If multiple rules are defined on a single line, the probability is equally divided between the rules. The sum of probabilities for all rules of a certain non-terminal symbol should be equal to 1. The probabilities are automatically scaled if this isn't the case.\n\nRelated:\n\n@pcfgrammar uses the same syntax to create probabilistic ContextFreeGrammars.\n@csgrammar uses a similar syntax to create non-probabilistic ContextSensitiveGrammars.\n\n\n\n\n\n","category":"macro"},{"location":"HerbGrammar/#Base.get-Tuple{RuleNode, NodeLoc}","page":"HerbGrammar.jl","title":"Base.get","text":"get(root::RuleNode, loc::NodeLoc) Obtain the node pointed to by loc.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#Base.insert!-Tuple{RuleNode, NodeLoc, RuleNode}","page":"HerbGrammar.jl","title":"Base.insert!","text":"insert!(loc::NodeLoc, rulenode::RuleNode) Replaces the subtree pointed to by loc with the given rulenode.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.add_rule!-Tuple{Grammar, Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.add_rule!","text":"add_rule!(g::Grammar, e::Expr)\n\nAdds a rule to the grammar. \n\nUsage:\n\n\tadd_rule!(grammar, :(\"Real = Real + Real\"))\n\nThe syntax is identical to the syntax of @csgrammar and @cfgrammar, but only single rules are supported.\n\nwarning: Warning\nCalls to this function are ignored if a rule is already in the grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.addconstraint!-Tuple{ContextSensitiveGrammar, Constraint}","page":"HerbGrammar.jl","title":"HerbGrammar.addconstraint!","text":"addconstraint!(grammar::ContextSensitiveGrammar, c::Constraint)\n\nAdds a Constraint to a ContextSensitiveGrammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.cfg2csg-Tuple{ContextFreeGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.cfg2csg","text":"cfg2csg(g::ContextFreeGrammar)::ContextSensitiveGrammar\n\nConverts a ContextFreeGrammar to a ContextSensitiveGrammar without any Constraints.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.child_types-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.child_types","text":"child_types(grammar::Grammar, rule_index::Int)\n\nReturns the types of the children (nonterminals) of the production rule at rule_index.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.child_types-Tuple{Grammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.child_types","text":"child_types(grammar::Grammar, node::RuleNode)\n\nReturns the list of child types (nonterminal symbols) in the production rule used by node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.cleanup_removed_rules!-Tuple{Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.cleanup_removed_rules!","text":"cleanup_removed_rules!(g::Grammar)\n\nRemoves any placeholders for previously deleted rules. This means that indices get shifted.\n\nwarning: Warning\nWhen indices are shifted, this grammar can no longer be used to interpret AbstractRuleNode trees created before the call to this function. These trees become meaningless. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.clearconstraints!-Tuple{ContextSensitiveGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.clearconstraints!","text":"Clear all constraints from the grammar\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.containedin-Tuple{Vector, Vector}","page":"HerbGrammar.jl","title":"HerbGrammar.containedin","text":"containedin(vec1::Vector, vec2::Vector)\n\nChecks if elements of vec1 are contained in vec2 in the same order (possibly with elements in between)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.contains_returntype","page":"HerbGrammar.jl","title":"HerbGrammar.contains_returntype","text":"contains_returntype(node::RuleNode, grammar::Grammar, sym::Symbol, maxdepth::Int=typemax(Int))\n\nReturns true if the tree rooted at node contains at least one node at depth less than maxdepth with the given return type or nonterminal symbol.\n\n\n\n\n\n","category":"function"},{"location":"HerbGrammar/#HerbGrammar.expr2cfgrammar-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.expr2cfgrammar","text":"expr2cfgrammar(ex::Expr)::ContextFreeGrammar\n\nA function for converting an Expr to a ContextFreeGrammar. If the expression is hardcoded, you should use the @cfgrammar macro. Only expressions in the correct format (see @cfgrammar) can be converted.\n\nExample usage:\n\ngrammar = expr2cfgrammar(\n\tbegin\n\t\tR = x\n\t\tR = 1 | 2\n\t\tR = R + R\n\tend\n)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.expr2csgrammar-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.expr2csgrammar","text":"expr2csgrammar(ex::Expr)::ContextSensitiveGrammar\n\nA function for converting an Expr to a ContextSensitiveGrammar. If the expression is hardcoded, you should use the @csgrammar macro. Only expressions in the correct format (see @csgrammar) can be converted.\n\nExample usage:\n\ngrammar = expr2csgrammar(\n\tbegin\n\t\tR = x\n\t\tR = 1 | 2\n\t\tR = R + R\n\tend\n)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.expr2pcfgrammar-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.expr2pcfgrammar","text":"Function for converting an Expr to a ContextFreeGrammar with probabilities. If the expression is hardcoded, you should use the @pcfgrammar macro. Only expressions in the correct format (see @pcfgrammar) can be converted.\n\nExample usage:\n\ngrammar = expr2pcsgrammar(\n\tbegin\n\t\t0.5 : R = x\n\t\t0.3 : R = 1 | 2\n\t\t0.2 : R = R + R\n\tend\n)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.expr2pcsgrammar-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.expr2pcsgrammar","text":"Function for converting an Expr to a ContextSensitiveGrammar with probabilities. If the expression is hardcoded, you should use the @pcsgrammar macro. Only expressions in the correct format (see @pcsgrammar) can be converted.\n\nExample usage:\n\ngrammar = expr2pcsgrammar(\n\tbegin\n\t\t0.5 : R = x\n\t\t0.3 : R = 1 | 2\n\t\t0.2 : R = R + R\n\tend\n)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_childtypes-Tuple{Any, AbstractVector{Symbol}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_childtypes","text":"get_childtypes(rule::Any, types::AbstractVector{Symbol})\n\nReturns the child types/nonterminals of a production rule.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_domain-Tuple{Grammar, Symbol}","page":"HerbGrammar.jl","title":"HerbGrammar.get_domain","text":"get_domain(g::Grammar, type::Symbol)::BitVector\n\nReturns the domain for the hole of a certain type as a BitVector of the same length as the number of rules in the grammar. Bit i is set to true iff rule i is of type type.\n\ninfo: Info\nSince this function can be intensively used when exploring a program space defined by a grammar, the outcomes of this function are precomputed and stored in the domains field in a Grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_domain-Tuple{Grammar, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_domain","text":"get_domain(g::Grammar, rules::Vector{Int})::BitVector\n\nTakes a domain rules defined as a vector of ints and converts it to a domain defined as a BitVector.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_node_at_location-Tuple{RuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_node_at_location","text":"get_node_at_location(root::RuleNode, location::Vector{Int})\n\nRetrieves a RuleNode at the given location by reference. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_rulesequence-Tuple{RuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_rulesequence","text":"get_rulesequence(node::RuleNode, path::Vector{Int})\n\nExtract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.has_children-Tuple{RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.has_children","text":"has_children(node::RuleNode)\n\nReturns true if node has children\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iscomplete-Tuple{Grammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.iscomplete","text":"iscomplete(grammar::Grammar, node::RuleNode)\n\nReturns true if the expression represented by the RuleNode is a complete expression, meaning that it is fully defined and doesn't have any Holes.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iseval-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.iseval","text":"iseval(rule)\n\nReturns true if the rule is the special evaluate immediately function, i.e., _()\n\ncompat: Compat\nevaluate immediately functionality is not yet supported by most of Herb.jl\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iseval-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.iseval","text":"iseval(grammar::Grammar, index::Int)::Bool\n\nReturns true if the production rule at rule_index contains the special _() eval function.\n\ncompat: Compat\nevaluate immediately functionality is not yet supported by most of Herb.jl\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iseval-Tuple{Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.iseval","text":"iseval(grammar::Grammar)::Bool\n\nReturns true if any production rules in grammar contain the special _() eval function.\n\ncompat: Compat\nevaluate immediately functionality is not yet supported by most of Herb.jl\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isprobabilistic-Tuple{Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.isprobabilistic","text":"isprobabilistic(grammar::Grammar)::Bool\n\nFunction returns whether a Grammar is probabilistic.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isterminal-Tuple{Any, AbstractVector{Symbol}}","page":"HerbGrammar.jl","title":"HerbGrammar.isterminal","text":"isterminal(rule::Any, types::AbstractVector{Symbol})\n\nReturns true if the rule is terminal, i.e., it does not contain any of the types in the provided vector. For example, :(x) is terminal, and :(1+1) is terminal, but :(Real + Real) is typically not.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isterminal-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.isterminal","text":"isterminal(grammar::Grammar, rule_index::Int)::Bool\n\nReturns true if the production rule at rule_index is terminal, i.e., does not contain any nonterminal symbols.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isterminal-Tuple{Grammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.isterminal","text":"isterminal(grammar::Grammar, node::RuleNode)::Bool\n\nReturns true if the production rule used by node is terminal, i.e., does not contain any nonterminal symbols.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isvariable-Tuple{Grammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.isvariable","text":"isvariable(grammar::Grammar, node::RuleNode)::Bool\n\nReturns true if the rule used by node represents a variable.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.log_probability-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.log_probability","text":"log_probability(grammar::Grammar, index::Int)::Real\n\nReturns the log probability for the rule at index in the grammar.\n\nwarning: Warning\nIf the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.max_arity-Tuple{Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.max_arity","text":"max_arity(grammar::Grammar)::Int\n\nReturns the maximum arity (number of children) over all production rules in the Grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.mindepth-Tuple{Grammar, Symbol, AbstractVector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.mindepth","text":"mindepth(grammar::Grammar, typ::Symbol, dmap::AbstractVector{Int})\n\nReturns the minimum depth achievable for a given nonterminal symbol. The minimum depth is the depth of the lowest tree that can be made using typ as a start symbol. dmap can be obtained from mindepth_map.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.mindepth_map-Tuple{Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.mindepth_map","text":"mindepth_map(grammar::Grammar)\n\nReturns the minimum depth achievable for each production rule in the Grammar. In other words, this function finds the depths of the lowest trees that can be made using each of the available production rules as a root.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.nchildren-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.nchildren","text":"nchildren(grammar::Grammar, rule_index::Int)::Int\n\nReturns the number of children (nonterminals) of the production rule at rule_index.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.nchildren-Tuple{Grammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.nchildren","text":"nchildren(grammar::Grammar, node::RuleNode)::Int\n\nReturns the number of children in the production rule used by node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.nonterminals-Tuple{Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.nonterminals","text":"nonterminals(grammar::Grammar)::Vector{Symbol}\n\nReturns a list of the nonterminals or types in the Grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.probability-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.probability","text":"probability(grammar::Grammar, index::Int)::Real\n\nReturn the probability for a rule in the grammar. Use log_probability whenever possible.\n\nwarning: Warning\nIf the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.read_cfg-Tuple{AbstractString}","page":"HerbGrammar.jl","title":"HerbGrammar.read_cfg","text":"read_cfg(filepath::AbstractString)::ContextFreeGrammar\n\nReads a ContextFreeGrammar from the file provided in filepath.\n\ndanger: Danger\nOnly open trusted grammars. Parts of the grammar can be passed to Julia's eval function. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.read_csg-Tuple{AbstractString, AbstractString}","page":"HerbGrammar.jl","title":"HerbGrammar.read_csg","text":"read_csg(grammarpath::AbstractString, constraintspath::AbstractString)::ContextSensitiveGrammar\n\nReads a ContextSensitiveGrammar from the files at grammarpath and constraintspath. The grammar path may also point to a ContextFreeGrammar.\n\ndanger: Danger\nOnly open trusted grammars. Parts of the grammar can be passed to Julia's eval function. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.read_pcfg-Tuple{AbstractString}","page":"HerbGrammar.jl","title":"HerbGrammar.read_pcfg","text":"read_pcfg(filepath::AbstractString)::ContextFreeGrammar\n\nReads a probabilistic ContextFreeGrammar from a file provided in filepath.\n\ndanger: Danger\nOnly open trusted grammars. Parts of the grammar can be passed to Julia's eval function. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.read_pcsg-Tuple{AbstractString, AbstractString}","page":"HerbGrammar.jl","title":"HerbGrammar.read_pcsg","text":"read_pcsg(grammarpath::AbstractString, constraintspath::AbstractString)::ContextSensitiveGrammar\n\nReads a probabilistic ContextSensitiveGrammar from the files at grammarpath and constraintspath. The grammar path may also point to a ContextFreeGrammar.\n\ndanger: Danger\nOnly open trusted grammars. Parts of the grammar can be passed to Julia's eval function. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.remove_rule!-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.remove_rule!","text":"remove_rule!(g::Grammar, idx::Int)\n\nRemoves the rule corresponding to idx from the grammar. In order to avoid shifting indices, the rule is replaced with nothing, and all other data structures are updated accordingly.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.return_type-Tuple{Grammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.return_type","text":"return_type(grammar::Grammar, rule_index::Int)::Symbol\n\nReturns the type of the production rule at rule_index.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.return_type-Tuple{Grammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.return_type","text":"return_type(grammar::Grammar, node::RuleNode)\n\nGives the return type or nonterminal symbol in the production rule used by node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.root_node_loc-Tuple{RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.root_node_loc","text":"rootnodeloc(root::RuleNode) Returns a NodeLoc pointing to the root node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulenode2expr-Tuple{RuleNode, Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.rulenode2expr","text":"rulenode2expr(rulenode::RuleNode, grammar::Grammar)\n\nConverts a RuleNode into a Julia expression corresponding to the rule definitions in the grammar. The returned expression can be evaluated with Julia semantics using eval().\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulenode_log_probability-Tuple{RuleNode, Grammar}","page":"HerbGrammar.jl","title":"HerbGrammar.rulenode_log_probability","text":"Calculates the log probability associated with a rulenode in a probabilistic grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesoftype-Tuple{RuleNode, Grammar, Symbol, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesoftype","text":"rulesoftype(node::RuleNode, grammar::Grammar, ruletype::Symbol, ignoreNode::RuleNode)\n\nReturns every rule of nonterminal symbol ruletype that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.\n\nwarning: Warning\nThe ignoreNode must be a subtree of node for it to have an effect.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesoftype-Tuple{RuleNode, Grammar, Symbol}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesoftype","text":"rulesoftype(node::RuleNode, grammar::Grammar, ruletype::Symbol)\n\nReturns every rule of nonterminal symbol ruletype that is also used in the AbstractRuleNode tree.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesoftype-Tuple{RuleNode, Set{Int64}, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesoftype","text":"rulesoftype(node::RuleNode, ruleset::Set{Int}, ignoreNode::RuleNode)\n\nReturns every rule in the ruleset that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.\n\nwarning: Warning\nThe ignoreNode must be a subtree of node for it to have an effect.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesonleft-Tuple{RuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesonleft","text":"rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}\n\nFinds all rules that are used in the left subtree defined by the path.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.store_cfg-Tuple{AbstractString, ContextFreeGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.store_cfg","text":"store_cfg(filepath::AbstractString, grammar::ContextFreeGrammar)\n\nWrites a ContextFreeGrammar to the file provided by filepath.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.store_csg-Tuple{AbstractString, AbstractString, ContextSensitiveGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.store_csg","text":"store_csg(grammarpath::AbstractString, constraintspath::AbstractString, g::ContextSensitiveGrammar)\n\nWrites a ContextSensitiveGrammar to the files at grammarpath and constraintspath. The grammarpath file will contain a ContextSensitiveGrammar definition, and the constraintspath file will contain the Constraints of the ContextSensitiveGrammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.subsequenceof-Tuple{Vector{Int64}, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.subsequenceof","text":"subsequenceof(vec1::Vector{Int}, vec2::Vector{Int})\n\nChecks if vec1 is a subsequence of vec2.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.swap_node-Tuple{AbstractRuleNode, AbstractRuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.swap_node","text":"swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})\n\nReplace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.swap_node-Tuple{RuleNode, RuleNode, Int64, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.swap_node","text":"swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)\n\nReplace child i of a node, a part of larger expr, with new_expr.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#Index","page":"HerbGrammar.jl","title":"Index","text":"","category":"section"},{"location":"HerbGrammar/","page":"HerbGrammar.jl","title":"HerbGrammar.jl","text":"","category":"page"},{"location":"HerbConstraints/#HerbConstraints_docs","page":"HerbConstraints.jl","title":"HerbConstraints.jl Documentation","text":"","category":"section"},{"location":"HerbConstraints/","page":"HerbConstraints.jl","title":"HerbConstraints.jl","text":"CurrentModule=HerbConstraints","category":"page"},{"location":"HerbConstraints/","page":"HerbConstraints.jl","title":"HerbConstraints.jl","text":"Modules = [HerbConstraints]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbConstraints/#HerbConstraints.AbstractMatchNode","page":"HerbConstraints.jl","title":"HerbConstraints.AbstractMatchNode","text":"abstract type AbstractMatchNode\n\nTree structure to which rulenode trees can be matched. Consists of MatchNodes, which can match a specific RuleNode, and MatchVars, which is a variable that can be filled in with any RuleNode.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.ComesAfter","page":"HerbConstraints.jl","title":"HerbConstraints.ComesAfter","text":"ComesAfter <: PropagatorConstraint\n\nA ComesAfter constraint is a PropagatorConstraint containing the following:\n\nrule::Int: A reference to a rule in the grammar\npredecessors: A list of rules in the grammar\n\nThis Constraint enforces that the rule can only be applied if every rule in predecessors is used in the path from the root of the tree to the current hole in the order that they are given. Even though the rules must be in order, there might be other rules inbetween.\n\nFor example, consider the tree 1(a, 2(b, 3(c, d)))):\n\nComesAfter(4, [2, 3]) would enforce that rule 4 can only be used if 2 and 3 are used in the path from the root in that order. Therefore, only hole c and d can be filled with 4.\nComesAfter(4, [1, 3]) also allows c and d to be filled, since 1 and 3 are still used in the correct order. It does not matter that 2 is also used in the path to the root.\nComesAfter(4, [3, 2]) does not allow any hole to be filled with 4, since either the predecessors are either not in the path or in the wrong order for each of the holes. \n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.ComesAfter-Tuple{Int64, Int64}","page":"HerbConstraints.jl","title":"HerbConstraints.ComesAfter","text":"ComesAfter(rule::Int, predecessor::Int)\n\nCreates a ComesAfter constraint with only a single predecessor. \n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.Forbidden","page":"HerbConstraints.jl","title":"HerbConstraints.Forbidden","text":"Forbidden <: PropagatorConstraint\n\nThis [PropagatorConstraint] forbids any subtree that matches the pattern given by tree to be generated. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the Grammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical. Any rule in the domain that makes the match attempt successful is removed.\n\nFor example, consider the tree 1(a, 2(b, 3(c, 4)))):\n\nForbidden(MatchNode(3, [MatchNode(5), MatchNode(4)])) forbids c to be filled with 5.\nForbidden(MatchNode(3, [MatchVar(:v), MatchNode(4)])) forbids c to be filled, since a [MatchVar] can match any rule, thus making the match attempt successful for the entire domain of c. Therefore, this tree invalid.\nForbidden(MatchNode(3, [MatchVar(:v), MatchVar(:v)])) forbids c to be filled with 4, since that would make both assignments to v equal, which causes a successful match.\n\nwarning: Warning\nThe Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.ForbiddenPath","page":"HerbConstraints.jl","title":"HerbConstraints.ForbiddenPath","text":"ForbiddenPath <: PropagatorConstraint\n\nA [PropagatorConstraint] that forbids a certain derivation sequence. sequence defines the forbidden sequence. Each rule that would complete the sequence when expanding a Hole in an AbstractRuleNode tree is removed from the domain. The derivation sequence is the path from the root to the hole.\n\nFor example, consider the tree 1(a, 2(b, 3(c, d)))):\n\nForbiddenPath([1, 2, 4]) enforces that rule 4 cannot be applied at b, since it completes the sequence. However, it can be applied at a, c and d.\nForbiddenPath([3, 1]) enforces that rule 1 cannot be applied at c or d.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.GrammarContext","page":"HerbConstraints.jl","title":"HerbConstraints.GrammarContext","text":"mutable struct GrammarContext\n\nStructure used to track the context. Contains: \t- the expression being modified \t- the path to the hole that is being expanded, represented as a sequence of child indices. \t e.g., [2, 1] would point to the first child of the second child of the root. \t- a vector with local constraints that should be propagated upon expansion.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalConstraint","page":"HerbConstraints.jl","title":"HerbConstraints.LocalConstraint","text":"abstract type LocalConstraint <: Constraint\n\nAbstract type representing all local constraints. Local constraints correspond to a specific (partial) AbstractRuleNode tree. Each local constraint contains a path to a specific location in the tree. Each local constraint has an implementation of a propagate-function that takes\n\nthe LocalConstraint\na Grammar\na GrammarContext, which most importantly contains the tree and the location in the tree where propagation should take place.\nThe domain which the propagate-function prunes. \n\nThe propagate-function returns a tuple containing\n\nThe pruned domain\nA list of new LocalConstraints\n\nwarning: Warning\nBy default, LocalConstraints are only propagated once. Constraints that have to be propagated more frequently should return themselves in the list of new local constraints.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalForbidden","page":"HerbConstraints.jl","title":"HerbConstraints.LocalForbidden","text":"LocalForbidden\n\nForbids the a subtree that matches the MatchNode tree to be generated at the location provided by the path. Use a Forbidden constraint for enforcing this throughout the entire search space.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalOneOf","page":"HerbConstraints.jl","title":"HerbConstraints.LocalOneOf","text":"Meta-constraint that enforces the disjunction of its given constraints.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalOrdered","page":"HerbConstraints.jl","title":"HerbConstraints.LocalOrdered","text":"Enforces an order over two or more subtrees that fill the variables specified in order when the pattern is applied at the location given by path. Use an Ordered constraint for enforcing this throughout the entire search space.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.MatchFail","page":"HerbConstraints.jl","title":"HerbConstraints.MatchFail","text":"@enum MatchFail hardfail softfail\n\nThis enum is used for distinguishing between two types of failures when trying to match a RuleNode either with another RuleNode or with an AbstractMatchNode\n\nHardfail means that there is no match, and there is no way to fill in the holes to get a match.\nSoftfail means that there is no match, but there might be a way to fill the holes that results in a match.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.MatchNode","page":"HerbConstraints.jl","title":"HerbConstraints.MatchNode","text":"struct MatchNode <: AbstractMatchNode\n\nMatch a specific rulenode, where the grammar rule index is rule_ind and children matches the children of the RuleNode. Example usage:\n\nMatchNode(3, [MatchNode(1), MatchNode(2)])\n\nThis matches RuleNode(3, [RuleNode(1), RuleNode(2)])\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.MatchVar","page":"HerbConstraints.jl","title":"HerbConstraints.MatchVar","text":"struct MatchVar <: AbstractMatchNode\n\nMatches anything and assigns it to a variable. The ForbiddenTree constraint will not match if identical variable symbols match to different trees. Example usage:\n\nMatchNode(3, [MatchVar(:x), MatchVar(:x)])\n\nThis matches RuleNode(3, [RuleNode(1), RuleNode(1)]), RuleNode(3, [RuleNode(2), RuleNode(2)]), etc.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.OneOf","page":"HerbConstraints.jl","title":"HerbConstraints.OneOf","text":"Meta-constraint that enforces the disjunction of its given constraints.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.Ordered","page":"HerbConstraints.jl","title":"HerbConstraints.Ordered","text":"Ordered <: PropagatorConstraint\n\nA PropagatorConstraint that enforces a specific order in MatchVar assignments in the pattern defined by tree. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the Grammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical.\n\nThe order defines an order between the variable assignments. For example, if the order is [x, y], the constraint will require the assignment to x to be less than or equal to the assignment to y. The order is recursively defined by RuleNode indices. For more information, see Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode).\n\nFor example, consider the tree 1(a, 2(b, 3(c, 4)))):\n\nOrdered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:v, :w]) removes every rule with an index of 5 or greater from the domain of c, since that would make the index of the assignment to v greater than the index of the assignment to w, violating the order.\nOrdered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:w, :v]) removes every rule with an index of 4 or less from the domain of c, since that would make the index of the assignment to v less than the index of the assignment to w, violating the order.\n\nwarning: Warning\nThe Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.PropagatorConstraint","page":"HerbConstraints.jl","title":"HerbConstraints.PropagatorConstraint","text":"PropagatorConstraint <: Constraint\n\nAbstract type representing all propagator constraints. Each propagator constraint has an implementation of a propagate-function that takes\n\nthe PropagatorConstraint\na Grammar\na GrammarContext, which most importantly contains the tree and the location in the tree where propagation should take place.\nThe domain which the propagate-function prunes. \n\nThe propagate-function returns a tuple containing\n\nThe pruned domain\nA list of new LocalConstraints\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.RequireOnLeft","page":"HerbConstraints.jl","title":"HerbConstraints.RequireOnLeft","text":"Rules have to be used in the specified order. That is, rule at index K can only be used if rules at indices [1...K-1] are used in the left subtree of the current expression\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.@csgrammar_annotated-Tuple{Any}","page":"HerbConstraints.jl","title":"HerbConstraints.@csgrammar_annotated","text":"@csgrammar_annotated Define an annotated grammar and return it as a ContextSensitiveGrammar. Allows for adding optional annotations per rule. As well as that, allows for adding optional labels per rule, which can be referenced in annotations. Syntax is backwards-compatible with @csgrammar. Examples:\n\ng₁ = @csgrammar_annotated begin\n Element = 1\n Element = x\n Element = Element + Element := commutative\n Element = Element * Element := (commutative, transitive)\nend\n\ng₁ = @csgrammar_annotated begin\n Element = 1\n Element = x\n Element = Element + Element := forbidden_path([3, 1])\n Element = Element * Element := (commutative, transitive)\nend\n\ng₁ = @csgrammar_annotated begin\n one:: Element = 1\n variable:: Element = x\n addition:: Element = Element + Element := (\n commutative,\n transitive,\n forbidden_path([:addition, :one]) || forbidden_path([:one, :variable])\n )\n multiplication:: Element = Element * Element := (commutative, transitive)\nend\n\n\n\n\n\n","category":"macro"},{"location":"HerbConstraints/#Base.show-Tuple{IO, MatchNode}","page":"HerbConstraints.jl","title":"Base.show","text":"Base.show(io::IO, node::MatchNode; separator=\",\", last_child::Bool=true)\n\nPrints a found MatchNode given an and the respective children to IO. \n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#Base.show-Tuple{IO, MatchVar}","page":"HerbConstraints.jl","title":"Base.show","text":"Base.show(io::IO, node::MatchVar; separator=\",\", last_child::Bool=true)\n\nPrints a matching variable assignment described by MatchVar to IO.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(expr::Expr, pattern::MatchNode, grammar::Grammar, j=0)\n\nInternal function for matchnode2expr, recursively iterating over a matched pattern and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr-2","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(typ::Symbol, pattern::MatchNode, grammar::Grammar, j=0)\n\nInternal function for matchnode2expr, returning the matched translated symbol. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr-3","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(typ::Symbol, pattern::MatchVar, grammar::Grammar, j=0)\n\nInternal function for matchnode2expr. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr-4","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(expr::Expr, pattern::MatchVar, grammar::Grammar, j=0)\n\nInternal function for matchnode2expr, recursively iterating over a matched variable and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._pattern_match-Tuple{RuleNode, MatchNode, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match","text":"_pattern_match(rn::RuleNode, mn::MatchNode, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}\n\nTries to match RuleNode rn with MatchNode mn. Modifies the variable assignment dictionary vars. Returns nothing if the match is successful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match-Tuple{RuleNode, MatchVar, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match","text":"_pattern_match(rn::RuleNode, mv::MatchVar, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}\n\nMatching RuleNode rn with MatchVar mv. If the variable is already assigned, the rulenode is matched with the specific variable value. Returns nothing if the match is succesful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{Hole, MatchNode, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(::Hole, mn::MatchNode, hole_location::Vector{Int}, ::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nMatches the Hole with the given MatchNode. \n\nTODO check this behaviour?\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{Hole, MatchVar, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(::Hole, mn::MatchNode, hole_location::Vector{Int}, ::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nMatches the Hole with the given MatchVar, similar to _pattern_match_with_hole.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{RuleNode, MatchNode, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(rn::RuleNode, mn::MatchNode, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nTries to match RuleNode rn with MatchNode mn and fill in the domain of the hole at hole_location. Returns if match is successful either:\n\nThe id for the node which fills the hole\nA symbol for the variable that fills the hole\nA tuple containing:\nThe variable that matched (the subtree containing) the hole\nThe location of the hole in this subtree\n\nIf the match is unsuccessful, it returns:\n\nhardfail if there are no holes that can be filled in such a way that the match will become succesful\nsoftfail if the match could become successful if the holes are filled in a certain way\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{RuleNode, MatchVar, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(rn::RuleNode, mv::MatchVar, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nTries to match RuleNode rn with MatchVar mv and fill in the domain of the hole at hole_location. If the variable name is already assigned in vars, the rulenode is matched with the hole. Otherwise the variable and the hole location are returned.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._rulenode_compare-Tuple{RuleNode, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints._rulenode_compare","text":"Returns -1 if rn₁ < rn₂\nReturns 0 if rn₁ == rn₂ \nReturns 1 if rn₁ > rn₂\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._rulenode_match_with_hole-Tuple{RuleNode, RuleNode, Vector{Int64}}","page":"HerbConstraints.jl","title":"HerbConstraints._rulenode_match_with_hole","text":"_rulenode_match_with_hole(rn₁::RuleNode, rn₂::RuleNode, hole_location::Vector{Int})::Union{Int, MatchFail}\n\nMatches two rulenodes. Returns how to fill in the hole in rn₁ to make it match rn₂ if:\n\nrn₁ has a single hole at the provided location\nrn₂ doesn't have any holes\nrn₁ matches rn₂ apart from the single hole location.\n\nIf the match fails, it returns whether it is a softfail or a hardfail (see MatchFail docstring)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.addparent!-Tuple{GrammarContext, Int64}","page":"HerbConstraints.jl","title":"HerbConstraints.addparent!","text":"addparent!(context::GrammarContext, parent::Int)\n\nAdds a parent to the context. The parent is defined by the grammar rule id.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.annotation2constraint-Tuple{Any, Int64, Vector{String}}","page":"HerbConstraints.jl","title":"HerbConstraints.annotation2constraint","text":"Converts an annotation to a constraint. commutative: creates an Ordered constraint transitive: creates an (incorrect) Forbidden constraint forbidden_path(path::Vector{Union{Symbol, Int}}): creates a ForbiddenPath constraint with the original rule included ... || ...: creates a OneOf constraint (also works with ... || ... || ... et cetera, though not very performant)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{ComesAfter, Grammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{Forbidden, Grammar, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"check_tree(c::Forbidden, g::Grammar, tree::RuleNode)::Bool\n\nChecks if the given AbstractRuleNode tree abides the Forbidden constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{ForbiddenPath, Grammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{HerbConstraints.Condition, Grammar, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{OneOf, Grammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{Ordered, Grammar, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"check_tree(c::Ordered, g::Grammar, tree::RuleNode)::Bool\n\nChecks if the given AbstractRuleNode tree abides the Ordered constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{RequireOnLeft, Grammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.copy_and_insert-Tuple{GrammarContext, Int64}","page":"HerbConstraints.jl","title":"HerbConstraints.copy_and_insert","text":"copy_and_insert(old_context::GrammarContext, parent::Int)\n\nCopies the given context and insert the parent in the node location.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.make_smaller_or_equal-Tuple{RuleNode, RuleNode, Vector{Int64}, Vector{Int64}}","page":"HerbConstraints.jl","title":"HerbConstraints.make_smaller_or_equal","text":"Filters the domain of the hole at hole_location in rn₁ to make rn₁ be ordered before rn₂. Returns the filtered domain, and a boolean indicating if this constraint can be deleted.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.matchnode2expr-Tuple{MatchNode, Grammar}","page":"HerbConstraints.jl","title":"HerbConstraints.matchnode2expr","text":"matchnode2expr(pattern::MatchNode, grammar::Grammar)\n\nConverts a MatchNode tree into a Julia expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.matchnode2expr-Tuple{MatchVar, Grammar}","page":"HerbConstraints.jl","title":"HerbConstraints.matchnode2expr","text":"matchnode2expr(pattern::MatchVar, grammar::Grammar)\n\nConverts a MatchVar into an expression by returning the variable directly. This is primarily useful for pretty-printing a pattern.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{Forbidden, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"propagate(c::Forbidden, g::Grammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}\n\nPropagates the Forbidden constraint. It removes the rules from the domain that would complete the forbidden tree.\n\nwarning: Warning\nThe Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{ForbiddenPath, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the ForbiddenPath constraint. It removes the elements from the domain that would complete the forbidden sequence.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{HerbConstraints.LocalOneOf, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the LocalOneOf constraint. It enforces that at least one of its given constraints hold.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{LocalForbidden, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the LocalForbidden constraint. It removes rules from the domain that would make the RuleNode at the given path match the pattern defined by the MatchNode.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{LocalOrdered, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the LocalOrdered constraint. It removes rules from the domain that would violate the order of variables as defined in the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{OneOf, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the OneOf constraint. It enforces that at least one of its given constraints hold.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{Ordered, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"propagate(c::Ordered, g::Grammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}\n\nPropagates the Ordered constraint. Any rule that violates the order as defined by the contraint is removed from the domain.\n\nwarning: Warning\nThe Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{RequireOnLeft, Grammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the RequireOnLeft constraint. It removes every element from the domain that does not have a necessary predecessor in the left subtree.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#Index","page":"HerbConstraints.jl","title":"Index","text":"","category":"section"},{"location":"HerbConstraints/","page":"HerbConstraints.jl","title":"HerbConstraints.jl","text":"","category":"page"},{"location":"tutorials/advanced_search/#Getting-started","page":"Advanced Search Procedures","title":"Getting started","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"You can either paste this code into the Julia REPL or run it using the advanced_search.ipynb notebook. Alternatively you can copy the code into a file like get_started.jl, followed by running julia get_started.jl.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"To start, we import the necessary packages.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"using HerbGrammar, HerbData, HerbSearch, HerbInterpret","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We start with the same simple grammar from the main file get_started.md.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g = @cfgrammar begin\n Number = |(1:2)\n Number = x\n Number = Number + Number\n Number = Number * Number\nend","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We use a simple problem.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":" problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])","category":"page"},{"location":"tutorials/advanced_search/#Parameters","page":"Advanced Search Procedures","title":"Parameters","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We can use a search strategy, where we can specify different parameters. For example, by setting the max_depth, we limit the depth of the search. In the next example, we can see the effect of the depth on the number of allocations considered. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"solution = @time search(g, problem, :Number, max_depth=3)\n>>> 0.003284 seconds (50.08 k allocations: 2.504 MiB)\nprintln(solution)\n>>> (x + 1) + x\n\nsolution = @time search(g, problem, :Number, max_depth=6)\n>>> 0.005696 seconds (115.28 k allocations: 5.910 MiB)\nprintln(solution)\n>>> (1 + x) + x","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Another parameter to use is max_enumerations, which limits the number of programs that can be tested at evaluation. We can see the number of enumerations necessary to solve a simple problem in the next example.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"for i in range(1, 50)\n println(i, \" enumerations\")\n solution = @time search(g, problem, :Number, max_enumerations=i)\n println(solution)\nend\n\n>>> ....\n>>> 23 enums: nothing\n>>> 0.010223 seconds (117.01 k allocations: 5.935 MiB, 44.23% gc time)\n>>> 24 enums: (1 + x) + x\n>>> 0.005305 seconds (117.01 k allocations: 5.935 MiB)\n>>> 25 enums: (1 + x) + x\n>>> 0.005381 seconds (117.01 k allocations: 5.935 MiB)\n>>> ...","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We see that only when i >= 24, there is a result. After that, increasing i does not have any effect on the number of allocations. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"A final parameter we consider here is allow_evaluation_errors, which is false by default. When this is set to true, the program will still run even when an exception is thrown during evaluation. To see the effect of this, we create a new grammar. We can also retrieve the error together with the solution from the search method.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g = @cfgrammar begin\n Number = 1\n List = []\n Index = List[Number]\nend\n\nproblem = Problem([IOExample(Dict(), x) for x ∈ 1:5])\nsolution = search(g, problem, :Index, max_depth=2, allow_evaluation_errors=true)\nprintln(solution)\n>>> nothing","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"There is also another search method called search_best which returns both the solution and the possible error. The method returns the best program found so far. In this case, we can also see the error:","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"solution, error = search_best(g, problem, :Index, max_depth=2, allow_evaluation_errors=true)\nprintln(solution)\n>>> nothing\nprintln(error)\n>>> 9223372036854775807 # or: typemax(Int)","category":"page"},{"location":"tutorials/advanced_search/#Search-methods","page":"Advanced Search Procedures","title":"Search methods","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We now show examples of using different search procedures.","category":"page"},{"location":"tutorials/advanced_search/#Breadth-First-Search","page":"Advanced Search Procedures","title":"Breadth-First Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The breadth-first search will first enumerate all possible programs at the same depth before considering programs with a depth of one more. A tree of the grammar is returned with programs ordered in increasing sizes. We can first collect the programs that have a max-depth of 2 and a max_size of infinite (integer maximum value), where the starting symbol is of type Real. This function uses a default heuristic 'left-most first', such that the left-most child in the tree is always explored first. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g1 = @cfgrammar begin\n Real = 1 | 2\n Real = Real * Real\nend\nprograms = collect(get_bfs_enumerator(g1, 2, typemax(Int), :Real))","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We can test that this function returns all and only the correct functions. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"answer_programs = [\n RuleNode(1),\n RuleNode(2),\n RuleNode(3, [RuleNode(1), RuleNode(1)]),\n RuleNode(3, [RuleNode(1), RuleNode(2)]),\n RuleNode(3, [RuleNode(2), RuleNode(1)]),\n RuleNode(3, [RuleNode(2), RuleNode(2)])\n]\n\nprintln(all(p ∈ programs for p ∈ answer_programs))\n>>> true","category":"page"},{"location":"tutorials/advanced_search/#Depth-First-Search","page":"Advanced Search Procedures","title":"Depth-First Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"In depth-first search, we first explore a certain branch of the search tree till the max_depth or a correct program is reached before we consider the next branch. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g1 = @cfgrammar begin\nReal = 1 | 2\nReal = Real * Real\nend\nprograms = collect(get_dfs_enumerator(g1, 2, typemax(Int), :Real))\nprintln(programs)\n>>> RuleNode[1,, 3{1,1}, 3{1,2}, 3{2,1}, 3{2,2}, 2,]","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"get_dfs_enumerator also has a default left-most heuristic and we consider what the difference is in output. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g1 = @cfgrammar begin\n Real = 1 | 2\n Real = Real * Real\nend\nprograms = collect(get_dfs_enumerator(g1, 2, typemax(Int), :Real, heuristic_rightmost))\nprintln(programs)\n>>> RuleNode[1,, 3{1,1}, 3{2,1}, 3{1,2}, 3{2,2}, 2,]","category":"page"},{"location":"tutorials/advanced_search/#Stochastic-search","page":"Advanced Search Procedures","title":"Stochastic search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"For the examples below, we use this grammar and helper function.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"grammar = @csgrammar begin\n X = |(1:5)\n X = X * X\n X = X + X\n X = X - X\n X = x\nend\nfunction create_problem(f, range=20)\n examples = [IOExample(Dict(:x => x), f(x)) for x ∈ 1:range]\n return Problem(examples), examples\nend","category":"page"},{"location":"tutorials/advanced_search/#Metropolis-Hastings","page":"Advanced Search Procedures","title":"Metropolis-Hastings","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"One of the stochastic search methods that is implemented is Metropolis-Hastings (MH), which samples from a distribution of programs based on the grammar. For more information on MH, see for example this webpage.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The below example uses a simple arithmetic example. As the search method is stochastic, different programs may be returned, as shown below.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> x * x + 4\")\nproblem, examples = create_problem(eval(e))\nenumerator = get_mh_enumerator(examples, mean_squared_error)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=3)\n\n>>> (:(x * x - (1 - 5)), 0)\n>>> (:(4 + x * x), 0)\n>>> (:(x * x + 4), 0)","category":"page"},{"location":"tutorials/advanced_search/#Very-Large-Scale-Neighbourhood-Search","page":"Advanced Search Procedures","title":"Very Large Scale Neighbourhood Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The second implemented stochastic search method is VLSN, which search for a local optimum in the neighbourhood. For more information, see this article.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Given the same grammar as before, we can try with some simple examples.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> 10\")\nmax_depth = 2\nproblem, examples = create_problem(eval(e))\nenumerator = get_vlsn_enumerator(examples, mean_squared_error, max_depth)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=max_depth)\n>>> (:(5 + 5), 0)","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> x\")\nmax_depth = 1\nproblem, examples = create_problem(eval(e))\nenumerator = get_vlsn_enumerator(examples, mean_squared_error, max_depth)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=max_depth)\n>>> (:x, 0)","category":"page"},{"location":"tutorials/advanced_search/#Simulated-Annealing","page":"Advanced Search Procedures","title":"Simulated Annealing","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The third stochastic search method is called simulated annealing. This is another hill-climbing method to find local optima. For more information, see this page.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We try the example from earlier, but now we can additionally define the initial_temperature of the algorithm, which is 1 by default. Two possible answers to the program are given as well.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> x * x + 4\")\ninitial_temperature = 2\nproblem, examples = create_problem(eval(e))\nenumerator = get_sa_enumerator(examples, mean_squared_error, initial_temperature)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=3)\n>>> (:(4 + x * x), 0)\n>>> (:(x * x + (5 - 1)), 0)","category":"page"},{"location":"tutorials/advanced_search/#Genetic-Search","page":"Advanced Search Procedures","title":"Genetic Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Genetic search is a type of evolutionary algorithm, which will simulate the process of natural selection and return the 'fittest' program of the population. For more information, see here.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We show the example of finding a lambda function.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = x -> 3 * x * x + (x + 2)\nproblem, examples = create_problem(e)\nenumerator = get_genetic_enumerator(examples, \n initial_population_size = 10,\n mutation_probability = 0.8,\n maximum_initial_population_depth = 3,\n)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=nothing, max_time=20)\n>>> (:(((((x - 5) + x) + x * x) + 1) + (((((2 + x * x) + 3) + x * x) + 1) - ((x - x) + x))), 0)\n>>> (:(x * 1 + (x * ((x + x) + x * 1) + (1 + 1) * 1)), 0)\n>>> (:((((x + x) + x) + 2) * x + ((x - x) + (2 - x))), 0)","category":"page"},{"location":"tutorials/advanced_search/#Other-functionality","page":"Advanced Search Procedures","title":"Other functionality","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Finally, we showcase two other functionalities of HerbSearch, sampling and heuristics.","category":"page"},{"location":"tutorials/advanced_search/#Sampling","page":"Advanced Search Procedures","title":"Sampling","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Sampling is implemented for the different stochastic search methods.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We consider here a simple grammar, which gives different programs for different search depths.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"grammar = @cfgrammar begin \n A = B | C | F\n F = G\n C = D\n D = E\nend\n\n# A->B (depth 1) or A->F->G (depth 2) or A->C->D->E (depth 3)\n\n# For depth ≤ 1 the only option is A->B\nexpression = rand(RuleNode, grammar, :A, 1)\n@assert rulenode2expr(expression, grammar) in [:B,:C,:F]\n\n# For depth ≤ 2 the two options are A->B (depth 1) and A->B->G| A->C->G | A->F->G (depth 2)\nexpression = rand(RuleNode, grammar, :A, 2)\n@assert rulenode2expr(expression,grammar) in [:B,:C,:F,:G]","category":"page"},{"location":"tutorials/advanced_search/#Heuristics","page":"Advanced Search Procedures","title":"Heuristics","text":"","category":"section"},{"location":"tutorials/advanced_search/#Examples-with-larger-domains-and-constraints","page":"Advanced Search Procedures","title":"Examples with larger domains and constraints","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Here, we showcase a few examples using a more complicated grammar and a few types of constraints","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"# Expects to return a program equivalent to 1 + (1 - x) = 2 - x\n\ng₁ = @csgrammar begin\n Element = |(1 : 3) # 1 - 3\n Element = Element + Element # 4\n Element = 1 - Element # 5\n Element = x # 6\nend\n\naddconstraint!(g₁, ComesAfter(6, [5]))\n\nexamples = [\n IOExample(Dict(:x => 0), 2),\n IOExample(Dict(:x => 1), 1),\n IOExample(Dict(:x => 2), 0)\n]\nproblem = Problem(examples)\nsolution = search(g₁, problem, :Element, max_depth=3)\n\n@assert test_with_input(SymbolTable(g₁), solution, Dict(:x => -2)) == 4\n\n# Expects to return a program equivalent to 4 + x * (x + 3 + 3) = x^2 + 6x + 4\n\ng₂ = @csgrammar begin\n Element = Element + Element + Element # 1\n Element = Element + Element * Element # 2\n Element = x # 3\n Element = |(3 : 5) # 4\nend\n\n# Restrict .. + x * x\naddconstraint!(g₂, Forbidden(MatchNode(2, [MatchVar(:x), MatchNode(3), MatchNode(3)])))\n# Restrict 4 and 5 in lower level\naddconstraint!(g₂, ForbiddenPath([2, 1, 5]))\naddconstraint!(g₂, ForbiddenPath([2, 1, 6]))\n\nexamples = [\n IOExample(Dict(:x => 1), 11)\n IOExample(Dict(:x => 2), 20)\n IOExample(Dict(:x => -1), -1)\n]\nproblem = Problem(examples)\nsolution = search(g₂, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₂), solution, Dict(:x => 0)) == 4\n\n# Expects to return a program equivalent to (1 - (((1 - x) - 1) - 1)) - 1 = x + 1\n\ng₃ = @csgrammar begin\n Element = |(1 : 20) # 1 - 20\n Element = Element - 1 # 21\n Element = 1 - Element # 22\n Element = x # 23\nend\n\naddconstraint!(g₃, ComesAfter(23, [22, 21]))\naddconstraint!(g₃, ComesAfter(22, [21]))\n\nexamples = [\n IOExample(Dict(:x => 1), 2)\n IOExample(Dict(:x => 10), 11)\n]\nproblem = Problem(examples)\nsolution = search(g₃, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₃), solution, Dict(:x => 0)) == 1\n@assert test_with_input(SymbolTable(g₃), solution, Dict(:x => 100)) == 101\n\n# Expects to return a program equivalent to 18 + 4x\n\ng₄ = @csgrammar begin\n Element = |(0 : 20) # 1 - 20\n Element = Element + Element + Element # 21\n Element = Element + Element * Element # 22\n Element = x # 23\nend\n\n# Enforce ordering on + +\naddconstraint!(g₄, Ordered(\n MatchNode(21, [MatchVar(:x), MatchVar(:y), MatchVar(:z)]),\n [:x, :y, :z]\n))\n\nexamples = [\n IOExample(Dict(:x => 1), 22),\n IOExample(Dict(:x => 0), 18),\n IOExample(Dict(:x => -1), 14)\n]\nproblem = Problem(examples)\nsolution = search(g₄, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₄), solution, Dict(:x => 100)) == 418\n\n# Expects to return a program equivalent to (x == 2) ? 1 : (x + 2)\n\ng₅ = @csgrammar begin\n Element = Number # 1\n Element = Bool # 2\n\n Number = |(1 : 3) # 3-5\n \n Number = Number + Number # 6\n Bool = Number ≡ Number # 7\n Number = x # 8\n \n Number = Bool ? Number : Number # 9\n Bool = Bool ? Bool : Bool # 10\nend\n\n# Forbid ? = ?\naddconstraint!(g₅, Forbidden(MatchNode(7, [MatchVar(:x), MatchVar(:x)])))\n# Order =\naddconstraint!(g₅, Ordered(MatchNode(7, [MatchVar(:x), MatchVar(:y)]), [:x, :y]))\n# Order +\naddconstraint!(g₅, Ordered(MatchNode(6, [MatchVar(:x), MatchVar(:y)]), [:x, :y]))\n\nexamples = [\n IOExample(Dict(:x => 0), 2)\n IOExample(Dict(:x => 1), 3)\n IOExample(Dict(:x => 2), 1)\n]\nproblem = Problem(examples)\nsolution = search(g₅, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₅), solution, Dict(:x => 3)) == 5","category":"page"},{"location":"HerbInterpret/#HerbInterpret_docs","page":"HerbInterpret.jl","title":"HerbInterpret.jl Documentation","text":"","category":"section"},{"location":"HerbInterpret/","page":"HerbInterpret.jl","title":"HerbInterpret.jl","text":"CurrentModule=HerbInterpret","category":"page"},{"location":"HerbInterpret/","page":"HerbInterpret.jl","title":"HerbInterpret.jl","text":"Modules = [HerbInterpret]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbInterpret/#HerbInterpret.evaluate_program-Tuple{RuleNode, Vector{<:Example}, Grammar, Function}","page":"HerbInterpret.jl","title":"HerbInterpret.evaluate_program","text":"evaluate_program(program::RuleNode, examples::Vector{<:Example}, grammar::Grammar, evaluation_function::Function)\n\nRuns a program on the examples and returns tuples of actual desired output and the program's output\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.execute_on_examples-Tuple{Dict{Symbol, Any}, Any, Vector{Dict{Symbol, Any}}}","page":"HerbInterpret.jl","title":"HerbInterpret.execute_on_examples","text":"execute_on_examples(tab::SymbolTable, expr::Any, example_inputs::Vector{Dict{Symbol, Any}})::Vector{Any}\n\nExecutes a given expression on a set of inputs and returns the respective outputs. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.interpret-Tuple{Dict{Symbol, Any}, Any}","page":"HerbInterpret.jl","title":"HerbInterpret.interpret","text":"interpret(tab::SymbolTable, ex::Expr)\n\nEvaluates an expression without compiling it. Uses AST and symbol lookups. Only supports :call and :(=) expressions at the moment.\n\nExample usage:\n\ntab = SymbolTable(:f => f, :x => x)\nex = :(f(x))\ninterpret(tab, ex)\n\nWARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.test_all_examples-Tuple{Dict{Symbol, Any}, Any, Vector{Example}}","page":"HerbInterpret.jl","title":"HerbInterpret.test_all_examples","text":"test_all_examples(tab::SymbolTable, expr::Any, examples::Vector{Example})::Vector{Bool}\n\nRuns the interpreter on all examples with the given input table and expression. The symbol table defines everything (functions, symbols) that are not input variables to the program to be synthesised. Returns a list of true/false values indicating if the expression satisfies the corresponding example. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.test_examples-Tuple{Dict{Symbol, Any}, Any, Vector{Example}}","page":"HerbInterpret.jl","title":"HerbInterpret.test_examples","text":"test_examples(tab::SymbolTable, expr::Any, examples::Vector{Example})::Bool\n\nEvaluates all examples and returns true iff all examples pass. Shortcircuits as soon as an example is found for which the program doesn't work. Returns false if one of the examples produces an error.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.test_with_input-Tuple{Dict{Symbol, Any}, Any, Dict}","page":"HerbInterpret.jl","title":"HerbInterpret.test_with_input","text":"test_with_input(tab::SymbolTable, expr::Any, input::Dict)\n\nInterprets an expression or symbol with the given symboltable and the input. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#Index","page":"HerbInterpret.jl","title":"Index","text":"","category":"section"},{"location":"HerbInterpret/","page":"HerbInterpret.jl","title":"HerbInterpret.jl","text":"","category":"page"},{"location":"tutorials/getting_started_with_herb/#Search","page":"A more verbose getting started with Herb.jl","title":"Search","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"This notebook describes how you can search a program space as defined by a grammar. Specifically, we will look at example-based search, where the goal is to find a program that is able to transform the inputs of every example to the corresponding output.","category":"page"},{"location":"tutorials/getting_started_with_herb/#Setup","page":"A more verbose getting started with Herb.jl","title":"Setup","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"First, we start with the setup. We need to access to all the function in the Herb.jl framework.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"using Herb","category":"page"},{"location":"tutorials/getting_started_with_herb/#Defining-the-program-space","page":"A more verbose getting started with Herb.jl","title":"Defining the program space","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Next, we start by creating a grammar. We define a context-free grammar which is just a simple set of production rules for defining combinations of terminal symbols (in our case real numbers). ","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Contrary, we could define a context-sensitive grammar, when the production rules only hold in a certain context. However, for more information on this, please see example2_defining_grammars.ipynb.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"For now, we specify a simple grammar for dealing with integers and explain all the rules individually:","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"First, we specify our interval [0:9] on real numbers and also constrain them to be integer.\nThen, we can also use the variable x to hold an integer.\nThe third rule determines we can add two integers.\nThe fourth rule determines we can subtract an integer from another.\nFinally, we also allow the multiplication of two integers.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"If you run this cell, you can see all the rules rolled out.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"g = Herb.HerbGrammar.@cfgrammar begin\n Real = |(0:9)\n Real = x\n Real = Real + Real\n Real = Real - Real\n Real = Real * Real\nend","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"1: Real = 0\n2: Real = 1\n3: Real = 2\n4: Real = 3\n5: Real = 4\n6: Real = 5\n7: Real = 6\n8: Real = 7\n9: Real = 8\n10: Real = 9\n11: Real = x\n12: Real = Real + Real\n13: Real = Real - Real\n14: Real = Real * Real","category":"page"},{"location":"tutorials/getting_started_with_herb/#Defining-the-problem","page":"A more verbose getting started with Herb.jl","title":"Defining the problem","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"As mentioned before, we are looking at example-based search. This means that the problem is defined by a set of input-output examples. A single example hence consists of an input and an output. The input is defined as a dictionary, with a value assigned to each variable in the grammar. It is important to write the variable name as a Symbol instead of a string. A Symbol in Julia is written with a colon prefix, i.e. :x. The output of the input-output example is just a single value for this specific grammar, but could possibly relate to e.g. arrays of values, too.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In the cell below we automatically generate some examples for x assigning values 1-5.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"# Create input-output examples\nexamples = [Herb.HerbData.IOExample(Dict(:x => x), 3x+5) for x ∈ 1:5]","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"5-element Vector{Main.Herb.HerbData.IOExample}:\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 1), 8)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 2), 11)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 3), 14)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 4), 17)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 5), 20)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Now that we have some input-output examples, we can define the problem. Next to the examples, a problem also contains a name meant to link to the file path, which can be used to keep track of current examples. For now, this is irrelevant, and you can give the program any name you like.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"problem = Herb.HerbData.Problem(examples, \"example\")","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Main.Herb.HerbData.Problem(Main.Herb.HerbData.Example[Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 1), 8), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 2), 11), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 3), 14), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 4), 17), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 5), 20)], \"example\")","category":"page"},{"location":"tutorials/getting_started_with_herb/#Searching","page":"A more verbose getting started with Herb.jl","title":"Searching","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Now that we have defined the search space and the goal of the search, we can start the search. ","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Of course, our problem is underdefined as there might be multiple programs that satisfy our examples. Let us consider the case where we also have a ternary if-then-else operator and standard boolean operators in our grammar: we could synthesize the program x ≤ 5 ? 3x+5 : 0. This program satisfies all our examples, but we don't expect it to generalize very well.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In general, we assume that a smaller program is more general than a larger program. Therefore, we search for the smallest program in our grammar that satisfies our examples. This can be done using a breadth-first search over the program/search space.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"This search is very basic; it makes use of an enumeration technique, where we enumerate programs one-by-one until we find a program that matches our examples. The search procedure has a built-in default evaluator to verify the candidate programs with the given input. The search procedure also has a built-in search procedure using breadth-first search. ","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"So, we only need to give our grammar and the problem to our search procedure, along with a starting Symbol, in our case a Real.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Herb.HerbSearch.search(g, problem, :Real)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":":(x * 3 + 5)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"As you can see, the search procedure found the correct program!","category":"page"},{"location":"tutorials/getting_started_with_herb/#Defining-the-search-procedure","page":"A more verbose getting started with Herb.jl","title":"Defining the search procedure","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In the previous case, we used the built-ins of the search procedure. However, we can also give a custom enumerator to the search procedure and define a few more values.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"We first define a new problem to test with, we are looking for the programs that can compute the value167. We immediately pass the examples to the problem and then set up the new search.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Search is done by passing the grammar, the problem and the starting point like before. We now also specify the enumeration function to be used, and now we use depth-first search. Then, we give the maximum depth of the programs we want to search for (3), the maximum number of nodes in the Abstract Syntax Tree that exists during search (10), and the maximum time in seconds allowed for the search.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"problem = Herb.HerbData.Problem([Herb.HerbData.IOExample(Dict(:x => x), 168) for x ∈ 1:5], \"example2\")\nexpr = Herb.HerbSearch.search(g, problem, :Real, enumerator=Herb.HerbSearch.get_dfs_enumerator, max_depth=4, max_size=30, max_time=180)\nprint(expr)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"nothing","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"We see that our synthesizer can find a program to construct the value 168, though a fun experiment would be trying to get the value 167, what do you think would happen? If you want you can try below.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In any case, this concludes our first introduction to the Herb.jl program synthesis framework. You can see more examples in this repository, or explore yourself. Enjoy!","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"problem = Herb.HerbData.Problem([Herb.HerbData.IOExample(Dict(:x => x), 167) for x ∈ 1:5], \"example2\")\nexpr = Herb.HerbSearch.search(g, problem, :Real)\nprintln(expr)","category":"page"},{"location":"get_started/#Getting-Started","page":"Getting Started","title":"Getting Started","text":"","category":"section"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"You can either paste this code into the Julia REPL or into a seperate file, e.g. get_started.jl followed by julia get_started.jl.","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"To begin, we need to import all needed packages using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"using HerbGrammar, HerbData, HerbSearch, HerbInterpret","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"To define a program synthesis problem, we need a grammar and specification. ","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"First, a grammar can be constructed using the @cfgrammar macro included in HerbGrammar. Alternatively, we can use the @csgrammar macro, which will be shown later on in the tutorial when we use constraints. ","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Here, we describe a simple integer arithmetic example, that can add and multiply an input variable x or the integers 1,2, using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"g = @cfgrammar begin\n Number = |(1:2)\n Number = x\n Number = Number + Number\n Number = Number * Number\nend","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Second, the problem specification can be provided using e.g. input/output examples using HerbData. Inputs are provided as a Dict assigning values to variables, and outputs as arbitrary values. The problem itself is then a list of IOExamples using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"The problem is given now, let us search for a solution with HerbSearch. For now we will just use the default parameters searching for a satisfying program over the grammar, given the problem and a starting symbol using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"solution = search(g, problem, :Number, max_depth=3)\nprintln(solution)","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"There are various ways to adapt the search technique to your needs. Please have a look at the search documentation.","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Eventually, we want to test our solution on some other inputs using HerbInterpret. We transform our grammar g to a Julia expression with Symboltable(g), add our solution and the input, assigning the value 6 to the variable x.","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"output = test_with_input(SymbolTable(g), solution, Dict(:x => 6))\nprintln(output)","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Just like that we tackled (almost) all modules of Herb.jl.","category":"page"},{"location":"get_started/#Where-to-go-from-here?","page":"Getting Started","title":"Where to go from here?","text":"","category":"section"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"See our other tutorials!","category":"page"},{"location":"get_started/#The-full-code-example","page":"Getting Started","title":"The full code example","text":"","category":"section"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"using HerbSearch, HerbData, HerbInterpret, HerbGrammar\n\n# define our very simple context-free grammar\n# Can add and multiply an input variable x or the integers 1,2.\ng = @cfgrammar begin\n Number = |(1:2)\n Number = x\n Number = Number + Number\n Number = Number * Number\nend\n\nproblem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])\nsolution = search(g, problem, :Number, max_depth=3)\n\ntest_with_input(SymbolTable(g), solution, Dict(:x => 6))","category":"page"},{"location":"HerbData/#HerbData_docs","page":"HerbCore.jl","title":"HerbData.jl Documentation","text":"","category":"section"},{"location":"HerbData/","page":"HerbCore.jl","title":"HerbCore.jl","text":"CurrentModule=HerbData","category":"page"},{"location":"HerbData/","page":"HerbCore.jl","title":"HerbCore.jl","text":"Modules = [HerbData]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbData/#HerbData.IOExample","page":"HerbCore.jl","title":"HerbData.IOExample","text":"struct IOExample <: Example\n\nAn input-output example. input is a Dict of {Symbol,Any} where the symbol represents a variable in a program. output can be anything.\n\n\n\n\n\n","category":"type"},{"location":"HerbData/#HerbData.IOPExample","page":"HerbCore.jl","title":"HerbData.IOPExample","text":"struct IOPExample <: Example\n\nAn input-output example with an associated program. ex is an IOExample. program is a program of arbitrary form. Please note that this is a pure container, and thus does not guarantee any checks on the validity of the program.\n\n\n\n\n\n","category":"type"},{"location":"HerbData/#HerbData.Problem","page":"HerbCore.jl","title":"HerbData.Problem","text":"struct Problem\n\nProgram synthesis problem defined with a vector of Examples\n\n\n\n\n\n","category":"type"},{"location":"HerbData/#HerbData.read_IOPexamples-Tuple{AbstractString}","page":"HerbCore.jl","title":"HerbData.read_IOPexamples","text":"read_IOPexamples(filepath::AbstractString)::Vector{Tuple{IOPExample}\n\nReads serialized IO + program examples from disk after type checking.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.read_IOexamples-Tuple{AbstractString}","page":"HerbCore.jl","title":"HerbData.read_IOexamples","text":"read_IOexamples(filepath::AbstractString)::Vector{IOExample}\n\nReads serialized IO examples from disk after type checking.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.readdata-Tuple{AbstractString, Function}","page":"HerbCore.jl","title":"HerbData.readdata","text":"readdata(directory::AbstractString, lineparser::Function)::Vector{Problem}\n\nReads all files in the given directory and parses them line by line into an ExampleProblem using the given lineparser.\n\nTODO: Turn this into an iterator that doesn't load all data into memory at initialization.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.readfile-Tuple{AbstractString, Function}","page":"HerbCore.jl","title":"HerbData.readfile","text":"readfile(filepath::AbstractString, lineparser::Function)::Problem\n\nReads a file and parses every non-empty line using the line parser.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.write_IOPexamples-Tuple{AbstractString, Vector{IOPExample}}","page":"HerbCore.jl","title":"HerbData.write_IOPexamples","text":"write_IOPexamples(filepath::AbstractString, examples::Vector{Tuple{IOExample, Any}})\n\nWrites IO examples and the corresponding programs to disk by serializing them into a file using HDF5 checking for and appending the .xiop.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.write_IOexamples-Tuple{AbstractString, Vector{IOExample}}","page":"HerbCore.jl","title":"HerbData.write_IOexamples","text":"write_IOexamples(filepath::AbstractString, examples::Vector{IOExample})\n\nWrites IO examples to disk by serializing them into a file using HDF5 checking for and appending the .xio file ending.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#Index","page":"HerbCore.jl","title":"Index","text":"","category":"section"},{"location":"HerbData/","page":"HerbCore.jl","title":"HerbCore.jl","text":"","category":"page"},{"location":"tutorials/defining_grammars/#Defining-Grammars-in-Herb.jl-using-HerbGrammar","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl using HerbGrammar","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"The program space in Herb.jl is defined using a grammar. This notebook demonstrates how such a grammar can be created. There are multiple kinds of grammars, but they can all be defined in a very similar way.","category":"page"},{"location":"tutorials/defining_grammars/#Setup","page":"Defining Grammars in Herb.jl","title":"Setup","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"using HerbGrammar, HerbConstraints","category":"page"},{"location":"tutorials/defining_grammars/#Creating-a-simple-grammar","page":"Defining Grammars in Herb.jl","title":"Creating a simple grammar","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"This cell contains a very simple arithmetic grammar. The grammar is defined using the @cfgrammar macro. This macro converts the grammar definition in the form of a Julia expression into Herb's internal grammar representation. Macro's are executed during compilation. If you want to load a grammar during execution, have a look at the HerbGrammar.expr2cfgrammar function.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₁ = HerbGrammar.@cfgrammar begin\n Int = 1\n Int = 2\n Int = 3\n Int = Int * Int\n Int = Int + Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 1\n2: Int = 2\n3: Int = 3\n4: Int = Int * Int\n5: Int = Int + Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Defining every integer one-by-one can be quite tedious. Therefore, it is also possible to use the following syntax that makes use of a Julia iterator:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₂ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int * Int\n Int = Int + Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = Int + Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"You can do the same with lists:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₃ = HerbGrammar.@cfgrammar begin\n Int = |([0, 2, 4, 6, 8])\n Int = Int * Int\n Int = Int + Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 2\n3: Int = 4\n4: Int = 6\n5: Int = 8\n6: Int = Int * Int\n7: Int = Int + Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Variables can also be added to the grammar by just using the variable name:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₄ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int * Int\n Int = Int + Int\n Int = x\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = Int + Int\n13: Int = x","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Grammars can also work with functions. After all, + and * are just infix operators for Julia's identically-named functions. You can use functions that are provided by Julia, or functions that you wrote yourself:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"f(a) = a + 1\n\ng₅ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int * Int\n Int = Int + Int\n Int = f(Int)\n Int = x\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = Int + Int\n13: Int = f(Int)\n14: Int = x","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Similarly, we can also define the operator times (x) manually.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"×(a, b) = a * b\n\ng₆ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = a\n Int = Int + Int\n Int = Int × Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = a\n12: Int = Int + Int\n13: Int = Int × Int","category":"page"},{"location":"tutorials/defining_grammars/#Working-with-grammars","page":"Defining Grammars in Herb.jl","title":"Working with grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"If you want to implement something using these grammars, it is useful to know about the functions that you can use to manipulate grammars and extract information. This section is not necessarily complete, but it aims to give an overview of the most important functions. ","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"It is recommended to also read up on Julia metaprogramming if you are not already familiar with that.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"One of the most important things about grammars is that each rule has an index associated with it:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₇ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int + Int\n Int = Int * Int\n Int = x\nend\n\ncollect(enumerate(g₇.rules))","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"13-element Vector{Tuple{Int64, Any}}:\n (1, 0)\n (2, 1)\n (3, 2)\n (4, 3)\n (5, 4)\n (6, 5)\n (7, 6)\n (8, 7)\n (9, 8)\n (10, 9)\n (11, :(Int + Int))\n (12, :(Int * Int))\n (13, :x)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"We can use this index to extract information from the grammar.","category":"page"},{"location":"tutorials/defining_grammars/#isterminal","page":"Defining Grammars in Herb.jl","title":"isterminal","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"isterminal returns true if a rule is terminal, i.e. it cannot be expanded. For example, rule 1 is terminal, but rule 11 is not, since it contains the non-terminal symbol :Int. ","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.isterminal(g₇, 1)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"true","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.isterminal(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"false","category":"page"},{"location":"tutorials/defining_grammars/#return_type","page":"Defining Grammars in Herb.jl","title":"return_type","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"This function is rather obvious; it returns the non-terminal symbol that corresponds to a certain rule. The return type for all rules in our grammar is :Int.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.return_type(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":":Int","category":"page"},{"location":"tutorials/defining_grammars/#child_types","page":"Defining Grammars in Herb.jl","title":"child_types","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"child_types returns the types of the nonterminal children of a rule in a vector. If you just want to know how many children a rule has, and not necessarily which types they have, you can use nchildren","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.child_types(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"2-element Vector{Symbol}:\n :Int\n :Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.nchildren(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"2","category":"page"},{"location":"tutorials/defining_grammars/#nonterminals","page":"Defining Grammars in Herb.jl","title":"nonterminals","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"The nonterminals function can be used to obtain a list of all nonterminals in the grammar.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.nonterminals(g₇)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1-element Vector{Symbol}:\n :Int","category":"page"},{"location":"tutorials/defining_grammars/#Adding-rules","page":"Defining Grammars in Herb.jl","title":"Adding rules","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"It is also possible to add rules to a grammar during execution. This can be done using the add_rule! function. As with most functions in Julia that end with an exclamation mark, this function modifies its argument (the grammar).","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"A rule can be provided in the same syntax as is used in the grammar definition. The rule should be of the Expr type, which is a built-in type for representing expressions. An easy way of creating Expr values in Julia is to encapsulate it in brackets and use a colon as prefix:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.add_rule!(g₇, :(Int = Int - Int))","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x\n14: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/#Removing-rules","page":"Defining Grammars in Herb.jl","title":"Removing rules","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"It is also possible to remove rules in Herb.jl, however, this is a bit more involved. As said before, rules have an index associated with them. The internal representation of programs that are defined by the grammar makes use of those indices for efficiency. Blindly removing a rule would shift the indices of other rules, and this could mean that existing programs get a different meaning or become invalid. ","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Therefore, there are two functions for removing rules:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"remove_rule! removes a rule from the grammar, but fills its place with a placeholder. Therefore, the indices stay the same, and only programs that use the removed rule become invalid.\ncleanup_removed_rules! removes all placeholders and shifts the indices of the other rules.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.remove_rule!(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: nothing = nothing\n12: Int = Int * Int\n13: Int = x\n14: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.cleanup_removed_rules!(g₇)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = x\n13: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/#Context-sensitive-grammars","page":"Defining Grammars in Herb.jl","title":"Context-sensitive grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Context-sensitive grammars allow additional constraints to be added with respect to context-free grammars. The syntax for defining a context-sensitive grammar is identical to defining a context-sensitive grammar:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₈ = HerbGrammar.@csgrammar begin\n Int = |(0:9)\n Int = Int + Int\n Int = Int * Int\n Int = x\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Constraints can be added using the addconstraint! function, which takes a context-sensitive grammar and a constraint and adds the constraint to the grammar. Currently, Herb.jl only has propagators constraints. These constraints each have a corresponding propagate function that removes all options that violate that constraint from the domain. At the moment, there are three propagator constraints:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"ComesAfter(rule, predecessors): It is only possible to use rule rule when predecessors are in its path to the root.\nForbidden(sequence): Forbids the derivation specified as a path in an expression tree.\nOrdered(order): Rules have to be used in the specified order. That is, rule at index K can only be used if rules at indices [1...K-1] are used in the left subtree of the current expression.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Below, an example is given of a context-sensitive grammar with a ComesAfter constraint:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.addconstraint!(g₈, HerbConstraints.ComesAfter(1, [9]))","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1-element Vector{Main.HerbCore.Constraint}:\n Main.HerbConstraints.ComesAfter(1, [9])","category":"page"},{"location":"tutorials/defining_grammars/#Probabilistic-grammars","page":"Defining Grammars in Herb.jl","title":"Probabilistic grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Herb.jl also supports probabilistic grammars. These grammars allow the user to assign a probability to each rule in the grammar. A probabilistic grammar can be defined in a very similar way to a standard grammar, but has some slightly different syntax:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₉ = HerbGrammar.@pcfgrammar begin\n 0.4 : Int = |(0:9)\n 0.2 : Int = Int + Int\n 0.1 : Int = Int * Int\n 0.3 : Int = x\nend\n\nfor r ∈ 1:length(g₃.rules)\n p = HerbGrammar.probability(g₈, r)\n\n println(\"$p : $r\")\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"0.07692307692307693 : 1\n0.07692307692307693 : 2\n0.07692307692307693 : 3\n0.07692307692307693 : 4\n0.07692307692307693 : 5\n0.07692307692307693 : 6\n0.07692307692307693 : 7\n\n\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"The numbers before each rule represent the probability assigned to that rule. The total probability for each return type should add up to 1.0. If this isn't the case, Herb.jl will normalize the probabilities.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"If a single line in the grammar definition represents multiple rules, such as 0.4 : Int = |(0:9), the probability will be evenly divided over all these rules.","category":"page"},{"location":"tutorials/defining_grammars/#File-writing","page":"Defining Grammars in Herb.jl","title":"File writing","text":"","category":"section"},{"location":"tutorials/defining_grammars/#Saving-and-loading-context-free-grammars","page":"Defining Grammars in Herb.jl","title":"Saving & loading context-free grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"If you want to store a grammar on the disk, you can use the store_cfg, read_cfg and functions to store and read grammars respectively. The store_cfg grammar can also be used to store probabilistic grammars. Reading probabilistic grammars can be done using read_pcfg. The stored grammar files can also be opened using a text editor to be modified, as long as the contents of the file doesn't violate the syntax for defining grammars.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.store_cfg(\"demo.txt\", g₇)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.read_cfg(\"demo.txt\")","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = x\n13: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/#Saving-and-loading-context-sensitive-grammars","page":"Defining Grammars in Herb.jl","title":"Saving & loading context-sensitive grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Saving and loading context-sensitive grammars is very similar to how it is done with context-free grammars. The only difference is that an additional file is created for the constraints. The file that contains the grammars can be edited and can also be read using the reader for context-free grammars. The file that contains the constraints cannot be edited.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.store_csg(\"demo.grammar\", \"demo.constraints\", g₈)\ng₈, g₈.constraints","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"(1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x\n, Main.HerbCore.Constraint[Main.HerbConstraints.ComesAfter(1, [9])])","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₉ = HerbGrammar.read_csg(\"demo.grammar\", \"demo.constraints\")\ng₉, g₉.constraints","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"(1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x\n, Main.HerbCore.Constraint[Main.HerbConstraints.ComesAfter(1, [9])])","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"CurrentModule=Herb","category":"page"},{"location":"#[Herb.jl](https://github.com/Herb-AI/Herb.jl)","page":"Herb.jl","title":"Herb.jl","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"A library for defining and efficiently solving program synthesis tasks in Julia.","category":"page"},{"location":"#Why-Herb.jl?","page":"Herb.jl","title":"Why Herb.jl?","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"When writing research software we almost always investigate highly specific properties or algorithms of our domain, leading to us building the tools from scratch over and over again. The very same holds for the field of program synthesis: Tools are hard to run, benchmarks are hard to get and prepare, and its hard to adapt our existing code to a novel idea.","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb.jl will take care of this for you and helps you defining, solving and extending your program synthesis problems.","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb.jl provides...","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"a unified and universal framework for program synthesis\nHerb.jl allows you to describe all sorts of program synthesis problems using context-free grammars\na number of state-of-the-art benchmarks and solvers already implemented and usable out-of-the-box","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb.jl's sub-packages provide fast and easily extendable implementations of ","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"various static and dynamic search strategies,\nlearning search strategies, sampling techniques and more,\nconstraint formulation and propagation, \neasy grammar formulation and usage,\nwide-range of usable program interpreters and languages + the possibility to use your own, and \nefficient data formulation.","category":"page"},{"location":"#Why-Julia?","page":"Herb.jl","title":"Why Julia?","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Julia is a perfect fit for program synthesis due to numerous reasons. Starting from scientific reasons like speed of execution and composability over to practical reasons like speed of writing Julia code. For a full ode on why to use Julia, please see the WhyJulia manifesto.","category":"page"},{"location":"#Sub-Modules","page":"Herb.jl","title":"Sub-Modules","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb's functionality is distributed among several sub-packages:","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"HerbCore.jl: The core of Herb.jl defining core concepts to avoid circular dependencies.\nHerbGrammar.jl:\nHerbData.jl:\nHerbInterpret.jl:\nHerbSearch.jl:\nHerbConstraints.jl:","category":"page"},{"location":"#Basics","page":"Herb.jl","title":"Basics","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Pages = [\"install.md\", \"get_started.md\", \"concepts.md\"]","category":"page"},{"location":"#Advanced-content","page":"Herb.jl","title":"Advanced content","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"","category":"page"}] +[{"location":"install/#Installation-Guide","page":"Installation Guide","title":"Installation Guide","text":"","category":"section"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"Before installing Herb.jl, ensure that you have a running Julia distribution installed (Julia version 1.7 and above were tested). ","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"Thanks to Julia's package management, installing Herb.jl is very straighforward. Activate the default Julia REPL using","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"julia","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"or from within one of your projects using","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"julia --project=.","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"From the Julia REPL run ","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"]\nadd Herb","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"or instead running","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"import Pkg\nPkg.add(\"Herb\")","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"which will both install all dependencies automatically.","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"For later convenience we can also add the respective dependencies to our project, so that we do not have to write Herb.HerbGrammar every time.","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"] add HerbConstraints HerbCore HerbData HerbInterpret HerbGrammar HerbSearch","category":"page"},{"location":"install/","page":"Installation Guide","title":"Installation Guide","text":"And just like this you are done! Welcome to Herb.jl!","category":"page"},{"location":"concepts/#Architecture-and-core-concepts","page":"Architecture and core concepts","title":"Architecture and core concepts","text":"","category":"section"},{"location":"HerbSearch/#HerbSearch_docs","page":"HerbSearch.jl","title":"HerbSearch.jl Documentation","text":"","category":"section"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"CurrentModule=HerbSearch","category":"page"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"Modules = [HerbSearch]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbSearch/#HerbSearch.BFSIterator","page":"HerbSearch.jl","title":"HerbSearch.BFSIterator","text":"@programiterator BFSIterator() <: TopDownIterator\n\nReturns a breadth-first iterator given a grammar and a starting symbol. Returns trees in the grammar in increasing order of size. Inherits all stop-criteria from TopDownIterator.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.DFSIterator","page":"HerbSearch.jl","title":"HerbSearch.DFSIterator","text":"@programiterator DFSIterator() <: TopDownIterator\n\nReturns a depth-first search enumerator given a grammar and a starting symbol. Returns trees in the grammar in decreasing order of size. Inherits all stop-criteria from TopDownIterator.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.ExpandFailureReason","page":"HerbSearch.jl","title":"HerbSearch.ExpandFailureReason","text":"@enum ExpandFailureReason limit_reached=1 already_complete=2\n\nRepresentation of the different reasons why expanding a partial tree failed. Currently, there are two possible causes of the expansion failing:\n\nlimit_reached: The depth limit or the size limit of the partial tree would be violated by the expansion\nalready_complete: There is no hole left in the tree, so nothing can be expanded.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.GeneticSearchIterator","page":"HerbSearch.jl","title":"HerbSearch.GeneticSearchIterator","text":"GeneticSearchIterator{FitnessFunction,CrossOverFunction,MutationFunction,SelectParentsFunction,EvaluationFunction} <: ProgramIterator\n\nDefines an ProgramIterator using genetic search. \n\nConsists of:\n\nexamples::Vector{<:IOExample}: a collection of examples defining the specification \nevaluation_function::EvaluationFunction: interpreter to evaluate the individual programs\npopulation_size::Int64: number of inviduals in the population\nmutation_probability::Float64: probability of mutation for each individual\nmaximum_initial_population_depth::Int64: maximum depth of trees when population is initialized \n\nend\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.MHSearchIterator","page":"HerbSearch.jl","title":"HerbSearch.MHSearchIterator","text":"MHSearchIterator(examples::AbstractArray{<:IOExample}, cost_function::Function, evaluation_function::Function=HerbInterpret.execute_on_input)\n\nReturns an enumerator that runs according to the Metropolis Hastings algorithm.\n\nspec : array of examples\ncost_function : cost function to evaluate the programs proposed\nevaluation_function : evaluation function that evaluates the program generated and produces an output\n\nThe propose function is randomfillpropose and the accept function is probabilistic. The temperature value of the algorithm remains constant over time.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.MLFSIterator","page":"HerbSearch.jl","title":"HerbSearch.MLFSIterator","text":"@programiterator MLFSIterator() <: TopDownIterator\n\nIterator that enumerates expressions in the grammar in decreasing order of probability (Only use this iterator with probabilistic grammars). Inherits all stop-criteria from TopDownIterator.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.PriorityQueueItem","page":"HerbSearch.jl","title":"HerbSearch.PriorityQueueItem","text":"struct PriorityQueueItem\n\nRepresents an item in the priority enumerator priority queue. An item contains of:\n\ntree: A partial AST\nsize: The size of the tree. This is a cached value which prevents having to traverse the entire tree each time the size is needed.\nconstraints: The local constraints that apply to this tree. These constraints are enforced each time the tree is modified.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.PriorityQueueItem-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.PriorityQueueItem","text":"PriorityQueueItem(tree::AbstractRuleNode, size::Int)\n\nConstructs PriorityQueueItem given only a tree and the size, but no constraints.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.ProgramIterator","page":"HerbSearch.jl","title":"HerbSearch.ProgramIterator","text":"abstract type ProgramIterator\n\nGeneric iterator for all possible search strategies. All iterators are expected to have the following fields:\n\ngrammar::ContextSensitiveGrammar: the grammar to search over\nsym::Symbol: defines the start symbol from which the search should be started \nmax_depth::Int: maximum depth of program trees\nmax_size::Int: maximum number of AbstractRuleNodes of program trees\nmax_time::Int: maximum time the iterator may take\nmax_enumerations::Int: maximum number of enumerations\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.PropagateResult","page":"HerbSearch.jl","title":"HerbSearch.PropagateResult","text":"@enum PropagateResult tree_complete=1 tree_incomplete=2 tree_infeasible=3\n\nRepresentation of the possible results of a constraint propagation. At the moment there are three possible outcomes:\n\ntree_complete: The propagation was applied successfully and the tree does not contain any holes anymore. Thus no constraints can be applied anymore.\ntree_incomplete: The propagation was applied successfully and the tree does contain more holes. Thus more constraints may be applied to further prune the respective domains.\ntree_infeasible: The propagation was succesful, but there are holes with empty domains. Hence, the tree is now infeasible.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.SASearchIterator","page":"HerbSearch.jl","title":"HerbSearch.SASearchIterator","text":"SASearchIterator(spec, cost_function, initial_temperature=1, temperature_decreasing_factor = 0.99, evaluation_function::Function=HerbInterpret.execute_on_input)\n\nReturns an enumerator that runs according to the Simulated Annealing Search algorithm.\n\nspec : array of examples\ncost_function : cost function to evaluate the programs proposed\ninitial_temperature : the starting temperature of the algorithm\ntemperature_decreasing_factor : the decreasing factor of the temperature of the time\nevaluation_function : evaluation function that evaluates the program generated and produces an output\n\nThe propose function is random_fill_propose (the same as for Metropolis Hastings). The accept function is probabilistic but takes into account the tempeerature too.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.StochasticSearchIterator","page":"HerbSearch.jl","title":"HerbSearch.StochasticSearchIterator","text":"abstract type StochasticSearchIterator <: ProgramIterator\n\nA unified abstract type for the algorithms Metropolis Hastings, Very Large Scale Neighbourhood and Simulated Annealing. Each algorithm implements neighbourhood, propose, accept and temperature functions. Below the signatures of each function is shown.\n\nSignatures\n\n\n\nReturns a node location from the program that is the neighbourhood. It can also return other information using dict\n\nneighbourhood(iter::T, current_program::RuleNode) where T <: StochasticSearchIterator -> (loc::NodeLocation, dict::Dict)\n\nProposes a list of programs using the location provided by neighbourhood and the dict.\n\npropose(iter::T, current_program::RuleNode, neighbourhood_node_loc::NodeLoc, dmap::AbstractVector{Int}, dict::Union{Nothing,Dict{String,Any}}) where T <: StochasticSearchIterator -> Iter[RuleNode]\n\n\n\nBased on the current program and possible cost and temperature it accepts the program or not. Usually we would always want to accept better programs but we might get stuck if we do so. That is why some implementations of the accept function accept with a probability costs that are worse. cost means how different are the outcomes of the program compared to the correct outcomes. The lower the cost the better the program performs on the examples. The cost is provided by the cost_function\n\naccept(::T, currentcost::Real, nextcost::Real, temperature::Real) where T <: StochasticSearchIterator -> Bool\n\nReturns the new temperature based on the previous temperature. Higher the temperature means that the algorithm will explore more.\n\ntemperature(::T, current_temperature::Real) where T <: StochasticSearchIterator -> Real\n\nReturns the cost of the current program. It receives a list of tuples (expected, found) and gives back a cost.\n\ncost_function(outcomes::Tuple{<:Number,<:Number}[]) -> Real\n\n\n\nFields\n\ngrammar::ContextSensitiveGrammar grammar that the algorithm uses\nsym::Symbol the start symbol of the algorithm :Real or :Int\nexamples::Vector{IOExample} example used to check the program\ncost_function::Function\ninitial_temperature::Real = 1 \nevaluation_function::Function that evaluates the julia expressions\n\nAn iterator over all possible expressions of a grammar up to maxdepth with start symbol sym. Also inherits all stop criteria like `maxdepthfromProgramIterator`.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.SynthResult","page":"HerbSearch.jl","title":"HerbSearch.SynthResult","text":"@enum SynthResult optimal_program=1 suboptimal_program=2\n\nRepresentation of the possible results of the synth procedure. At the moment there are two possible outcomes:\n\noptimal_program: The synthesized program satisfies the entire program specification.\nsuboptimal_program: The synthesized program does not satisfy the entire program specification, but got the best score from the evaluator.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.TopDownIterator","page":"HerbSearch.jl","title":"HerbSearch.TopDownIterator","text":"mutable struct TopDownIterator <: ProgramIterator\n\nEnumerates a context-free grammar starting at Symbol sym with respect to the grammar up to a given depth and a given size. The exploration is done using the given priority function for derivations, and the expand function for discovered nodes. Concrete iterators may overload the following methods:\n\npriority_function\nderivation_heuristic\nhole_heuristic\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.VLSNSearchIterator","page":"HerbSearch.jl","title":"HerbSearch.VLSNSearchIterator","text":"VLSNSearchIterator(spec, cost_function, enumeration_depth = 2, evaluation_function::Function=HerbInterpret.execute_on_input) = StochasticSearchIterator(\n\nReturns an iterator that runs according to the Very Large Scale Neighbourhood Search algorithm.\n\nspec : array of examples\ncost_function : cost function to evaluate the programs proposed\nvlsn_neighbourhood_depth : the enumeration depth to search for a best program at a time\nevaluation_function : evaluation function that evaluates the program generated and produces an output\n\nThe propose function consists of all possible programs of the given enumeration_depth. The accept function accepts the program with the lowest cost according to the cost_function. The temperature value of the algorithm remains constant over time.\n\n\n\n\n\n","category":"type"},{"location":"HerbSearch/#HerbSearch.@programiterator-Tuple{Any, Any}","page":"HerbSearch.jl","title":"HerbSearch.@programiterator","text":"@programiterator\n\nCanonical way of creating a program iterator. The macro automatically declares the expected fields listed in the ProgramIterator documentation. Syntax accepted by the macro is as follows (anything enclosed in square brackets is optional): @programiterator [mutable] ( , ..., ) [<: ] Note that the macro emits an assertion that the SupertypeIterator is a subtype of ProgramIterator which otherwise throws an ArgumentError. If no supertype is given, the new iterator extends ProgramIterator directly. Each may be (almost) any expression valid in a struct declaration, and they must be comma separated. One known exception is that an inner constructor must always be given using the extended function (...) ... end syntax. The mutable keyword determines whether the declared struct is mutable.\n\n\n\n\n\n","category":"macro"},{"location":"HerbSearch/#Base.iterate-Tuple{GeneticSearchIterator, HerbSearch.GeneticIteratorState}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::GeneticSearchIterator, current_state::GeneticIteratorState)\n\nIterates the search space using a genetic algorithm. Takes the iterator and the current state to mutate and crossover random inviduals. Returns the best program-so-far and the state of the iterator.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{GeneticSearchIterator}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::GeneticSearchIterator)\n\nIterates the search space using a genetic algorithm. First generates a population sampling random programs. Returns the best program-so-far, and the state of the iterator.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{HerbSearch.StochasticSearchIterator, HerbSearch.IteratorState}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::StochasticSearchIterator, current_state::IteratorState)\n\nThe algorithm that constructs the iterator of StochasticSearchIterator. It has the following structure:\n\nget a random node location -> location,dict = neighbourhood(current_program)\ncall propose on the current program getting a list of possbile replacements in the node location \niterate through all the possible replacements and perform the replacement in the current program \naccept the new program by modifying the next_program or reject the new program\nreturn the new next_program\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{TopDownIterator, DataStructures.PriorityQueue}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::TopDownIterator, pq::DataStructures.PriorityQueue)\n\nDescribes the iteration for a given TopDownIterator and a PriorityQueue over the grammar without enqueueing new items to the priority queue. Recursively returns the result for the priority queue.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.iterate-Tuple{TopDownIterator}","page":"HerbSearch.jl","title":"Base.iterate","text":"Base.iterate(iter::TopDownIterator)\n\nDescribes the iteration for a given TopDownIterator over the grammar. The iteration constructs a PriorityQueue first and then prunes it propagating the active constraints. Recursively returns the result for the priority queue.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#Base.rand","page":"HerbSearch.jl","title":"Base.rand","text":"rand(::Type{RuleNode}, grammar::AbstractGrammar, typ::Symbol, max_depth::Int=10)\n\nGenerates a random RuleNode of return type typ and maximum depth max_depth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#Base.rand-2","page":"HerbSearch.jl","title":"Base.rand","text":"rand(::Type{RuleNode}, grammar::AbstractGrammar, typ::Symbol, dmap::AbstractVector{Int}, max_depth::Int=10)\n\nGenerates a random RuleNode, i.e. an expression tree, of root type typ and maximum depth max_depth guided by a depth map dmap if possible.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#Base.rand-3","page":"HerbSearch.jl","title":"Base.rand","text":"rand(::Type{RuleNode}, grammar::AbstractGrammar, max_depth::Int=10)\n\nGenerates a random RuleNode of arbitrary type and maximum depth max_depth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch._calculate_cost-Tuple{RuleNode, Function, AbstractVector{HerbSpecification.IOExample}, AbstractGrammar, Function}","page":"HerbSearch.jl","title":"HerbSearch._calculate_cost","text":"_calculate_cost(program::RuleNode, cost_function::Function, spec::AbstractVector{IOExample}, grammar::AbstractGrammar, evaluation_function::Function)\n\nReturns the cost of the program using the examples and the cost_function. It first convert the program to an expression and evaluates it on all the examples.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch._expand-Tuple{Hole, ContextSensitiveGrammar, Int64, Int64, GrammarContext, TopDownIterator}","page":"HerbSearch.jl","title":"HerbSearch._expand","text":"_expand(node::Hole, grammar::ContextSensitiveGrammar, ::Int, max_holes::Int, context::GrammarContext, iter::TopDownIterator)::Union{ExpandFailureReason, Vector{TreeConstraints}}\n\nExpands a given hole that was found in _expand using the given derivation heuristic. Returns the list of discovered nodes in that order and with their respective constraints.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch._expand-Tuple{RuleNode, ContextSensitiveGrammar, Int64, Int64, GrammarContext, TopDownIterator}","page":"HerbSearch.jl","title":"HerbSearch._expand","text":"_expand(root::RuleNode, grammar::ContextSensitiveGrammar, max_depth::Int, max_holes::Int, context::GrammarContext, iter::TopDownIterator)::Union{ExpandFailureReason, Vector{TreeConstraints}}\n\nRecursive expand function used in multiple enumeration techniques. Expands one hole/undefined leaf of the given RuleNode tree found using the given hole heuristic. If the expansion was successful, returns a list of new trees and a list of lists of hole locations, corresponding to the holes of each newly expanded tree. Returns nothing if tree is already complete (i.e. contains no holes). Returns an empty list if the tree is partial (i.e. contains holes), but they could not be expanded because of the depth limit.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch._find_next_complete_tree-Tuple{ContextSensitiveGrammar, Int64, Int64, DataStructures.PriorityQueue, TopDownIterator}","page":"HerbSearch.jl","title":"HerbSearch._find_next_complete_tree","text":"_find_next_complete_tree(grammar::ContextSensitiveGrammar, max_depth::Int, max_size::Int, pq::PriorityQueue, iter::TopDownIterator)::Union{Tuple{RuleNode, PriorityQueue}, Nothing}\n\nTakes a priority queue and returns the smallest AST from the grammar it can obtain from the queue or by (repeatedly) expanding trees that are in the queue. Returns nothing if there are no trees left within the depth limit.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.best_accept-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.best_accept","text":"best_accept(current_cost::Real, next_cost::Real, temperature::Real)\n\nReturns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns false.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the temperature; not used.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.calculate_cost-Union{Tuple{T}, Tuple{T, RuleNode}} where T<:HerbSearch.StochasticSearchIterator","page":"HerbSearch.jl","title":"HerbSearch.calculate_cost","text":"calculate_cost(iter::T, program::RuleNode) where T <: StochasticSearchIterator\n\nWrapper around _calculate_cost.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.const_temperature-Tuple{Real}","page":"HerbSearch.jl","title":"HerbSearch.const_temperature","text":"const_temperature(current_temperature::Real)\n\nReturns the temperature unchanged. This function is used by Metropolis Hastings and Very Large Neighbourhood Search algorithms.\n\nArguments\n\ncurrent_temperature::Real: the current temperature of the search.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.constructNeighbourhood-Tuple{RuleNode, AbstractGrammar}","page":"HerbSearch.jl","title":"HerbSearch.constructNeighbourhood","text":"constructNeighbourhood(current_program::RuleNode, grammar::AbstractGrammar)\n\nThe neighbourhood node location is chosen at random. The dictionary is nothing.\n\nArguments\n\ncurrent_program::RuleNode: the current program.\ngrammar::AbstractGrammar: the grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.constructNeighbourhoodRuleSubset-Tuple{RuleNode, AbstractGrammar}","page":"HerbSearch.jl","title":"HerbSearch.constructNeighbourhoodRuleSubset","text":"constructNeighbourhoodRuleSubset(current_program::RuleNode, grammar::AbstractGrammar)\n\nThe neighbourhood node location is chosen at random. The dictionary is contains one entry with key \"rule_subset\" and value of type Vector{Any} being a random subset of grammar rules.\n\nArguments\n\ncurrent_program::RuleNode: the current program.\ngrammar::AbstractGrammar: the grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.count_expressions-Tuple{AbstractGrammar, Int64, Int64, Symbol}","page":"HerbSearch.jl","title":"HerbSearch.count_expressions","text":"count_expressions(grammar::AbstractGrammar, max_depth::Int, max_size::Int, sym::Symbol)\n\nCounts and returns the number of possible expressions of a grammar up to max_depth with start symbol sym.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.count_expressions-Tuple{ProgramIterator}","page":"HerbSearch.jl","title":"HerbSearch.count_expressions","text":"count_expressions(iter::ProgramIterator)\n\nCounts and returns the number of possible expressions in the expression iterator. The Iterator is not modified.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.cross_over-Tuple{GeneticSearchIterator, RuleNode, RuleNode}","page":"HerbSearch.jl","title":"HerbSearch.cross_over","text":"cross_over(::GeneticSearchIterator, parent_1::RuleNode, parent_2::RuleNode)\n\nCombines the program from two parent individuals to create one or more offspring individuals.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.crossover_swap_children_1-Tuple{RuleNode, RuleNode}","page":"HerbSearch.jl","title":"HerbSearch.crossover_swap_children_1","text":"crossover_swap_children_1(parent_1::RuleNode, parent_2::RuleNode)\n\nPerforms a random crossover of two parents of type RuleNode. The subprograms are swapped and only one altered parent program is returned.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.crossover_swap_children_2-Tuple{RuleNode, RuleNode}","page":"HerbSearch.jl","title":"HerbSearch.crossover_swap_children_2","text":"crossover_swap_children_2(parent_1::RuleNode, parent_2::RuleNode)\n\nPerforms a random crossover of two parents of type RuleNode. The subprograms are swapped and both altered parent programs are returned.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.decreasing_temperature-Tuple{Real}","page":"HerbSearch.jl","title":"HerbSearch.decreasing_temperature","text":"decreasing_temperature(percentage::Real)\n\nReturns a function that produces a temperature decreased by percentage%. This function is used by the Simmulated Annealing algorithm.\n\nArguments\n\npercentage::Real: the percentage to decrease the temperature by.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.default_fitness-Tuple{Any, Any}","page":"HerbSearch.jl","title":"HerbSearch.default_fitness","text":"default_fitness(program, results)\n\nDefines the default fitness function taking the program and its results. Results are a vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}. As we are looking for individuals with the highest fitness function, the error is inverted. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.derivation_heuristic-Tuple{TopDownIterator, Vector{RuleNode}, GrammarContext}","page":"HerbSearch.jl","title":"HerbSearch.derivation_heuristic","text":"derivation_heuristic(::TopDownIterator, nodes::Vector{RuleNode}, ::GrammarContext)::Vector{AbstractRuleNode}\n\nReturns an ordered sublist of nodes, based on which ones are most promising to fill the hole at the given context.\n\nnodes::Vector{RuleNode}: a list of nodes the hole can be filled with\ncontext::GrammarContext: holds the location of the to be filled hole\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.enumerate_neighbours_propose-Tuple{Int64}","page":"HerbSearch.jl","title":"HerbSearch.enumerate_neighbours_propose","text":"enumerate_neighbours_propose(enumeration_depth::Int64)\n\nThe return function is a function that produces a list with all the subprograms with depth at most enumeration_depth.\n\nArguments\n\nenumeration_depth::Int64: the maximum enumeration depth.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.evaluate-Tuple{HerbSpecification.Problem{Vector{HerbSpecification.IOExample}}, Any, Dict{Symbol, Any}}","page":"HerbSearch.jl","title":"HerbSearch.evaluate","text":"evaluate(problem::Problem{Vector{IOExample}}, expr::Any, tab::SymbolTable; allow_evaluation_errors::Bool=false)\n\nEvaluate the expression on the examples.\n\nOptional parameters:\n\n- `shortcircuit` - Whether to stop evaluating after finding single example fails, to speed up the [synth](@ref) procedure. If true, the returned score is an underapproximation of the actual score.\n- `allow_evaluation_errors` - Whether the search should continue if an exception is thrown in the evaluation or throw the error\n\nReturns a score in the interval [0, 1]\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.extractname-Tuple{Any}","page":"HerbSearch.jl","title":"HerbSearch.extractname","text":"extractname(ex)\n\nExtracts the name of a field declaration, otherwise throws an ArgumentError. A field declaration is of the form [::]\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.fitness-Tuple{GeneticSearchIterator, RuleNode, AbstractVector{<:Tuple{Any, Any}}}","page":"HerbSearch.jl","title":"HerbSearch.fitness","text":"fitness(::GeneticSearchIterator, program, results)\n\nAssigns a numerical value (fitness score) to each individual based on how closely it meets the desired objective.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.get_best_program-Tuple{Array{RuleNode}, GeneticSearchIterator}","page":"HerbSearch.jl","title":"HerbSearch.get_best_program","text":"get_best_program(population::Array{RuleNode}, iter::GeneticSearchIterator)::RuleNode\n\nReturns the best program within the population with respect to the fitness function.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_leftmost-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_leftmost","text":"heuristic_leftmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes, where the left-most hole always gets considered first. Returns a HoleReference once a hole is found. This is the default option for enumerators.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_random-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_random","text":"heuristic_random(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes, where random holes get chosen randomly using random exploration. Returns a HoleReference once a hole is found.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_rightmost-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_rightmost","text":"heuristic_rightmost(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes, where the right-most hole always gets considered first. Returns a HoleReference once a hole is found. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.heuristic_smallest_domain-Tuple{AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.heuristic_smallest_domain","text":"heuristic_smallest_domain(node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over all available holes in the unfinished AST, by considering the size of their respective domains. A domain here describes the number of possible derivations with respect to the constraints. Returns a HoleReference once a hole is found. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.hole_heuristic-Tuple{TopDownIterator, AbstractRuleNode, Int64}","page":"HerbSearch.jl","title":"HerbSearch.hole_heuristic","text":"hole_heuristic(::TopDownIterator, node::AbstractRuleNode, max_depth::Int)::Union{ExpandFailureReason, HoleReference}\n\nDefines a heuristic over holes. Returns a HoleReference once a hole is found. \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.is_field_decl-Tuple{Any}","page":"HerbSearch.jl","title":"HerbSearch.is_field_decl","text":"is_field_decl(ex)\n\nCheck if extractname(ex) returns a name.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.mean_squared_error-Tuple{AbstractVector{<:Tuple{Number, Number}}}","page":"HerbSearch.jl","title":"HerbSearch.mean_squared_error","text":"mean_squared_error(results::AbstractVector{Tuple{<:Number,<:Number}})\n\nReturns the mean squared error of results.\n\nArguments\n\nresults<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.misclassification-Tuple{T} where T<:(AbstractVector{<:Tuple{Number, Number}})","page":"HerbSearch.jl","title":"HerbSearch.misclassification","text":"misclassification(results::AbstractVector{Tuple{<:Number,<:Number}})\n\nReturns the amount of misclassified examples, i.e. how many tuples with non-matching entries are there in results.\n\nArguments\n\nresults<:AbstractVector{<:Tuple{Number,Number}}: the vector of tuples, where each tuple is in the form Tuple{expected_output, actual_output}.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.mutate!","page":"HerbSearch.jl","title":"HerbSearch.mutate!","text":"mutate!(::GeneticSearchIterator, program::RuleNode, grammar::AbstractGrammar, max_depth::Int = 2)\n\nMutates the program of an invididual.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.mutate_random!","page":"HerbSearch.jl","title":"HerbSearch.mutate_random!","text":"mutate_random!(program::RuleNode, grammar::AbstractGrammar, max_depth::Int64 = 2)\n\nMutates the given program by inserting a randomly generated sub-program at a random location.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.priority_function-Tuple{BFSIterator, AbstractGrammar, AbstractRuleNode, Union{Real, Tuple{Vararg{Real}}}}","page":"HerbSearch.jl","title":"HerbSearch.priority_function","text":"priority_function(::BFSIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})\n\nAssigns priority such that the search tree is traversed like in a BFS manner\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.priority_function-Tuple{DFSIterator, AbstractGrammar, AbstractRuleNode, Union{Real, Tuple{Vararg{Real}}}}","page":"HerbSearch.jl","title":"HerbSearch.priority_function","text":"priority_function(::DFSIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})\n\nAssigns priority such that the search tree is traversed like in a DFS manner\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.priority_function-Tuple{MLFSIterator, AbstractGrammar, AbstractRuleNode, Union{Real, Tuple{Vararg{Real}}}}","page":"HerbSearch.jl","title":"HerbSearch.priority_function","text":"priority_function(::MLFSIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})\n\nCalculates logit for all possible derivations for a node in a tree and returns them.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.priority_function-Tuple{TopDownIterator, AbstractGrammar, AbstractRuleNode, Union{Real, Tuple{Vararg{Real}}}}","page":"HerbSearch.jl","title":"HerbSearch.priority_function","text":"priority_function(::TopDownIterator, g::AbstractGrammar, tree::AbstractRuleNode, parent_value::Union{Real, Tuple{Vararg{Real}}})\n\nAssigns a priority value to a tree that needs to be considered later in the search. Trees with the lowest priority value are considered first.\n\ng: The grammar used for enumeration\ntree: The tree that is about to be stored in the priority queue\nparent_value: The priority value of the parent PriorityQueueItem\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.probabilistic_accept-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.probabilistic_accept","text":"probabilistic_accept(current_cost::Real, next_cost::Real, temperature::Real)\n\nProbabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program. Returns True if the new program is accepted, False otherwise.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the temperature; not used.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.probabilistic_accept_with_temperature-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.probabilistic_accept_with_temperature","text":"probabilistic_accept_with_temperature(current_cost::Real, next_cost::Real, temperature::Real)\n\nReturns true if the cost of the proposed program is smaller than the cost of the current program. Otherwise, returns true with the probability equal to: \n\n1 (1 + exp(delta temperature))\n\nIn any other case, returns false.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the temperature of the search.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.probabilistic_accept_with_temperature_fraction-Tuple{Real, Real, Real}","page":"HerbSearch.jl","title":"HerbSearch.probabilistic_accept_with_temperature_fraction","text":"probabilistic_accept_with_temperature_fraction(current_cost::Real, program_to_consider_cost::Real, temperature::Real)\n\nProbabilistically decides whether to accept the new program (next) based on the ratio of costs (smaller is better) between the previous and new program multiplied by the temperature. Returns True if the new program is accepted, False otherwise.\n\nArguments\n\ncurrent_cost::Real: the cost of the current program.\nnext_cost::Real: the cost of the proposed program.\ntemperature::Real: the current temperature \n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.processkwarg!-Tuple{Vector{Expr}, Union{Expr, Symbol}}","page":"HerbSearch.jl","title":"HerbSearch.processkwarg!","text":"processkwarg!(keywords::Vector{Expr}, ex::Union{Expr, Symbol})\n\nChecks if ex has a default value specified, if so it returns only the field declaration, and pushes ex to keywords. Otherwise it returns ex\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.propagate_constraints","page":"HerbSearch.jl","title":"HerbSearch.propagate_constraints","text":"function propagate_constraints(root::AbstractRuleNode, grammar::ContextSensitiveGrammar, local_constraints::Set{LocalConstraint}, max_holes::Int, filled_hole::Union{HoleReference, Nothing}=nothing)::Tuple{PropagateResult, Set{LocalConstraint}}\n\nPropagates a set of local constraints recursively to all children of a given root node. As propagate_constraints gets often called when a hole was just filled, filled_hole helps keeping track to propagate the constraints to relevant nodes, e.g. children of filled_hole. max_holes makes sure that max_size of Base.iterate is not violated. The function returns the PropagateResult and the set of relevant LocalConstraints.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#HerbSearch.random_fill_propose-Tuple{RuleNode, NodeLoc, AbstractGrammar, Int64, AbstractVector{Int64}, Union{Nothing, Dict{String, Any}}}","page":"HerbSearch.jl","title":"HerbSearch.random_fill_propose","text":"random_fill_propose(current_program::RuleNode, neighbourhood_node_loc::NodeLoc, grammar::AbstractGrammar, max_depth::Int, dmap::AbstractVector{Int}, dict::Union{Nothing,Dict{String,Any}})\n\nReturns a list with only one proposed, completely random, subprogram.\n\nArguments\n\ncurrent_program::RuleNode: the current program.\nneighbourhood_node_loc::NodeLoc: the location of the program to replace.\ngrammar::AbstractGrammar: the grammar used to create programs.\nmax_depth::Int: the maximum depth of the resulting programs.\ndmap::AbstractVector{Int} : the minimum possible depth to reach for each rule\ndict::Dict{String, Any}: the dictionary with additional arguments; not used.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.select_chromosome-Tuple{Array{RuleNode}, Array{<:Real}}","page":"HerbSearch.jl","title":"HerbSearch.select_chromosome","text":"select_chromosome(population::Array{RuleNode}, fitness_array::Array{<:Real})::RuleNode\n\nSelects a chromosome (individual) from the population based on a fitness array. The function uses a fitness-proportionate selection strategy, often referred to as \"roulette wheel\" selection. Assumes fitness_array to be normalized already.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.select_fitness_proportional_parents-Tuple{Array{RuleNode}, Array{<:Real}}","page":"HerbSearch.jl","title":"HerbSearch.select_fitness_proportional_parents","text":"select_fitness_proportional_parents(population::Array{RuleNode}, fitness_array::Array{<:Real})::Tuple{RuleNode,RuleNode}\n\nSelects two parent chromosomes (individuals) from a population based on fitness-proportionate selection. The selected parents can be used for genetic crossover in the next steps of the algorithm.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.select_parents-Tuple{GeneticSearchIterator, Array{RuleNode}, Array{<:Real}}","page":"HerbSearch.jl","title":"HerbSearch.select_parents","text":"select_parents(::GeneticSearchIterator, population::Array{RuleNode}, fitness_array::Array{<:Real})\n\nSelects two parents for the crossover.\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.synth-Tuple{HerbSpecification.Problem, ProgramIterator}","page":"HerbSearch.jl","title":"HerbSearch.synth","text":"synth(problem::Problem, iterator::ProgramIterator; shortcircuit::Bool=true, allow_evaluation_errors::Bool=false, mod::Module=Main)::Union{Tuple{RuleNode, SynthResult}, Nothing}\n\nSynthesize a program that satisfies the maximum number of examples in the problem. - problem - The problem definition with IO examples - iterator - The iterator that will be used - shortcircuit - Whether to stop evaluating after finding a single example that fails, to speed up the synth procedure. If true, the returned score is an underapproximation of the actual score. - allowevaluationerrors - Whether the search should crash if an exception is thrown in the evaluation - mod - A module containing definitions for the functions in the grammar that do not exist in Main\n\nReturns a tuple of the rulenode representing the solution program and a synthresult that indicates if that program is optimal. synth uses evaluate which returns a score in the interval [0, 1] and checks whether that score reaches 1. If not it will return the best program so far, with the proper flag\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#HerbSearch.validate_iterator-Tuple{Any}","page":"HerbSearch.jl","title":"HerbSearch.validate_iterator","text":"validate_iterator(iter)\n\nValidates the parameters of the iterator\n\n\n\n\n\n","category":"method"},{"location":"HerbSearch/#StatsBase.sample","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(::Type{NodeLoc}, root::RuleNode, typ::Symbol, grammar::AbstractGrammar)\n\nUniformly selects a random node in the tree of a given type, specified using its parent such that the subtree can be replaced. Returns a NodeLoc.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#StatsBase.sample-2","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(root::RuleNode, typ::Symbol, grammar::AbstractGrammar,\n maxdepth::Int=typemax(Int))\n\nUniformly selects a random node of the given return type typ limited by maxdepth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#StatsBase.sample-3","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(::Type{NodeLoc}, root::RuleNode, maxdepth::Int=typemax(Int))\n\nUniformly selects a random node in the tree no deeper than maxdepth using reservoir sampling. Returns a NodeLoc that specifies the location using its parent so that the subtree can be replaced.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/#StatsBase.sample-4","page":"HerbSearch.jl","title":"StatsBase.sample","text":"sample(root::RuleNode, typ::Symbol, grammar::AbstractGrammar, maxdepth::Int=typemax(Int))\n\nUniformly samples a random node from the tree limited to maxdepth.\n\n\n\n\n\n","category":"function"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"The HerbSearch package takes care of all operations related to searching for the desired program. This includes","category":"page"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"the functionality to sample a certain program given a grammar,\nthe implementation of several heuristic functions,\nsearching for a program that satisfies the specification, and\nimplementations of several search algorithms in terms of how they enumerate the search space\nBreadth-First Search \nDepth-First Search \nMetropolis Hastings \nVery Large Scale Neighbourhood Search \nSimulated Annealing\nGenetic Search","category":"page"},{"location":"HerbSearch/#Index","page":"HerbSearch.jl","title":"Index","text":"","category":"section"},{"location":"HerbSearch/","page":"HerbSearch.jl","title":"HerbSearch.jl","text":"","category":"page"},{"location":"HerbCore/#HerbCore_docs","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"","category":"section"},{"location":"HerbCore/","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"CurrentModule=HerbCore","category":"page"},{"location":"HerbCore/","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"Modules = [HerbCore]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbCore/#HerbCore.AbstractGrammar","page":"HerbCore.jl Documentation","title":"HerbCore.AbstractGrammar","text":"AbstractGrammar\n\nAbstract type representing all grammars. It is assumed that all grammar structs have at least the following attributes:\n\nrules::Vector{Any}: A list of RHS of rules (subexpressions).\ntypes::Vector{Symbol}: A list of LHS of rules (types, all symbols).\nisterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.\niseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.\nbytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.\ndomains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.\nchildtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. \n\nIf a rule is terminal, the corresponding list is empty.\n\nlog_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. \n\nIf the grammar is non-probabilistic, the list can be nothing.\n\nFor concrete types, see ContextSensitiveGrammar within the HerbGrammar module.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.AbstractRuleNode","page":"HerbCore.jl Documentation","title":"HerbCore.AbstractRuleNode","text":"AbstractRuleNode\n\nAbstract type for representing expression trees. Expression trees consist of RuleNodes and Holes.\n\nA RuleNode represents a certain production rule in the AbstractGrammar.\nA Hole is a placeholder where certain rules in the grammar still can be applied. \n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.Constraint","page":"HerbCore.jl Documentation","title":"HerbCore.Constraint","text":"Represents a constraint for a ContextSensitiveGrammar. Concrete implementations can be found in HerbConstraints.jl.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.Hole","page":"HerbCore.jl Documentation","title":"HerbCore.Hole","text":"Hole <: AbstractRuleNode\n\nA Hole is a placeholder where certain rules from the grammar can still be applied. The domain of a Hole defines which rules can be applied. The domain is a bitvector, where the ith bit is set to true if the ith rule in the grammar can be applied. \n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.HoleReference","page":"HerbCore.jl Documentation","title":"HerbCore.HoleReference","text":"HoleReference\n\nContains a hole and the path to the hole from the root of the tree.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.RuleNode","page":"HerbCore.jl Documentation","title":"HerbCore.RuleNode","text":"RuleNode <: AbstractRuleNode\n\nA RuleNode represents a node in an expression tree. Each node corresponds to a certain rule in the AbstractGrammar. A RuleNode consists of:\n\nind: The index of the rule in the AbstractGrammar which this node is representing.\n_val: Field for storing immediately evaluated values\nchildren: The children of this node in the expression tree\n\ncompat: Compat\nEvaluate immediately functionality is not yet supported by most of Herb.jl.\n\n\n\n\n\n","category":"type"},{"location":"HerbCore/#HerbCore.RuleNode-Tuple{Int64, Any}","page":"HerbCore.jl Documentation","title":"HerbCore.RuleNode","text":"RuleNode(ind::Int, _val::Any)\n\nCreate a RuleNode for the AbstractGrammar rule with index ind, _val as immediately evaluated value and no children\n\nwarning: Warning\nOnly use this constructor if you are absolutely certain that a rule is terminal and cannot have children. Use [RuleNode(ind::Int, grammar::AbstractGrammar)] for rules that might have children. In general, Holes should be used as a placeholder when the children of a node are not yet known. \n\ncompat: Compat\nEvaluate immediately functionality is not yet supported by most of Herb.jl.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.RuleNode-Tuple{Int64, Vector{AbstractRuleNode}}","page":"HerbCore.jl Documentation","title":"HerbCore.RuleNode","text":"RuleNode(ind::Int, children::Vector{AbstractRuleNode})\n\nCreate a RuleNode for the AbstractGrammar rule with index ind and children as subtrees.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Base.isless-Tuple{AbstractRuleNode, AbstractRuleNode}","page":"HerbCore.jl Documentation","title":"Base.isless","text":"Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode)::Bool\n\nCompares two RuleNodes. Returns true if the left RuleNode is less than the right RuleNode. Order is determined from the index of the RuleNodes. If both RuleNodes have the same index, a depth-first search is performed in both RuleNodes until nodes with a different index are found.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Base.length-Tuple{Hole}","page":"HerbCore.jl Documentation","title":"Base.length","text":"Base.length(root::RuleNode)\n\nReturn the number of nodes in the tree rooted at root. Holes don't count.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Base.length-Tuple{RuleNode}","page":"HerbCore.jl Documentation","title":"Base.length","text":"Base.length(root::RuleNode)\n\nReturn the number of nodes in the tree rooted at root. Holes don't count.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.contains_hole-Tuple{RuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.contains_hole","text":"contains_hole(rn::RuleNode) = any(contains_hole(c) for c ∈ rn.children)\n\nChecks if an AbstractRuleNode tree contains a Hole.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.depth-Tuple{RuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.depth","text":"depth(root::RuleNode)::Int\n\nReturn the depth of the AbstractRuleNode tree rooted at root. Holes don't count towards the depth.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.get_node_at_location-Tuple{RuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.get_node_at_location","text":"get_node_at_location(root::RuleNode, location::Vector{Int})\n\nRetrieves a RuleNode at the given location by reference. \n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.get_rulesequence-Tuple{RuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.get_rulesequence","text":"get_rulesequence(node::RuleNode, path::Vector{Int})\n\nExtract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.node_depth-Tuple{AbstractRuleNode, AbstractRuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.node_depth","text":"node_depth(root::AbstractRuleNode, node::AbstractRuleNode)::Int\n\nReturn the depth of node for an AbstractRuleNode tree rooted at root. Depth is 1 when root == node.\n\nwarning: Warning\nnode must be a subtree of root in order for this function to work.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.rulesoftype-Tuple{RuleNode, Set{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.rulesoftype","text":"rulesoftype(node::RuleNode, ruleset::Set{Int})\n\nReturns every rule in the ruleset that is also used in the AbstractRuleNode tree.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.rulesonleft-Tuple{RuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.rulesonleft","text":"rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}\n\nFinds all rules that are used in the left subtree defined by the path.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.swap_node-Tuple{AbstractRuleNode, AbstractRuleNode, Vector{Int64}}","page":"HerbCore.jl Documentation","title":"HerbCore.swap_node","text":"swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})\n\nReplace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#HerbCore.swap_node-Tuple{RuleNode, RuleNode, Int64, RuleNode}","page":"HerbCore.jl Documentation","title":"HerbCore.swap_node","text":"swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)\n\nReplace child i of a node, a part of larger expr, with new_expr.\n\n\n\n\n\n","category":"method"},{"location":"HerbCore/#Index","page":"HerbCore.jl Documentation","title":"Index","text":"","category":"section"},{"location":"HerbCore/","page":"HerbCore.jl Documentation","title":"HerbCore.jl Documentation","text":"","category":"page"},{"location":"HerbGrammar/#HerbGrammar_docs","page":"HerbGrammar.jl","title":"HerbGrammar.jl Documentation","text":"","category":"section"},{"location":"HerbGrammar/","page":"HerbGrammar.jl","title":"HerbGrammar.jl","text":"CurrentModule=HerbGrammar","category":"page"},{"location":"HerbGrammar/","page":"HerbGrammar.jl","title":"HerbGrammar.jl","text":"Modules = [HerbGrammar]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbGrammar/#HerbGrammar.ContextSensitiveGrammar","page":"HerbGrammar.jl","title":"HerbGrammar.ContextSensitiveGrammar","text":"ContextSensitiveGrammar <: AbstractGrammar\n\nRepresents a context-sensitive grammar. Extends AbstractGrammar with constraints.\n\nConsists of:\n\nrules::Vector{Any}: A list of RHS of rules (subexpressions).\ntypes::Vector{Symbol}: A list of LHS of rules (types, all symbols).\nisterminal::BitVector: A bitvector where bit i represents whether rule i is terminal.\niseval::BitVector: A bitvector where bit i represents whether rule i is an eval rule.\nbytype::Dict{Symbol,Vector{Int}}: A dictionary that maps a type to all rules of said type.\ndomains::Dict{Symbol, BitVector}: A dictionary that maps a type to a domain bitvector. The domain bitvector has bit i set to true iff the ith rule is of this type.\nchildtypes::Vector{Vector{Symbol}}: A list of types of the children for each rule. If a rule is terminal, the corresponding list is empty.\nlog_probabilities::Union{Vector{Real}, Nothing}: A list of probabilities for each rule. If the grammar is non-probabilistic, the list can be nothing.\nconstraints::Vector{Constraint}: A list of constraints that programs in this grammar have to abide.\n\nUse the @csgrammar macro to create a ContextSensitiveGrammar object. Use the @pcsgrammar macro to create a ContextSensitiveGrammar object with probabilities.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.NodeLoc","page":"HerbGrammar.jl","title":"HerbGrammar.NodeLoc","text":"NodeLoc A helper struct that points to a node in the tree via its parent such that the child can be easily swapped out. If i is 0 the node pointed to is the root node and parent is the node itself.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.SymbolTable","page":"HerbGrammar.jl","title":"HerbGrammar.SymbolTable","text":"SymbolTable(grammar::AbstractGrammar, mod::Module=Main)\n\nReturns a SymbolTable populated with a mapping from symbols in the AbstractGrammar to symbols in module mod or Main, if defined.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.SymbolTable-2","page":"HerbGrammar.jl","title":"HerbGrammar.SymbolTable","text":"SymbolTable\n\nData structure for mapping terminal symbols in the AbstractGrammar to their Julia interpretation.\n\n\n\n\n\n","category":"type"},{"location":"HerbGrammar/#HerbGrammar.@csgrammar-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.@csgrammar","text":"@csgrammar\n\nA macro for defining a ContextSensitiveGrammar. Constraints can be added afterwards using the addconstraint! function.\n\nExample usage:\n\ngrammar = @csgrammar begin\n\tR = x\n\tR = 1 | 2\n\tR = R + R\nend\n\nSyntax:\n\nLiterals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.\nVariables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.\nFunctions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).\nCombinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.\nIterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).\n\nRelated:\n\n@pcsgrammar uses a similar syntax to create probabilistic ContextSensitiveGrammars.\n\n\n\n\n\n","category":"macro"},{"location":"HerbGrammar/#HerbGrammar.@pcsgrammar-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.@pcsgrammar","text":"@pcsgrammar\n\nA macro for defining a probabilistic ContextSensitiveGrammar. \n\nExample usage:\n\ngrammar = @pcsgrammar begin\n\t0.5 : R = x\n\t0.3 : R = 1 | 2\n\t0.2 : R = R + R\nend\n\nSyntax:\n\nThe syntax of rules is identical to the syntax used by @csgrammar:\n\nLiterals: Symbols that are already defined in Julia are considered literals, such as 1, 2, or π. For example: R = 1.\nVariables: A variable is a symbol that is not a nonterminal symbol and not already defined in Julia. For example: R = x.\nFunctions: Functions and infix operators that are defined in Julia or the Main module can be used with the default evaluator. For example: R = R + R, R = f(a, b).\nCombinations: Multiple rules can be defined on a single line in the grammar definition using the | symbol. For example: R = 1 | 2 | 3.\nIterators: Another way to define multiple rules is by providing a Julia iterator after a | symbol. For example: R = |(1:9).\n\nEvery rule is also prefixed with a probability. Rules and probabilities are separated using the : symbol. If multiple rules are defined on a single line, the probability is equally divided between the rules. The sum of probabilities for all rules of a certain non-terminal symbol should be equal to 1. The probabilities are automatically scaled if this isn't the case.\n\nRelated:\n\n@csgrammar uses a similar syntax to create non-probabilistic ContextSensitiveGrammars.\n\n\n\n\n\n","category":"macro"},{"location":"HerbGrammar/#Base.get-Tuple{RuleNode, NodeLoc}","page":"HerbGrammar.jl","title":"Base.get","text":"get(root::RuleNode, loc::NodeLoc) Obtain the node pointed to by loc.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#Base.insert!-Tuple{RuleNode, NodeLoc, RuleNode}","page":"HerbGrammar.jl","title":"Base.insert!","text":"insert!(loc::NodeLoc, rulenode::RuleNode) Replaces the subtree pointed to by loc with the given rulenode.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.add_rule!-Tuple{AbstractGrammar, Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.add_rule!","text":"add_rule!(g::AbstractGrammar, e::Expr)\n\nAdds a rule to the grammar. \n\nUsage:\n\n\tadd_rule!(grammar, :(\"Real = Real + Real\"))\n\nThe syntax is identical to the syntax of @csgrammar and @cfgrammar, but only single rules are supported.\n\nwarning: Warning\nCalls to this function are ignored if a rule is already in the grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.add_rule!-Tuple{AbstractGrammar, Real, Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.add_rule!","text":"Adds a probabilistic derivation rule.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.addconstraint!-Tuple{ContextSensitiveGrammar, Constraint}","page":"HerbGrammar.jl","title":"HerbGrammar.addconstraint!","text":"addconstraint!(grammar::ContextSensitiveGrammar, c::Constraint)\n\nAdds a Constraint to a ContextSensitiveGrammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.child_types-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.child_types","text":"child_types(grammar::AbstractGrammar, rule_index::Int)\n\nReturns the types of the children (nonterminals) of the production rule at rule_index.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.child_types-Tuple{AbstractGrammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.child_types","text":"child_types(grammar::AbstractGrammar, node::RuleNode)\n\nReturns the list of child types (nonterminal symbols) in the production rule used by node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.cleanup_removed_rules!-Tuple{AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.cleanup_removed_rules!","text":"cleanup_removed_rules!(g::AbstractGrammar)\n\nRemoves any placeholders for previously deleted rules. This means that indices get shifted.\n\nwarning: Warning\nWhen indices are shifted, this grammar can no longer be used to interpret AbstractRuleNode trees created before the call to this function. These trees become meaningless. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.clearconstraints!-Tuple{ContextSensitiveGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.clearconstraints!","text":"Clear all constraints from the grammar\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.containedin-Tuple{Vector, Vector}","page":"HerbGrammar.jl","title":"HerbGrammar.containedin","text":"containedin(vec1::Vector, vec2::Vector)\n\nChecks if elements of vec1 are contained in vec2 in the same order (possibly with elements in between)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.contains_returntype","page":"HerbGrammar.jl","title":"HerbGrammar.contains_returntype","text":"contains_returntype(node::RuleNode, grammar::AbstractGrammar, sym::Symbol, maxdepth::Int=typemax(Int))\n\nReturns true if the tree rooted at node contains at least one node at depth less than maxdepth with the given return type or nonterminal symbol.\n\n\n\n\n\n","category":"function"},{"location":"HerbGrammar/#HerbGrammar.expr2csgrammar-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.expr2csgrammar","text":"expr2csgrammar(ex::Expr)::ContextSensitiveGrammar\n\nA function for converting an Expr to a ContextSensitiveGrammar. If the expression is hardcoded, you should use the @csgrammar macro. Only expressions in the correct format (see @csgrammar) can be converted.\n\nExample usage:\n\ngrammar = expr2csgrammar(\n\tbegin\n\t\tR = x\n\t\tR = 1 | 2\n\t\tR = R + R\n\tend\n)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.expr2pcsgrammar-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.expr2pcsgrammar","text":"Function for converting an Expr to a ContextSensitiveGrammar with probabilities. If the expression is hardcoded, you should use the @pcsgrammar macro. Only expressions in the correct format (see @pcsgrammar) can be converted.\n\nExample usage:\n\ngrammar = expr2pcsgrammar(\n\tbegin\n\t\t0.5 : R = x\n\t\t0.3 : R = 1 | 2\n\t\t0.2 : R = R + R\n\tend\n)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_childtypes-Tuple{Any, AbstractVector{Symbol}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_childtypes","text":"get_childtypes(rule::Any, types::AbstractVector{Symbol})\n\nReturns the child types/nonterminals of a production rule.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_domain-Tuple{AbstractGrammar, Symbol}","page":"HerbGrammar.jl","title":"HerbGrammar.get_domain","text":"get_domain(g::AbstractGrammar, type::Symbol)::BitVector\n\nReturns the domain for the hole of a certain type as a BitVector of the same length as the number of rules in the grammar. Bit i is set to true iff rule i is of type type.\n\ninfo: Info\nSince this function can be intensively used when exploring a program space defined by a grammar, the outcomes of this function are precomputed and stored in the domains field in a AbstractGrammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_domain-Tuple{AbstractGrammar, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_domain","text":"get_domain(g::AbstractGrammar, rules::Vector{Int})::BitVector\n\nTakes a domain rules defined as a vector of ints and converts it to a domain defined as a BitVector.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_node_at_location-Tuple{RuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_node_at_location","text":"get_node_at_location(root::RuleNode, location::Vector{Int})\n\nRetrieves a RuleNode at the given location by reference. \n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.get_rulesequence-Tuple{RuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.get_rulesequence","text":"get_rulesequence(node::RuleNode, path::Vector{Int})\n\nExtract the derivation sequence from a path (sequence of child indices) and an AbstractRuleNode. If the path is deeper than the deepest node, it returns what it has.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.has_children-Tuple{RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.has_children","text":"has_children(node::RuleNode)\n\nReturns true if node has children\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iscomplete-Tuple{AbstractGrammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.iscomplete","text":"iscomplete(grammar::AbstractGrammar, node::RuleNode)\n\nReturns true if the expression represented by the RuleNode is a complete expression, meaning that it is fully defined and doesn't have any Holes.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iseval-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.iseval","text":"iseval(grammar::AbstractGrammar, index::Int)::Bool\n\nReturns true if the production rule at rule_index contains the special _() eval function.\n\ncompat: Compat\nevaluate immediately functionality is not yet supported by most of Herb.jl\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iseval-Tuple{AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.iseval","text":"iseval(grammar::AbstractGrammar)::Bool\n\nReturns true if any production rules in grammar contain the special _() eval function.\n\ncompat: Compat\nevaluate immediately functionality is not yet supported by most of Herb.jl\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.iseval-Tuple{Any}","page":"HerbGrammar.jl","title":"HerbGrammar.iseval","text":"iseval(rule)\n\nReturns true if the rule is the special evaluate immediately function, i.e., _()\n\ncompat: Compat\nevaluate immediately functionality is not yet supported by most of Herb.jl\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isprobabilistic-Tuple{AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.isprobabilistic","text":"isprobabilistic(grammar::AbstractGrammar)::Bool\n\nFunction returns whether a AbstractGrammar is probabilistic.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isterminal-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.isterminal","text":"isterminal(grammar::AbstractGrammar, rule_index::Int)::Bool\n\nReturns true if the production rule at rule_index is terminal, i.e., does not contain any nonterminal symbols.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isterminal-Tuple{AbstractGrammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.isterminal","text":"isterminal(grammar::AbstractGrammar, node::RuleNode)::Bool\n\nReturns true if the production rule used by node is terminal, i.e., does not contain any nonterminal symbols.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isterminal-Tuple{Any, AbstractVector{Symbol}}","page":"HerbGrammar.jl","title":"HerbGrammar.isterminal","text":"isterminal(rule::Any, types::AbstractVector{Symbol})\n\nReturns true if the rule is terminal, i.e., it does not contain any of the types in the provided vector. For example, :(x) is terminal, and :(1+1) is terminal, but :(Real + Real) is typically not.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isvariable-Tuple{AbstractGrammar, Int64, Vararg{Module}}","page":"HerbGrammar.jl","title":"HerbGrammar.isvariable","text":"isvariable(grammar::AbstractGrammar, ind::Int, mod::Module)::Bool\n\nReturn true if the rule with index ind represents a variable.\n\nTaking into account the symbols defined in the given module(s).\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isvariable-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.isvariable","text":"isvariable(grammar::AbstractGrammar, ind::Int)::Bool\n\nReturn true if the rule with index ind represents a variable.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isvariable-Tuple{AbstractGrammar, RuleNode, Vararg{Module}}","page":"HerbGrammar.jl","title":"HerbGrammar.isvariable","text":"isvariable(grammar::AbstractGrammar, node::RuleNode, mod::Module)::Bool\n\nReturn true if the rule used by node represents a variable.\n\nTaking into account the symbols defined in the given module(s).\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.isvariable-Tuple{AbstractGrammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.isvariable","text":"isvariable(grammar::AbstractGrammar, node::RuleNode)::Bool\n\nReturn true if the rule used by node represents a variable in a program (essentially, an input to the program)\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.log_probability-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.log_probability","text":"log_probability(grammar::AbstractGrammar, index::Int)::Real\n\nReturns the log probability for the rule at index in the grammar.\n\nwarning: Warning\nIf the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.max_arity-Tuple{AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.max_arity","text":"max_arity(grammar::AbstractGrammar)::Int\n\nReturns the maximum arity (number of children) over all production rules in the AbstractGrammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.merge_grammars!-Tuple{AbstractGrammar, AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.merge_grammars!","text":"merge_grammars!(merge_to::AbstractGrammar, merge_from::AbstractGrammar)\n\nAdds all rules and constraints from merge_from to merge_to.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.mindepth-Tuple{AbstractGrammar, Symbol, AbstractVector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.mindepth","text":"mindepth(grammar::AbstractGrammar, typ::Symbol, dmap::AbstractVector{Int})\n\nReturns the minimum depth achievable for a given nonterminal symbol. The minimum depth is the depth of the lowest tree that can be made using typ as a start symbol. dmap can be obtained from mindepth_map.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.mindepth_map-Tuple{AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.mindepth_map","text":"mindepth_map(grammar::AbstractGrammar)\n\nReturns the minimum depth achievable for each production rule in the AbstractGrammar. In other words, this function finds the depths of the lowest trees that can be made using each of the available production rules as a root.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.nchildren-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.nchildren","text":"nchildren(grammar::AbstractGrammar, rule_index::Int)::Int\n\nReturns the number of children (nonterminals) of the production rule at rule_index.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.nchildren-Tuple{AbstractGrammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.nchildren","text":"nchildren(grammar::AbstractGrammar, node::RuleNode)::Int\n\nReturns the number of children in the production rule used by node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.nonterminals-Tuple{AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.nonterminals","text":"nonterminals(grammar::AbstractGrammar)::Vector{Symbol}\n\nReturns a list of the nonterminals or types in the AbstractGrammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.normalize!","page":"HerbGrammar.jl","title":"HerbGrammar.normalize!","text":"A function for normalizing the probabilities of a probabilistic ContextSensitiveGrammar. If the optional type argument is provided, only the rules of that type are normalized.\n\n\n\n\n\n","category":"function"},{"location":"HerbGrammar/#HerbGrammar.parse_probabilistic_rule-Tuple{Expr}","page":"HerbGrammar.jl","title":"HerbGrammar.parse_probabilistic_rule","text":"Parses a single (potentially shorthand) derivation rule of a probabilistic ContextSensitiveGrammar. Returns nothing if the rule is not probabilistic, otherwise a Tuple of its type and a Vector of probability-rule pairs it expands into.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.probability-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.probability","text":"probability(grammar::AbstractGrammar, index::Int)::Real\n\nReturn the probability for a rule in the grammar. Use log_probability whenever possible.\n\nwarning: Warning\nIf the grammar is not probabilistic, a warning is displayed, and a uniform probability is assumed.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.read_csg","page":"HerbGrammar.jl","title":"HerbGrammar.read_csg","text":"read_csg(grammarpath::AbstractString, constraintspath::OptionalPath=nothing)::ContextSensitiveGrammar\n\nReads a ContextSensitiveGrammar from the files at grammarpath and constraintspath.\n\ndanger: Danger\nOnly open trusted grammars. Parts of the grammar can be passed to Julia's eval function. \n\n\n\n\n\n","category":"function"},{"location":"HerbGrammar/#HerbGrammar.read_pcsg","page":"HerbGrammar.jl","title":"HerbGrammar.read_pcsg","text":"read_pcsg(grammarpath::AbstractString, constraintspath::OptionalPath=nothing)::ContextSensitiveGrammar\n\nReads a probabilistic ContextSensitiveGrammar from the files at grammarpath and constraintspath.\n\ndanger: Danger\nOnly open trusted grammars. Parts of the grammar can be passed to Julia's eval function. \n\n\n\n\n\n","category":"function"},{"location":"HerbGrammar/#HerbGrammar.remove_rule!-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.remove_rule!","text":"remove_rule!(g::AbstractGrammar, idx::Int)\n\nRemoves the rule corresponding to idx from the grammar. In order to avoid shifting indices, the rule is replaced with nothing, and all other data structures are updated accordingly.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.return_type-Tuple{AbstractGrammar, Int64}","page":"HerbGrammar.jl","title":"HerbGrammar.return_type","text":"return_type(grammar::AbstractGrammar, rule_index::Int)::Symbol\n\nReturns the type of the production rule at rule_index.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.return_type-Tuple{AbstractGrammar, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.return_type","text":"return_type(grammar::AbstractGrammar, node::RuleNode)\n\nGives the return type or nonterminal symbol in the production rule used by node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.root_node_loc-Tuple{RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.root_node_loc","text":"rootnodeloc(root::RuleNode) Returns a NodeLoc pointing to the root node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulenode2expr-Tuple{RuleNode, AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.rulenode2expr","text":"rulenode2expr(rulenode::RuleNode, grammar::AbstractGrammar)\n\nConverts a RuleNode into a Julia expression corresponding to the rule definitions in the grammar. The returned expression can be evaluated with Julia semantics using eval().\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulenode_log_probability-Tuple{RuleNode, AbstractGrammar}","page":"HerbGrammar.jl","title":"HerbGrammar.rulenode_log_probability","text":"Calculates the log probability associated with a rulenode in a probabilistic grammar.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesoftype-Tuple{RuleNode, AbstractGrammar, Symbol, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesoftype","text":"rulesoftype(node::RuleNode, grammar::AbstractGrammar, ruletype::Symbol, ignoreNode::RuleNode)\n\nReturns every rule of nonterminal symbol ruletype that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.\n\nwarning: Warning\nThe ignoreNode must be a subtree of node for it to have an effect.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesoftype-Tuple{RuleNode, AbstractGrammar, Symbol}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesoftype","text":"rulesoftype(node::RuleNode, grammar::AbstractGrammar, ruletype::Symbol)\n\nReturns every rule of nonterminal symbol ruletype that is also used in the AbstractRuleNode tree.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesoftype-Tuple{RuleNode, Set{Int64}, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesoftype","text":"rulesoftype(node::RuleNode, ruleset::Set{Int}, ignoreNode::RuleNode)\n\nReturns every rule in the ruleset that is also used in the AbstractRuleNode tree, but not in the ignoreNode subtree.\n\nwarning: Warning\nThe ignoreNode must be a subtree of node for it to have an effect.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.rulesonleft-Tuple{RuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.rulesonleft","text":"rulesonleft(expr::RuleNode, path::Vector{Int})::Set{Int}\n\nFinds all rules that are used in the left subtree defined by the path.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.store_csg","page":"HerbGrammar.jl","title":"HerbGrammar.store_csg","text":"store_csg(g::ContextSensitiveGrammar, grammarpath::AbstractString, constraintspath::OptionalPath=nothing)\n\nWrites a ContextSensitiveGrammar to the files at grammarpath and constraintspath. The grammarpath file will contain a ContextSensitiveGrammar definition, and the constraintspath file will contain the Constraints of the ContextSensitiveGrammar.\n\n\n\n\n\n","category":"function"},{"location":"HerbGrammar/#HerbGrammar.subsequenceof-Tuple{Vector{Int64}, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.subsequenceof","text":"subsequenceof(vec1::Vector{Int}, vec2::Vector{Int})\n\nChecks if vec1 is a subsequence of vec2.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.swap_node-Tuple{AbstractRuleNode, AbstractRuleNode, Vector{Int64}}","page":"HerbGrammar.jl","title":"HerbGrammar.swap_node","text":"swap_node(expr::AbstractRuleNode, new_expr::AbstractRuleNode, path::Vector{Int})\n\nReplace a node in expr, specified by path, with new_expr. Path is a sequence of child indices, starting from the root node.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#HerbGrammar.swap_node-Tuple{RuleNode, RuleNode, Int64, RuleNode}","page":"HerbGrammar.jl","title":"HerbGrammar.swap_node","text":"swap_node(expr::RuleNode, node::RuleNode, child_index::Int, new_expr::RuleNode)\n\nReplace child i of a node, a part of larger expr, with new_expr.\n\n\n\n\n\n","category":"method"},{"location":"HerbGrammar/#Index","page":"HerbGrammar.jl","title":"Index","text":"","category":"section"},{"location":"HerbGrammar/","page":"HerbGrammar.jl","title":"HerbGrammar.jl","text":"","category":"page"},{"location":"HerbConstraints/#HerbConstraints_docs","page":"HerbConstraints.jl","title":"HerbConstraints.jl Documentation","text":"","category":"section"},{"location":"HerbConstraints/","page":"HerbConstraints.jl","title":"HerbConstraints.jl","text":"CurrentModule=HerbConstraints","category":"page"},{"location":"HerbConstraints/","page":"HerbConstraints.jl","title":"HerbConstraints.jl","text":"Modules = [HerbConstraints]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbConstraints/#HerbConstraints.AbstractMatchNode","page":"HerbConstraints.jl","title":"HerbConstraints.AbstractMatchNode","text":"abstract type AbstractMatchNode\n\nTree structure to which rulenode trees can be matched. Consists of MatchNodes, which can match a specific RuleNode, and MatchVars, which is a variable that can be filled in with any RuleNode.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.ComesAfter","page":"HerbConstraints.jl","title":"HerbConstraints.ComesAfter","text":"ComesAfter <: PropagatorConstraint\n\nA ComesAfter constraint is a PropagatorConstraint containing the following:\n\nrule::Int: A reference to a rule in the grammar\npredecessors: A list of rules in the grammar\n\nThis Constraint enforces that the rule can only be applied if every rule in predecessors is used in the path from the root of the tree to the current hole in the order that they are given. Even though the rules must be in order, there might be other rules inbetween.\n\nFor example, consider the tree 1(a, 2(b, 3(c, d)))):\n\nComesAfter(4, [2, 3]) would enforce that rule 4 can only be used if 2 and 3 are used in the path from the root in that order. Therefore, only hole c and d can be filled with 4.\nComesAfter(4, [1, 3]) also allows c and d to be filled, since 1 and 3 are still used in the correct order. It does not matter that 2 is also used in the path to the root.\nComesAfter(4, [3, 2]) does not allow any hole to be filled with 4, since either the predecessors are either not in the path or in the wrong order for each of the holes. \n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.ComesAfter-Tuple{Int64, Int64}","page":"HerbConstraints.jl","title":"HerbConstraints.ComesAfter","text":"ComesAfter(rule::Int, predecessor::Int)\n\nCreates a ComesAfter constraint with only a single predecessor. \n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.Condition","page":"HerbConstraints.jl","title":"HerbConstraints.Condition","text":"Condition <: PropagatorConstraint\n\nThis PropagatorConstraint forbids any subtree that matches the pattern defined by tree and where the RuleNode that is matched to the variable in the pattern violates the predicate given by the condition function.\n\nThe condition function takes a RuleNode tree and should return a Bool.\n\nwarning: Warning\nThe Condition constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Condition can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.Forbidden","page":"HerbConstraints.jl","title":"HerbConstraints.Forbidden","text":"Forbidden <: PropagatorConstraint\n\nThis [PropagatorConstraint] forbids any subtree that matches the pattern given by tree to be generated. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the AbstractGrammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical. Any rule in the domain that makes the match attempt successful is removed.\n\nFor example, consider the tree 1(a, 2(b, 3(c, 4)))):\n\nForbidden(MatchNode(3, [MatchNode(5), MatchNode(4)])) forbids c to be filled with 5.\nForbidden(MatchNode(3, [MatchVar(:v), MatchNode(4)])) forbids c to be filled, since a [MatchVar] can match any rule, thus making the match attempt successful for the entire domain of c. Therefore, this tree invalid.\nForbidden(MatchNode(3, [MatchVar(:v), MatchVar(:v)])) forbids c to be filled with 4, since that would make both assignments to v equal, which causes a successful match.\n\nwarning: Warning\nThe Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.ForbiddenPath","page":"HerbConstraints.jl","title":"HerbConstraints.ForbiddenPath","text":"ForbiddenPath <: PropagatorConstraint\n\nA [PropagatorConstraint] that forbids a certain derivation sequence. sequence defines the forbidden sequence. Each rule that would complete the sequence when expanding a Hole in an AbstractRuleNode tree is removed from the domain. The derivation sequence is the path from the root to the hole.\n\nFor example, consider the tree 1(a, 2(b, 3(c, d)))):\n\nForbiddenPath([1, 2, 4]) enforces that rule 4 cannot be applied at b, since it completes the sequence. However, it can be applied at a, c and d.\nForbiddenPath([3, 1]) enforces that rule 1 cannot be applied at c or d.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.GrammarContext","page":"HerbConstraints.jl","title":"HerbConstraints.GrammarContext","text":"mutable struct GrammarContext\n\nStructure used to track the context. Contains: \t- the expression being modified \t- the path to the hole that is being expanded, represented as a sequence of child indices. \t e.g., [2, 1] would point to the first child of the second child of the root. \t- a vector with local constraints that should be propagated upon expansion.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalCondition","page":"HerbConstraints.jl","title":"HerbConstraints.LocalCondition","text":"LocalCondition <: LocalConstraint\n\nForbids any subtree that matches the pattern defined by tree and where the RuleNode that is matched to the variable in the pattern violates the predicate given by the condition function.\n\nThe condition function takes a RuleNode tree and should return a Bool.\n\nThis constraint is only enforced at the location defined by path. Use a Condition constraint for enforcing this throughout the entire search space.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalConstraint","page":"HerbConstraints.jl","title":"HerbConstraints.LocalConstraint","text":"abstract type LocalConstraint <: Constraint\n\nAbstract type representing all local constraints. Local constraints correspond to a specific (partial) AbstractRuleNode tree. Each local constraint contains a path to a specific location in the tree. Each local constraint has an implementation of a propagate-function that takes\n\nthe LocalConstraint\na AbstractGrammar\na GrammarContext, which most importantly contains the tree and the location in the tree where propagation should take place.\nThe domain which the propagate-function prunes. \n\nThe propagate-function returns a tuple containing\n\nThe pruned domain\nA list of new LocalConstraints\n\nwarning: Warning\nBy default, LocalConstraints are only propagated once. Constraints that have to be propagated more frequently should return themselves in the list of new local constraints.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalForbidden","page":"HerbConstraints.jl","title":"HerbConstraints.LocalForbidden","text":"LocalForbidden\n\nForbids the a subtree that matches the MatchNode tree to be generated at the location provided by the path. Use a Forbidden constraint for enforcing this throughout the entire search space.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalOneOf","page":"HerbConstraints.jl","title":"HerbConstraints.LocalOneOf","text":"Meta-constraint that enforces the disjunction of its given constraints.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.LocalOrdered","page":"HerbConstraints.jl","title":"HerbConstraints.LocalOrdered","text":"Enforces an order over two or more subtrees that fill the variables specified in order when the pattern is applied at the location given by path. Use an Ordered constraint for enforcing this throughout the entire search space.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.MatchFail","page":"HerbConstraints.jl","title":"HerbConstraints.MatchFail","text":"@enum MatchFail hardfail softfail\n\nThis enum is used for distinguishing between two types of failures when trying to match a RuleNode either with another RuleNode or with an AbstractMatchNode\n\nHardfail means that there is no match, and there is no way to fill in the holes to get a match.\nSoftfail means that there is no match, but there might be a way to fill the holes that results in a match.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.MatchNode","page":"HerbConstraints.jl","title":"HerbConstraints.MatchNode","text":"struct MatchNode <: AbstractMatchNode\n\nMatch a specific rulenode, where the grammar rule index is rule_ind and children matches the children of the RuleNode. Example usage:\n\nMatchNode(3, [MatchNode(1), MatchNode(2)])\n\nThis matches RuleNode(3, [RuleNode(1), RuleNode(2)])\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.MatchVar","page":"HerbConstraints.jl","title":"HerbConstraints.MatchVar","text":"struct MatchVar <: AbstractMatchNode\n\nMatches anything and assigns it to a variable. The ForbiddenTree constraint will not match if identical variable symbols match to different trees. Example usage:\n\nMatchNode(3, [MatchVar(:x), MatchVar(:x)])\n\nThis matches RuleNode(3, [RuleNode(1), RuleNode(1)]), RuleNode(3, [RuleNode(2), RuleNode(2)]), etc.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.OneOf","page":"HerbConstraints.jl","title":"HerbConstraints.OneOf","text":"Meta-constraint that enforces the disjunction of its given constraints.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.Ordered","page":"HerbConstraints.jl","title":"HerbConstraints.Ordered","text":"Ordered <: PropagatorConstraint\n\nA PropagatorConstraint that enforces a specific order in MatchVar assignments in the pattern defined by tree. A pattern is a tree of AbstractMatchNodes. Such a node can either be a MatchNode, which contains a rule index corresponding to the rule index in the AbstractGrammar and the appropriate number of children, similar to RuleNodes. It can also contain a MatchVar, which contains a single identifier symbol. A MatchVar can match any subtree, but if there are multiple instances of the same variable in the pattern, the matched subtrees must be identical.\n\nThe order defines an order between the variable assignments. For example, if the order is [x, y], the constraint will require the assignment to x to be less than or equal to the assignment to y. The order is recursively defined by RuleNode indices. For more information, see Base.isless(rn₁::AbstractRuleNode, rn₂::AbstractRuleNode).\n\nFor example, consider the tree 1(a, 2(b, 3(c, 4)))):\n\nOrdered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:v, :w]) removes every rule with an index of 5 or greater from the domain of c, since that would make the index of the assignment to v greater than the index of the assignment to w, violating the order.\nOrdered(MatchNode(3, [MatchVar(:v), MatchVar(:w)]), [:w, :v]) removes every rule with an index of 4 or less from the domain of c, since that would make the index of the assignment to v less than the index of the assignment to w, violating the order.\n\nwarning: Warning\nThe Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.PropagatorConstraint","page":"HerbConstraints.jl","title":"HerbConstraints.PropagatorConstraint","text":"PropagatorConstraint <: Constraint\n\nAbstract type representing all propagator constraints. Each propagator constraint has an implementation of a propagate-function that takes\n\nthe PropagatorConstraint\na AbstractGrammar\na GrammarContext, which most importantly contains the tree and the location in the tree where propagation should take place.\nThe domain which the propagate-function prunes. \n\nThe propagate-function returns a tuple containing\n\nThe pruned domain\nA list of new LocalConstraints\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.RequireOnLeft","page":"HerbConstraints.jl","title":"HerbConstraints.RequireOnLeft","text":"Rules have to be used in the specified order. That is, rule at index K can only be used if rules at indices [1...K-1] are used in the left subtree of the current expression\n\n\n\n\n\n","category":"type"},{"location":"HerbConstraints/#HerbConstraints.@csgrammar_annotated-Tuple{Any}","page":"HerbConstraints.jl","title":"HerbConstraints.@csgrammar_annotated","text":"@csgrammar_annotated Define an annotated grammar and return it as a ContextSensitiveGrammar. Allows for adding optional annotations per rule. As well as that, allows for adding optional labels per rule, which can be referenced in annotations. Syntax is backwards-compatible with @csgrammar. Examples:\n\ng₁ = @csgrammar_annotated begin\n Element = 1\n Element = x\n Element = Element + Element := commutative\n Element = Element * Element := (commutative, transitive)\nend\n\ng₁ = @csgrammar_annotated begin\n Element = 1\n Element = x\n Element = Element + Element := forbidden_path([3, 1])\n Element = Element * Element := (commutative, transitive)\nend\n\ng₁ = @csgrammar_annotated begin\n one:: Element = 1\n variable:: Element = x\n addition:: Element = Element + Element := (\n commutative,\n transitive,\n forbidden_path([:addition, :one]) || forbidden_path([:one, :variable])\n )\n multiplication:: Element = Element * Element := (commutative, transitive)\nend\n\n\n\n\n\n","category":"macro"},{"location":"HerbConstraints/#Base.show-Tuple{IO, MatchNode}","page":"HerbConstraints.jl","title":"Base.show","text":"Base.show(io::IO, node::MatchNode; separator=\",\", last_child::Bool=true)\n\nPrints a found MatchNode given an and the respective children to IO. \n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#Base.show-Tuple{IO, MatchVar}","page":"HerbConstraints.jl","title":"Base.show","text":"Base.show(io::IO, node::MatchVar; separator=\",\", last_child::Bool=true)\n\nPrints a matching variable assignment described by MatchVar to IO.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(expr::Expr, pattern::MatchNode, grammar::AbstractGrammar, j=0)\n\nInternal function for matchnode2expr, recursively iterating over a matched pattern and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr-2","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(typ::Symbol, pattern::MatchNode, grammar::AbstractGrammar, j=0)\n\nInternal function for matchnode2expr, returning the matched translated symbol. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr-3","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(typ::Symbol, pattern::MatchVar, grammar::AbstractGrammar, j=0)\n\nInternal function for matchnode2expr. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression, i.e. the variable name and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._matchnode2expr-4","page":"HerbConstraints.jl","title":"HerbConstraints._matchnode2expr","text":"_matchnode2expr(expr::Expr, pattern::MatchVar, grammar::AbstractGrammar, j=0)\n\nInternal function for matchnode2expr, recursively iterating over a matched variable and converting it to an expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression and the current child index.\n\n\n\n\n\n","category":"function"},{"location":"HerbConstraints/#HerbConstraints._pattern_match-Tuple{RuleNode, MatchNode, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match","text":"_pattern_match(rn::RuleNode, mn::MatchNode, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}\n\nTries to match RuleNode rn with MatchNode mn. Modifies the variable assignment dictionary vars. Returns nothing if the match is successful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match-Tuple{RuleNode, MatchVar, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match","text":"_pattern_match(rn::RuleNode, mv::MatchVar, vars::Dict{Symbol, AbstractRuleNode})::Union{Nothing, MatchFail}\n\nMatching RuleNode rn with MatchVar mv. If the variable is already assigned, the rulenode is matched with the specific variable value. Returns nothing if the match is succesful. If the match is unsuccessful, it returns whether it is a softfail or hardfail (see MatchFail docstring)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{Hole, MatchNode, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(::Hole, mn::MatchNode, hole_location::Vector{Int}, ::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nMatches the Hole with the given MatchNode. \n\nTODO check this behaviour?\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{Hole, MatchVar, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(::Hole, mn::MatchNode, hole_location::Vector{Int}, ::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nMatches the Hole with the given MatchVar, similar to _pattern_match_with_hole.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{RuleNode, MatchNode, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(rn::RuleNode, mn::MatchNode, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nTries to match RuleNode rn with MatchNode mn and fill in the domain of the hole at hole_location. Returns if match is successful either:\n\nThe id for the node which fills the hole\nA symbol for the variable that fills the hole\nA tuple containing:\nThe variable that matched (the subtree containing) the hole\nThe location of the hole in this subtree\n\nIf the match is unsuccessful, it returns:\n\nhardfail if there are no holes that can be filled in such a way that the match will become succesful\nsoftfail if the match could become successful if the holes are filled in a certain way\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._pattern_match_with_hole-Tuple{RuleNode, MatchVar, Vector{Int64}, Dict{Symbol, AbstractRuleNode}}","page":"HerbConstraints.jl","title":"HerbConstraints._pattern_match_with_hole","text":"_pattern_match_with_hole(rn::RuleNode, mv::MatchVar, hole_location::Vector{Int}, vars::Dict{Symbol, AbstractRuleNode})::Union{Int, Symbol, MatchFail, Tuple{Symbol, Vector{Int}}}\n\nTries to match RuleNode rn with MatchVar mv and fill in the domain of the hole at hole_location. If the variable name is already assigned in vars, the rulenode is matched with the hole. Otherwise the variable and the hole location are returned.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._rulenode_compare-Tuple{RuleNode, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints._rulenode_compare","text":"Returns -1 if rn₁ < rn₂\nReturns 0 if rn₁ == rn₂ \nReturns 1 if rn₁ > rn₂\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints._rulenode_match_with_hole-Tuple{RuleNode, RuleNode, Vector{Int64}}","page":"HerbConstraints.jl","title":"HerbConstraints._rulenode_match_with_hole","text":"_rulenode_match_with_hole(rn₁::RuleNode, rn₂::RuleNode, hole_location::Vector{Int})::Union{Int, MatchFail}\n\nMatches two rulenodes. Returns how to fill in the hole in rn₁ to make it match rn₂ if:\n\nrn₁ has a single hole at the provided location\nrn₂ doesn't have any holes\nrn₁ matches rn₂ apart from the single hole location.\n\nIf the match fails, it returns whether it is a softfail or a hardfail (see MatchFail docstring)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.addparent!-Tuple{GrammarContext, Int64}","page":"HerbConstraints.jl","title":"HerbConstraints.addparent!","text":"addparent!(context::GrammarContext, parent::Int)\n\nAdds a parent to the context. The parent is defined by the grammar rule id.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.annotation2constraint-Tuple{Any, Int64, Vector{String}}","page":"HerbConstraints.jl","title":"HerbConstraints.annotation2constraint","text":"Converts an annotation to a constraint. commutative: creates an Ordered constraint transitive: creates an (incorrect) Forbidden constraint forbidden_path(path::Vector{Union{Symbol, Int}}): creates a ForbiddenPath constraint with the original rule included ... || ...: creates a OneOf constraint (also works with ... || ... || ... et cetera, though not very performant)\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{ComesAfter, AbstractGrammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{Forbidden, AbstractGrammar, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"check_tree(c::Forbidden, g::AbstractGrammar, tree::RuleNode)::Bool\n\nChecks if the given AbstractRuleNode tree abides the Forbidden constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{ForbiddenPath, AbstractGrammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{HerbConstraints.Condition, AbstractGrammar, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{OneOf, AbstractGrammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{Ordered, AbstractGrammar, RuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"check_tree(c::Ordered, g::AbstractGrammar, tree::RuleNode)::Bool\n\nChecks if the given AbstractRuleNode tree abides the Ordered constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.check_tree-Tuple{RequireOnLeft, AbstractGrammar, AbstractRuleNode}","page":"HerbConstraints.jl","title":"HerbConstraints.check_tree","text":"Checks if the given tree abides the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.copy_and_insert-Tuple{GrammarContext, Int64}","page":"HerbConstraints.jl","title":"HerbConstraints.copy_and_insert","text":"copy_and_insert(old_context::GrammarContext, parent::Int)\n\nCopies the given context and insert the parent in the node location.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.make_smaller_or_equal-Tuple{RuleNode, RuleNode, Vector{Int64}, Vector{Int64}}","page":"HerbConstraints.jl","title":"HerbConstraints.make_smaller_or_equal","text":"Filters the domain of the hole at hole_location in rn₁ to make rn₁ be ordered before rn₂. Returns the filtered domain, and a boolean indicating if this constraint can be deleted.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.matchnode2expr-Tuple{MatchNode, AbstractGrammar}","page":"HerbConstraints.jl","title":"HerbConstraints.matchnode2expr","text":"matchnode2expr(pattern::MatchNode, grammar::AbstractGrammar)\n\nConverts a MatchNode tree into a Julia expression. This is primarily useful for pretty-printing a pattern. Returns the corresponding expression.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.matchnode2expr-Tuple{MatchVar, AbstractGrammar}","page":"HerbConstraints.jl","title":"HerbConstraints.matchnode2expr","text":"matchnode2expr(pattern::MatchVar, grammar::AbstractGrammar)\n\nConverts a MatchVar into an expression by returning the variable directly. This is primarily useful for pretty-printing a pattern.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{Forbidden, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"propagate(c::Forbidden, g::AbstractGrammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}\n\nPropagates the Forbidden constraint. It removes the rules from the domain that would complete the forbidden tree.\n\nwarning: Warning\nThe Forbidden constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Forbidden can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{ForbiddenPath, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the ForbiddenPath constraint. It removes the elements from the domain that would complete the forbidden sequence.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{HerbConstraints.LocalOneOf, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the LocalOneOf constraint. It enforces that at least one of its given constraints hold.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{LocalCondition, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"propagate(c::LocalCondition, ::AbstractGrammar, context::GrammarContext, domain::Vector{Int}, filled_hole::Union{HoleReference, Nothing})\n\nPropagates the LocalCondition constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{LocalForbidden, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the LocalForbidden constraint. It removes rules from the domain that would make the RuleNode at the given path match the pattern defined by the MatchNode.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{LocalOrdered, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the LocalOrdered constraint. It removes rules from the domain that would violate the order of variables as defined in the constraint.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{OneOf, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the OneOf constraint. It enforces that at least one of its given constraints hold.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{Ordered, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"propagate(c::Ordered, g::AbstractGrammar, context::GrammarContext, domain::Vector{Int})::Tuple{Vector{Int}, Vector{LocalConstraint}}\n\nPropagates the Ordered constraint. Any rule that violates the order as defined by the contraint is removed from the domain.\n\nwarning: Warning\nThe Ordered constraint makes use of LocalConstraints to make sure that constraints are also enforced in the future when the context of a Hole changes. Therefore, Ordered can only be used in implementations that keep track of the LocalConstraints and propagate them at the right moments.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#HerbConstraints.propagate-Tuple{RequireOnLeft, AbstractGrammar, GrammarContext, Vector{Int64}, Union{Nothing, HoleReference}}","page":"HerbConstraints.jl","title":"HerbConstraints.propagate","text":"Propagates the RequireOnLeft constraint. It removes every element from the domain that does not have a necessary predecessor in the left subtree.\n\n\n\n\n\n","category":"method"},{"location":"HerbConstraints/#Index","page":"HerbConstraints.jl","title":"Index","text":"","category":"section"},{"location":"HerbConstraints/","page":"HerbConstraints.jl","title":"HerbConstraints.jl","text":"","category":"page"},{"location":"tutorials/advanced_search/#Getting-started","page":"Advanced Search Procedures","title":"Getting started","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"You can either paste this code into the Julia REPL or run it using the advanced_search.ipynb notebook. Alternatively you can copy the code into a file like get_started.jl, followed by running julia get_started.jl.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"To start, we import the necessary packages.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"using HerbGrammar, HerbData, HerbSearch, HerbInterpret","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We start with the same simple grammar from the main file get_started.md.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g = @cfgrammar begin\n Number = |(1:2)\n Number = x\n Number = Number + Number\n Number = Number * Number\nend","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We use a simple problem.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":" problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])","category":"page"},{"location":"tutorials/advanced_search/#Parameters","page":"Advanced Search Procedures","title":"Parameters","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We can use a search strategy, where we can specify different parameters. For example, by setting the max_depth, we limit the depth of the search. In the next example, we can see the effect of the depth on the number of allocations considered. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"solution = @time search(g, problem, :Number, max_depth=3)\n>>> 0.003284 seconds (50.08 k allocations: 2.504 MiB)\nprintln(solution)\n>>> (x + 1) + x\n\nsolution = @time search(g, problem, :Number, max_depth=6)\n>>> 0.005696 seconds (115.28 k allocations: 5.910 MiB)\nprintln(solution)\n>>> (1 + x) + x","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Another parameter to use is max_enumerations, which limits the number of programs that can be tested at evaluation. We can see the number of enumerations necessary to solve a simple problem in the next example.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"for i in range(1, 50)\n println(i, \" enumerations\")\n solution = @time search(g, problem, :Number, max_enumerations=i)\n println(solution)\nend\n\n>>> ....\n>>> 23 enums: nothing\n>>> 0.010223 seconds (117.01 k allocations: 5.935 MiB, 44.23% gc time)\n>>> 24 enums: (1 + x) + x\n>>> 0.005305 seconds (117.01 k allocations: 5.935 MiB)\n>>> 25 enums: (1 + x) + x\n>>> 0.005381 seconds (117.01 k allocations: 5.935 MiB)\n>>> ...","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We see that only when i >= 24, there is a result. After that, increasing i does not have any effect on the number of allocations. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"A final parameter we consider here is allow_evaluation_errors, which is false by default. When this is set to true, the program will still run even when an exception is thrown during evaluation. To see the effect of this, we create a new grammar. We can also retrieve the error together with the solution from the search method.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g = @cfgrammar begin\n Number = 1\n List = []\n Index = List[Number]\nend\n\nproblem = Problem([IOExample(Dict(), x) for x ∈ 1:5])\nsolution = search(g, problem, :Index, max_depth=2, allow_evaluation_errors=true)\nprintln(solution)\n>>> nothing","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"There is also another search method called search_best which returns both the solution and the possible error. The method returns the best program found so far. In this case, we can also see the error:","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"solution, error = search_best(g, problem, :Index, max_depth=2, allow_evaluation_errors=true)\nprintln(solution)\n>>> nothing\nprintln(error)\n>>> 9223372036854775807 # or: typemax(Int)","category":"page"},{"location":"tutorials/advanced_search/#Search-methods","page":"Advanced Search Procedures","title":"Search methods","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We now show examples of using different search procedures.","category":"page"},{"location":"tutorials/advanced_search/#Breadth-First-Search","page":"Advanced Search Procedures","title":"Breadth-First Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The breadth-first search will first enumerate all possible programs at the same depth before considering programs with a depth of one more. A tree of the grammar is returned with programs ordered in increasing sizes. We can first collect the programs that have a max-depth of 2 and a max_size of infinite (integer maximum value), where the starting symbol is of type Real. This function uses a default heuristic 'left-most first', such that the left-most child in the tree is always explored first. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g1 = @cfgrammar begin\n Real = 1 | 2\n Real = Real * Real\nend\nprograms = collect(get_bfs_enumerator(g1, 2, typemax(Int), :Real))","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We can test that this function returns all and only the correct functions. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"answer_programs = [\n RuleNode(1),\n RuleNode(2),\n RuleNode(3, [RuleNode(1), RuleNode(1)]),\n RuleNode(3, [RuleNode(1), RuleNode(2)]),\n RuleNode(3, [RuleNode(2), RuleNode(1)]),\n RuleNode(3, [RuleNode(2), RuleNode(2)])\n]\n\nprintln(all(p ∈ programs for p ∈ answer_programs))\n>>> true","category":"page"},{"location":"tutorials/advanced_search/#Depth-First-Search","page":"Advanced Search Procedures","title":"Depth-First Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"In depth-first search, we first explore a certain branch of the search tree till the max_depth or a correct program is reached before we consider the next branch. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g1 = @cfgrammar begin\nReal = 1 | 2\nReal = Real * Real\nend\nprograms = collect(get_dfs_enumerator(g1, 2, typemax(Int), :Real))\nprintln(programs)\n>>> RuleNode[1,, 3{1,1}, 3{1,2}, 3{2,1}, 3{2,2}, 2,]","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"get_dfs_enumerator also has a default left-most heuristic and we consider what the difference is in output. ","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"g1 = @cfgrammar begin\n Real = 1 | 2\n Real = Real * Real\nend\nprograms = collect(get_dfs_enumerator(g1, 2, typemax(Int), :Real, heuristic_rightmost))\nprintln(programs)\n>>> RuleNode[1,, 3{1,1}, 3{2,1}, 3{1,2}, 3{2,2}, 2,]","category":"page"},{"location":"tutorials/advanced_search/#Stochastic-search","page":"Advanced Search Procedures","title":"Stochastic search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"For the examples below, we use this grammar and helper function.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"grammar = @csgrammar begin\n X = |(1:5)\n X = X * X\n X = X + X\n X = X - X\n X = x\nend\nfunction create_problem(f, range=20)\n examples = [IOExample(Dict(:x => x), f(x)) for x ∈ 1:range]\n return Problem(examples), examples\nend","category":"page"},{"location":"tutorials/advanced_search/#Metropolis-Hastings","page":"Advanced Search Procedures","title":"Metropolis-Hastings","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"One of the stochastic search methods that is implemented is Metropolis-Hastings (MH), which samples from a distribution of programs based on the grammar. For more information on MH, see for example this webpage.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The below example uses a simple arithmetic example. As the search method is stochastic, different programs may be returned, as shown below.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> x * x + 4\")\nproblem, examples = create_problem(eval(e))\nenumerator = get_mh_enumerator(examples, mean_squared_error)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=3)\n\n>>> (:(x * x - (1 - 5)), 0)\n>>> (:(4 + x * x), 0)\n>>> (:(x * x + 4), 0)","category":"page"},{"location":"tutorials/advanced_search/#Very-Large-Scale-Neighbourhood-Search","page":"Advanced Search Procedures","title":"Very Large Scale Neighbourhood Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The second implemented stochastic search method is VLSN, which search for a local optimum in the neighbourhood. For more information, see this article.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Given the same grammar as before, we can try with some simple examples.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> 10\")\nmax_depth = 2\nproblem, examples = create_problem(eval(e))\nenumerator = get_vlsn_enumerator(examples, mean_squared_error, max_depth)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=max_depth)\n>>> (:(5 + 5), 0)","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> x\")\nmax_depth = 1\nproblem, examples = create_problem(eval(e))\nenumerator = get_vlsn_enumerator(examples, mean_squared_error, max_depth)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=max_depth)\n>>> (:x, 0)","category":"page"},{"location":"tutorials/advanced_search/#Simulated-Annealing","page":"Advanced Search Procedures","title":"Simulated Annealing","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"The third stochastic search method is called simulated annealing. This is another hill-climbing method to find local optima. For more information, see this page.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We try the example from earlier, but now we can additionally define the initial_temperature of the algorithm, which is 1 by default. Two possible answers to the program are given as well.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = Meta.parse(\"x -> x * x + 4\")\ninitial_temperature = 2\nproblem, examples = create_problem(eval(e))\nenumerator = get_sa_enumerator(examples, mean_squared_error, initial_temperature)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=3)\n>>> (:(4 + x * x), 0)\n>>> (:(x * x + (5 - 1)), 0)","category":"page"},{"location":"tutorials/advanced_search/#Genetic-Search","page":"Advanced Search Procedures","title":"Genetic Search","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Genetic search is a type of evolutionary algorithm, which will simulate the process of natural selection and return the 'fittest' program of the population. For more information, see here.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We show the example of finding a lambda function.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"e = x -> 3 * x * x + (x + 2)\nproblem, examples = create_problem(e)\nenumerator = get_genetic_enumerator(examples, \n initial_population_size = 10,\n mutation_probability = 0.8,\n maximum_initial_population_depth = 3,\n)\nprogram, cost = search_best(grammar, problem, :X, enumerator=enumerator, error_function=mse_error_function, max_depth=nothing, max_time=20)\n>>> (:(((((x - 5) + x) + x * x) + 1) + (((((2 + x * x) + 3) + x * x) + 1) - ((x - x) + x))), 0)\n>>> (:(x * 1 + (x * ((x + x) + x * 1) + (1 + 1) * 1)), 0)\n>>> (:((((x + x) + x) + 2) * x + ((x - x) + (2 - x))), 0)","category":"page"},{"location":"tutorials/advanced_search/#Other-functionality","page":"Advanced Search Procedures","title":"Other functionality","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Finally, we showcase two other functionalities of HerbSearch, sampling and heuristics.","category":"page"},{"location":"tutorials/advanced_search/#Sampling","page":"Advanced Search Procedures","title":"Sampling","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Sampling is implemented for the different stochastic search methods.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"We consider here a simple grammar, which gives different programs for different search depths.","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"grammar = @cfgrammar begin \n A = B | C | F\n F = G\n C = D\n D = E\nend\n\n# A->B (depth 1) or A->F->G (depth 2) or A->C->D->E (depth 3)\n\n# For depth ≤ 1 the only option is A->B\nexpression = rand(RuleNode, grammar, :A, 1)\n@assert rulenode2expr(expression, grammar) in [:B,:C,:F]\n\n# For depth ≤ 2 the two options are A->B (depth 1) and A->B->G| A->C->G | A->F->G (depth 2)\nexpression = rand(RuleNode, grammar, :A, 2)\n@assert rulenode2expr(expression,grammar) in [:B,:C,:F,:G]","category":"page"},{"location":"tutorials/advanced_search/#Heuristics","page":"Advanced Search Procedures","title":"Heuristics","text":"","category":"section"},{"location":"tutorials/advanced_search/#Examples-with-larger-domains-and-constraints","page":"Advanced Search Procedures","title":"Examples with larger domains and constraints","text":"","category":"section"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"Here, we showcase a few examples using a more complicated grammar and a few types of constraints","category":"page"},{"location":"tutorials/advanced_search/","page":"Advanced Search Procedures","title":"Advanced Search Procedures","text":"# Expects to return a program equivalent to 1 + (1 - x) = 2 - x\n\ng₁ = @csgrammar begin\n Element = |(1 : 3) # 1 - 3\n Element = Element + Element # 4\n Element = 1 - Element # 5\n Element = x # 6\nend\n\naddconstraint!(g₁, ComesAfter(6, [5]))\n\nexamples = [\n IOExample(Dict(:x => 0), 2),\n IOExample(Dict(:x => 1), 1),\n IOExample(Dict(:x => 2), 0)\n]\nproblem = Problem(examples)\nsolution = search(g₁, problem, :Element, max_depth=3)\n\n@assert test_with_input(SymbolTable(g₁), solution, Dict(:x => -2)) == 4\n\n# Expects to return a program equivalent to 4 + x * (x + 3 + 3) = x^2 + 6x + 4\n\ng₂ = @csgrammar begin\n Element = Element + Element + Element # 1\n Element = Element + Element * Element # 2\n Element = x # 3\n Element = |(3 : 5) # 4\nend\n\n# Restrict .. + x * x\naddconstraint!(g₂, Forbidden(MatchNode(2, [MatchVar(:x), MatchNode(3), MatchNode(3)])))\n# Restrict 4 and 5 in lower level\naddconstraint!(g₂, ForbiddenPath([2, 1, 5]))\naddconstraint!(g₂, ForbiddenPath([2, 1, 6]))\n\nexamples = [\n IOExample(Dict(:x => 1), 11)\n IOExample(Dict(:x => 2), 20)\n IOExample(Dict(:x => -1), -1)\n]\nproblem = Problem(examples)\nsolution = search(g₂, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₂), solution, Dict(:x => 0)) == 4\n\n# Expects to return a program equivalent to (1 - (((1 - x) - 1) - 1)) - 1 = x + 1\n\ng₃ = @csgrammar begin\n Element = |(1 : 20) # 1 - 20\n Element = Element - 1 # 21\n Element = 1 - Element # 22\n Element = x # 23\nend\n\naddconstraint!(g₃, ComesAfter(23, [22, 21]))\naddconstraint!(g₃, ComesAfter(22, [21]))\n\nexamples = [\n IOExample(Dict(:x => 1), 2)\n IOExample(Dict(:x => 10), 11)\n]\nproblem = Problem(examples)\nsolution = search(g₃, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₃), solution, Dict(:x => 0)) == 1\n@assert test_with_input(SymbolTable(g₃), solution, Dict(:x => 100)) == 101\n\n# Expects to return a program equivalent to 18 + 4x\n\ng₄ = @csgrammar begin\n Element = |(0 : 20) # 1 - 20\n Element = Element + Element + Element # 21\n Element = Element + Element * Element # 22\n Element = x # 23\nend\n\n# Enforce ordering on + +\naddconstraint!(g₄, Ordered(\n MatchNode(21, [MatchVar(:x), MatchVar(:y), MatchVar(:z)]),\n [:x, :y, :z]\n))\n\nexamples = [\n IOExample(Dict(:x => 1), 22),\n IOExample(Dict(:x => 0), 18),\n IOExample(Dict(:x => -1), 14)\n]\nproblem = Problem(examples)\nsolution = search(g₄, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₄), solution, Dict(:x => 100)) == 418\n\n# Expects to return a program equivalent to (x == 2) ? 1 : (x + 2)\n\ng₅ = @csgrammar begin\n Element = Number # 1\n Element = Bool # 2\n\n Number = |(1 : 3) # 3-5\n \n Number = Number + Number # 6\n Bool = Number ≡ Number # 7\n Number = x # 8\n \n Number = Bool ? Number : Number # 9\n Bool = Bool ? Bool : Bool # 10\nend\n\n# Forbid ? = ?\naddconstraint!(g₅, Forbidden(MatchNode(7, [MatchVar(:x), MatchVar(:x)])))\n# Order =\naddconstraint!(g₅, Ordered(MatchNode(7, [MatchVar(:x), MatchVar(:y)]), [:x, :y]))\n# Order +\naddconstraint!(g₅, Ordered(MatchNode(6, [MatchVar(:x), MatchVar(:y)]), [:x, :y]))\n\nexamples = [\n IOExample(Dict(:x => 0), 2)\n IOExample(Dict(:x => 1), 3)\n IOExample(Dict(:x => 2), 1)\n]\nproblem = Problem(examples)\nsolution = search(g₅, problem, :Element)\n\n@assert test_with_input(SymbolTable(g₅), solution, Dict(:x => 3)) == 5","category":"page"},{"location":"HerbInterpret/#HerbInterpret_docs","page":"HerbInterpret.jl","title":"HerbInterpret.jl Documentation","text":"","category":"section"},{"location":"HerbInterpret/","page":"HerbInterpret.jl","title":"HerbInterpret.jl","text":"CurrentModule=HerbInterpret","category":"page"},{"location":"HerbInterpret/","page":"HerbInterpret.jl","title":"HerbInterpret.jl","text":"Modules = [HerbInterpret]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbInterpret/#HerbInterpret.evaluate_program-Tuple{RuleNode, Vector{<:HerbSpecification.IOExample}, AbstractGrammar, Function}","page":"HerbInterpret.jl","title":"HerbInterpret.evaluate_program","text":"evaluate_program(program::RuleNode, examples::Vector{<:IOExample}, grammar::AbstractGrammar, evaluation_function::Function)\n\nRuns a program on the examples and returns tuples of actual desired output and the program's output\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.execute_on_input-Union{Tuple{T}, Tuple{AbstractGrammar, RuleNode, Dict{Symbol, T}}} where T","page":"HerbInterpret.jl","title":"HerbInterpret.execute_on_input","text":"execute_on_input(grammar::AbstractGrammar, program::RuleNode, input::Dict{Symbol, T})::Any where T\n\nConverts a RuleNode program into an expression using a given grammar, then evaluates this expression with a single input dictionary input and a symbol table derived from the grammar using execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T}).\n\nArguments\n\ngrammar::AbstractGrammar: A grammar object used to convert the RuleNode into an executable expression.\nprogram::RuleNode: The program, represented as a RuleNode, to be converted and evaluated.\ninput::Dict{Symbol, T}: A dictionary providing input values for symbols used in the generated expression.\n\nReturns\n\nAny: The result of evaluating the generated expression with the given input dictionary.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.execute_on_input-Union{Tuple{T}, Tuple{AbstractGrammar, RuleNode, Vector{T}}} where T<:(Dict{Symbol})","page":"HerbInterpret.jl","title":"HerbInterpret.execute_on_input","text":"execute_on_input(grammar::AbstractGrammar, program::RuleNode, input::Vector{T})::Vector{Any} where T <: Dict{Symbol, <:Any}\n\nConverts a RuleNode program into an expression using a given grammar, then evaluates this expression for each input dictionary in a vector input and a symbol table derived from the grammar using execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T}).\n\nArguments\n\ngrammar::AbstractGrammar: A grammar object used to convert the RuleNode into an executable expression.\nprogram::RuleNode: The program, represented as a RuleNode, to be converted and evaluated.\ninput::Vector{T}: A vector of dictionaries, each providing input values for symbols used in the generated expression.\n\nReturns\n\nVector{Any}: A vector containing the results of evaluating the generated expression for each input dictionary.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.execute_on_input-Union{Tuple{T}, Tuple{Dict{Symbol, Any}, Any, Dict{Symbol, T}}} where T","page":"HerbInterpret.jl","title":"HerbInterpret.execute_on_input","text":"execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T})::Any where T\n\nEvaluates an expression expr within the context of a symbol table tab and a single input dictionary input. The input dictionary keys should match the symbols used in the expression, and their values are used during the expression's evaluation.\n\nArguments\n\ntab::SymbolTable: A symbol table containing predefined symbols and their associated values or functions.\nexpr::Any: The expression to be evaluated. Can be any Julia expression that is valid within the context of the provided symbol table and input.\ninput::Dict{Symbol, T}: A dictionary where each key is a symbol used in the expression, and the value is the corresponding value to be used in the expression's evaluation. The type T can be any type.\n\nReturns\n\nAny: The result of evaluating the expression with the given symbol table and input dictionary.\n\nwarning: Warning\nThis function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.execute_on_input-Union{Tuple{T}, Tuple{Dict{Symbol, Any}, Any, Vector{T}}} where T<:(Dict{Symbol})","page":"HerbInterpret.jl","title":"HerbInterpret.execute_on_input","text":"execute_on_input(tab::SymbolTable, expr::Any, input::Vector{T})::Vector{<:Any} where T <: Dict{Symbol, <:Any}\n\nWrapper around execute_on_input(tab::SymbolTable, expr::Any, input::Dict{Symbol, T}) to execute all inputs given as an array.\n\nArguments\n\ntab::SymbolTable: A symbol table containing predefined symbols and their associated values or functions.\nexpr::Any: The expression to be evaluated for each input dictionary.\ninputs::Vector{T}: A vector of dictionaries, each serving as an individual set of inputs for the expression's evaluation.\n\nReturns\n\nVector{<:Any}: A vector containing the results of evaluating the expression for each input dictionary.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.interpret-Tuple{Dict{Symbol, Any}, Any}","page":"HerbInterpret.jl","title":"HerbInterpret.interpret","text":"interpret(tab::SymbolTable, ex::Expr)\n\nEvaluates an expression without compiling it. Uses AST and symbol lookups. Only supports :call and :(=) expressions at the moment.\n\nExample usage:\n\ntab = SymbolTable(:f => f, :x => x)\nex = :(f(x))\ninterpret(tab, ex)\n\nWARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.test_all_examples-Tuple{Dict{Symbol, Any}, Any, Vector{HerbSpecification.IOExample}}","page":"HerbInterpret.jl","title":"HerbInterpret.test_all_examples","text":"test_all_examples(tab::SymbolTable, expr::Any, examples::Vector{IOExample})::Vector{Bool}\n\nwarning: Warning\nThis function is deprecated. Please use execute_on_input instead.\n\nRuns the interpreter on all examples with the given input table and expression. The symbol table defines everything (functions, symbols) that are not input variables to the program to be synthesised. Returns a list of true/false values indicating if the expression satisfies the corresponding example. WARNING: This function throws exceptions that are caused in the given expression. These exceptions have to be handled by the caller of this function.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#HerbInterpret.test_examples-Tuple{Dict{Symbol, Any}, Any, Vector{HerbSpecification.IOExample}}","page":"HerbInterpret.jl","title":"HerbInterpret.test_examples","text":"test_examples(tab::SymbolTable, expr::Any, examples::Vector{IOExample})::Bool\n\nwarning: Warning\nThis function is deprecated. Please use execute_on_input instead.\n\nEvaluates all examples and returns true iff all examples pass. Shortcircuits as soon as an example is found for which the program doesn't work. Returns false if one of the examples produces an error.\n\n\n\n\n\n","category":"method"},{"location":"HerbInterpret/#Index","page":"HerbInterpret.jl","title":"Index","text":"","category":"section"},{"location":"HerbInterpret/","page":"HerbInterpret.jl","title":"HerbInterpret.jl","text":"","category":"page"},{"location":"tutorials/getting_started_with_herb/#Search","page":"A more verbose getting started with Herb.jl","title":"Search","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"This notebook describes how you can search a program space as defined by a grammar. Specifically, we will look at example-based search, where the goal is to find a program that is able to transform the inputs of every example to the corresponding output.","category":"page"},{"location":"tutorials/getting_started_with_herb/#Setup","page":"A more verbose getting started with Herb.jl","title":"Setup","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"First, we start with the setup. We need to access to all the function in the Herb.jl framework.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"using Herb","category":"page"},{"location":"tutorials/getting_started_with_herb/#Defining-the-program-space","page":"A more verbose getting started with Herb.jl","title":"Defining the program space","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Next, we start by creating a grammar. We define a context-free grammar which is just a simple set of production rules for defining combinations of terminal symbols (in our case real numbers). ","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Contrary, we could define a context-sensitive grammar, when the production rules only hold in a certain context. However, for more information on this, please see example2_defining_grammars.ipynb.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"For now, we specify a simple grammar for dealing with integers and explain all the rules individually:","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"First, we specify our interval [0:9] on real numbers and also constrain them to be integer.\nThen, we can also use the variable x to hold an integer.\nThe third rule determines we can add two integers.\nThe fourth rule determines we can subtract an integer from another.\nFinally, we also allow the multiplication of two integers.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"If you run this cell, you can see all the rules rolled out.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"g = Herb.HerbGrammar.@cfgrammar begin\n Real = |(0:9)\n Real = x\n Real = Real + Real\n Real = Real - Real\n Real = Real * Real\nend","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"1: Real = 0\n2: Real = 1\n3: Real = 2\n4: Real = 3\n5: Real = 4\n6: Real = 5\n7: Real = 6\n8: Real = 7\n9: Real = 8\n10: Real = 9\n11: Real = x\n12: Real = Real + Real\n13: Real = Real - Real\n14: Real = Real * Real","category":"page"},{"location":"tutorials/getting_started_with_herb/#Defining-the-problem","page":"A more verbose getting started with Herb.jl","title":"Defining the problem","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"As mentioned before, we are looking at example-based search. This means that the problem is defined by a set of input-output examples. A single example hence consists of an input and an output. The input is defined as a dictionary, with a value assigned to each variable in the grammar. It is important to write the variable name as a Symbol instead of a string. A Symbol in Julia is written with a colon prefix, i.e. :x. The output of the input-output example is just a single value for this specific grammar, but could possibly relate to e.g. arrays of values, too.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In the cell below we automatically generate some examples for x assigning values 1-5.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"# Create input-output examples\nexamples = [Herb.HerbData.IOExample(Dict(:x => x), 3x+5) for x ∈ 1:5]","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"5-element Vector{Main.Herb.HerbData.IOExample}:\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 1), 8)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 2), 11)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 3), 14)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 4), 17)\n Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 5), 20)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Now that we have some input-output examples, we can define the problem. Next to the examples, a problem also contains a name meant to link to the file path, which can be used to keep track of current examples. For now, this is irrelevant, and you can give the program any name you like.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"problem = Herb.HerbData.Problem(examples, \"example\")","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Main.Herb.HerbData.Problem(Main.Herb.HerbData.Example[Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 1), 8), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 2), 11), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 3), 14), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 4), 17), Main.Herb.HerbData.IOExample(Dict{Symbol, Any}(:x => 5), 20)], \"example\")","category":"page"},{"location":"tutorials/getting_started_with_herb/#Searching","page":"A more verbose getting started with Herb.jl","title":"Searching","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Now that we have defined the search space and the goal of the search, we can start the search. ","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Of course, our problem is underdefined as there might be multiple programs that satisfy our examples. Let us consider the case where we also have a ternary if-then-else operator and standard boolean operators in our grammar: we could synthesize the program x ≤ 5 ? 3x+5 : 0. This program satisfies all our examples, but we don't expect it to generalize very well.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In general, we assume that a smaller program is more general than a larger program. Therefore, we search for the smallest program in our grammar that satisfies our examples. This can be done using a breadth-first search over the program/search space.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"This search is very basic; it makes use of an enumeration technique, where we enumerate programs one-by-one until we find a program that matches our examples. The search procedure has a built-in default evaluator to verify the candidate programs with the given input. The search procedure also has a built-in search procedure using breadth-first search. ","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"So, we only need to give our grammar and the problem to our search procedure, along with a starting Symbol, in our case a Real.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Herb.HerbSearch.search(g, problem, :Real)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":":(x * 3 + 5)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"As you can see, the search procedure found the correct program!","category":"page"},{"location":"tutorials/getting_started_with_herb/#Defining-the-search-procedure","page":"A more verbose getting started with Herb.jl","title":"Defining the search procedure","text":"","category":"section"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In the previous case, we used the built-ins of the search procedure. However, we can also give a custom enumerator to the search procedure and define a few more values.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"We first define a new problem to test with, we are looking for the programs that can compute the value167. We immediately pass the examples to the problem and then set up the new search.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"Search is done by passing the grammar, the problem and the starting point like before. We now also specify the enumeration function to be used, and now we use depth-first search. Then, we give the maximum depth of the programs we want to search for (3), the maximum number of nodes in the Abstract Syntax Tree that exists during search (10), and the maximum time in seconds allowed for the search.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"problem = Herb.HerbData.Problem([Herb.HerbData.IOExample(Dict(:x => x), 168) for x ∈ 1:5], \"example2\")\nexpr = Herb.HerbSearch.search(g, problem, :Real, enumerator=Herb.HerbSearch.get_dfs_enumerator, max_depth=4, max_size=30, max_time=180)\nprint(expr)","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"nothing","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"We see that our synthesizer can find a program to construct the value 168, though a fun experiment would be trying to get the value 167, what do you think would happen? If you want you can try below.","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"In any case, this concludes our first introduction to the Herb.jl program synthesis framework. You can see more examples in this repository, or explore yourself. Enjoy!","category":"page"},{"location":"tutorials/getting_started_with_herb/","page":"A more verbose getting started with Herb.jl","title":"A more verbose getting started with Herb.jl","text":"problem = Herb.HerbData.Problem([Herb.HerbData.IOExample(Dict(:x => x), 167) for x ∈ 1:5], \"example2\")\nexpr = Herb.HerbSearch.search(g, problem, :Real)\nprintln(expr)","category":"page"},{"location":"get_started/#Getting-Started","page":"Getting Started","title":"Getting Started","text":"","category":"section"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"You can either paste this code into the Julia REPL or into a seperate file, e.g. get_started.jl followed by julia get_started.jl.","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"To begin, we need to import all needed packages using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"using HerbGrammar, HerbSpecification, HerbSearch, HerbInterpret","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"To define a program synthesis problem, we need a grammar and specification. ","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"First, a grammar can be constructed using the @cfgrammar macro included in HerbGrammar. Alternatively, we can use the @csgrammar macro, which will be shown later on in the tutorial when we use constraints. ","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Here, we describe a simple integer arithmetic example, that can add and multiply an input variable x or the integers 1,2, using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"g = @cfgrammar begin\n Number = |(1:2)\n Number = x\n Number = Number + Number\n Number = Number * Number\nend","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Second, the problem specification can be provided using e.g. input/output examples using HerbData. Inputs are provided as a Dict assigning values to variables, and outputs as arbitrary values. The problem itself is then a list of IOExamples using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"problem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"The problem is given now, let us search for a solution with HerbSearch. For now we will just use the default parameters searching for a satisfying program over the grammar, given the problem and a starting symbol using","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"iterator = BFSIterator(g₁, :Number, max_depth=5)\nsolution, flag = synth(problem, iterator)\nprintln(solution)","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"There are various ways to adapt the search technique to your needs. Please have a look at the search documentation.","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Eventually, we want to test our solution on some other inputs using HerbInterpret. We transform our grammar g to a Julia expression with Symboltable(g), add our solution and the input, assigning the value 6 to the variable x.","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"program = rulenode2expr(solution, g) # should yield 2*6+1\n\noutput = execute_on_input(SymbolTable(g), program, Dict(:x => 6)) \nprintln(output)","category":"page"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"Just like that we tackled (almost) all modules of Herb.jl.","category":"page"},{"location":"get_started/#Where-to-go-from-here?","page":"Getting Started","title":"Where to go from here?","text":"","category":"section"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"See our other tutorials!","category":"page"},{"location":"get_started/#The-full-code-example","page":"Getting Started","title":"The full code example","text":"","category":"section"},{"location":"get_started/","page":"Getting Started","title":"Getting Started","text":"using HerbSearch, HerbData, HerbInterpret, HerbGrammar\n\n# define our very simple context-free grammar\n# Can add and multiply an input variable x or the integers 1,2.\ng = @cfgrammar begin\n Number = |(1:2)\n Number = x\n Number = Number + Number\n Number = Number * Number\nend\n\nproblem = Problem([IOExample(Dict(:x => x), 2x+1) for x ∈ 1:5])\niterator = BFSIterator(g₁, :Number, max_depth=5)\n\nsolution, flag = synth(problem, iterator)\nprogram = rulenode2expr(solution, g) # should yield 2*6 +1 \n\noutput = execute_on_input(SymbolTable(g), program, Dict(:x => 6)) \nprintln(output)\n","category":"page"},{"location":"HerbData/#HerbData_docs","page":"HerbCore.jl","title":"HerbData.jl Documentation","text":"","category":"section"},{"location":"HerbData/","page":"HerbCore.jl","title":"HerbCore.jl","text":"CurrentModule=HerbData","category":"page"},{"location":"HerbData/","page":"HerbCore.jl","title":"HerbCore.jl","text":"Modules = [HerbData]\nOrder = [:type, :const, :macro, :function]","category":"page"},{"location":"HerbData/#HerbData.IOExample","page":"HerbCore.jl","title":"HerbData.IOExample","text":"struct IOExample <: Example\n\nAn input-output example. input is a Dict of {Symbol,Any} where the symbol represents a variable in a program. output can be anything.\n\n\n\n\n\n","category":"type"},{"location":"HerbData/#HerbData.IOPExample","page":"HerbCore.jl","title":"HerbData.IOPExample","text":"struct IOPExample <: Example\n\nAn input-output example with an associated program. ex is an IOExample. program is a program of arbitrary form. Please note that this is a pure container, and thus does not guarantee any checks on the validity of the program.\n\n\n\n\n\n","category":"type"},{"location":"HerbData/#HerbData.Problem","page":"HerbCore.jl","title":"HerbData.Problem","text":"struct Problem\n\nProgram synthesis problem defined with a vector of Examples\n\n\n\n\n\n","category":"type"},{"location":"HerbData/#HerbData.read_IOPexamples-Tuple{AbstractString}","page":"HerbCore.jl","title":"HerbData.read_IOPexamples","text":"read_IOPexamples(filepath::AbstractString)::Vector{Tuple{IOPExample}\n\nReads serialized IO + program examples from disk after type checking.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.read_IOexamples-Tuple{AbstractString}","page":"HerbCore.jl","title":"HerbData.read_IOexamples","text":"read_IOexamples(filepath::AbstractString)::Vector{IOExample}\n\nReads serialized IO examples from disk after type checking.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.readdata-Tuple{AbstractString, Function}","page":"HerbCore.jl","title":"HerbData.readdata","text":"readdata(directory::AbstractString, lineparser::Function)::Vector{Problem}\n\nReads all files in the given directory and parses them line by line into an ExampleProblem using the given lineparser.\n\nTODO: Turn this into an iterator that doesn't load all data into memory at initialization.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.readfile-Tuple{AbstractString, Function}","page":"HerbCore.jl","title":"HerbData.readfile","text":"readfile(filepath::AbstractString, lineparser::Function)::Problem\n\nReads a file and parses every non-empty line using the line parser.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.write_IOPexamples-Tuple{AbstractString, Vector{IOPExample}}","page":"HerbCore.jl","title":"HerbData.write_IOPexamples","text":"write_IOPexamples(filepath::AbstractString, examples::Vector{Tuple{IOExample, Any}})\n\nWrites IO examples and the corresponding programs to disk by serializing them into a file using HDF5 checking for and appending the .xiop.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#HerbData.write_IOexamples-Tuple{AbstractString, Vector{IOExample}}","page":"HerbCore.jl","title":"HerbData.write_IOexamples","text":"write_IOexamples(filepath::AbstractString, examples::Vector{IOExample})\n\nWrites IO examples to disk by serializing them into a file using HDF5 checking for and appending the .xio file ending.\n\n\n\n\n\n","category":"method"},{"location":"HerbData/#Index","page":"HerbCore.jl","title":"Index","text":"","category":"section"},{"location":"HerbData/","page":"HerbCore.jl","title":"HerbCore.jl","text":"","category":"page"},{"location":"tutorials/defining_grammars/#Defining-Grammars-in-Herb.jl-using-HerbGrammar","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl using HerbGrammar","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"The program space in Herb.jl is defined using a grammar. This notebook demonstrates how such a grammar can be created. There are multiple kinds of grammars, but they can all be defined in a very similar way.","category":"page"},{"location":"tutorials/defining_grammars/#Setup","page":"Defining Grammars in Herb.jl","title":"Setup","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"using HerbGrammar, HerbConstraints","category":"page"},{"location":"tutorials/defining_grammars/#Creating-a-simple-grammar","page":"Defining Grammars in Herb.jl","title":"Creating a simple grammar","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"This cell contains a very simple arithmetic grammar. The grammar is defined using the @cfgrammar macro. This macro converts the grammar definition in the form of a Julia expression into Herb's internal grammar representation. Macro's are executed during compilation. If you want to load a grammar during execution, have a look at the HerbGrammar.expr2cfgrammar function.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₁ = HerbGrammar.@cfgrammar begin\n Int = 1\n Int = 2\n Int = 3\n Int = Int * Int\n Int = Int + Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 1\n2: Int = 2\n3: Int = 3\n4: Int = Int * Int\n5: Int = Int + Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Defining every integer one-by-one can be quite tedious. Therefore, it is also possible to use the following syntax that makes use of a Julia iterator:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₂ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int * Int\n Int = Int + Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = Int + Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"You can do the same with lists:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₃ = HerbGrammar.@cfgrammar begin\n Int = |([0, 2, 4, 6, 8])\n Int = Int * Int\n Int = Int + Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 2\n3: Int = 4\n4: Int = 6\n5: Int = 8\n6: Int = Int * Int\n7: Int = Int + Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Variables can also be added to the grammar by just using the variable name:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₄ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int * Int\n Int = Int + Int\n Int = x\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = Int + Int\n13: Int = x","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Grammars can also work with functions. After all, + and * are just infix operators for Julia's identically-named functions. You can use functions that are provided by Julia, or functions that you wrote yourself:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"f(a) = a + 1\n\ng₅ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int * Int\n Int = Int + Int\n Int = f(Int)\n Int = x\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = Int + Int\n13: Int = f(Int)\n14: Int = x","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Similarly, we can also define the operator times (x) manually.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"×(a, b) = a * b\n\ng₆ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = a\n Int = Int + Int\n Int = Int × Int\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = a\n12: Int = Int + Int\n13: Int = Int × Int","category":"page"},{"location":"tutorials/defining_grammars/#Working-with-grammars","page":"Defining Grammars in Herb.jl","title":"Working with grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"If you want to implement something using these grammars, it is useful to know about the functions that you can use to manipulate grammars and extract information. This section is not necessarily complete, but it aims to give an overview of the most important functions. ","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"It is recommended to also read up on Julia metaprogramming if you are not already familiar with that.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"One of the most important things about grammars is that each rule has an index associated with it:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₇ = HerbGrammar.@cfgrammar begin\n Int = |(0:9)\n Int = Int + Int\n Int = Int * Int\n Int = x\nend\n\ncollect(enumerate(g₇.rules))","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"13-element Vector{Tuple{Int64, Any}}:\n (1, 0)\n (2, 1)\n (3, 2)\n (4, 3)\n (5, 4)\n (6, 5)\n (7, 6)\n (8, 7)\n (9, 8)\n (10, 9)\n (11, :(Int + Int))\n (12, :(Int * Int))\n (13, :x)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"We can use this index to extract information from the grammar.","category":"page"},{"location":"tutorials/defining_grammars/#isterminal","page":"Defining Grammars in Herb.jl","title":"isterminal","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"isterminal returns true if a rule is terminal, i.e. it cannot be expanded. For example, rule 1 is terminal, but rule 11 is not, since it contains the non-terminal symbol :Int. ","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.isterminal(g₇, 1)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"true","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.isterminal(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"false","category":"page"},{"location":"tutorials/defining_grammars/#return_type","page":"Defining Grammars in Herb.jl","title":"return_type","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"This function is rather obvious; it returns the non-terminal symbol that corresponds to a certain rule. The return type for all rules in our grammar is :Int.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.return_type(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":":Int","category":"page"},{"location":"tutorials/defining_grammars/#child_types","page":"Defining Grammars in Herb.jl","title":"child_types","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"child_types returns the types of the nonterminal children of a rule in a vector. If you just want to know how many children a rule has, and not necessarily which types they have, you can use nchildren","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.child_types(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"2-element Vector{Symbol}:\n :Int\n :Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.nchildren(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"2","category":"page"},{"location":"tutorials/defining_grammars/#nonterminals","page":"Defining Grammars in Herb.jl","title":"nonterminals","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"The nonterminals function can be used to obtain a list of all nonterminals in the grammar.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.nonterminals(g₇)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1-element Vector{Symbol}:\n :Int","category":"page"},{"location":"tutorials/defining_grammars/#Adding-rules","page":"Defining Grammars in Herb.jl","title":"Adding rules","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"It is also possible to add rules to a grammar during execution. This can be done using the add_rule! function. As with most functions in Julia that end with an exclamation mark, this function modifies its argument (the grammar).","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"A rule can be provided in the same syntax as is used in the grammar definition. The rule should be of the Expr type, which is a built-in type for representing expressions. An easy way of creating Expr values in Julia is to encapsulate it in brackets and use a colon as prefix:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.add_rule!(g₇, :(Int = Int - Int))","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x\n14: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/#Removing-rules","page":"Defining Grammars in Herb.jl","title":"Removing rules","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"It is also possible to remove rules in Herb.jl, however, this is a bit more involved. As said before, rules have an index associated with them. The internal representation of programs that are defined by the grammar makes use of those indices for efficiency. Blindly removing a rule would shift the indices of other rules, and this could mean that existing programs get a different meaning or become invalid. ","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Therefore, there are two functions for removing rules:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"remove_rule! removes a rule from the grammar, but fills its place with a placeholder. Therefore, the indices stay the same, and only programs that use the removed rule become invalid.\ncleanup_removed_rules! removes all placeholders and shifts the indices of the other rules.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.remove_rule!(g₇, 11)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: nothing = nothing\n12: Int = Int * Int\n13: Int = x\n14: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.cleanup_removed_rules!(g₇)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = x\n13: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/#Context-sensitive-grammars","page":"Defining Grammars in Herb.jl","title":"Context-sensitive grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Context-sensitive grammars allow additional constraints to be added with respect to context-free grammars. The syntax for defining a context-sensitive grammar is identical to defining a context-sensitive grammar:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₈ = HerbGrammar.@csgrammar begin\n Int = |(0:9)\n Int = Int + Int\n Int = Int * Int\n Int = x\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Constraints can be added using the addconstraint! function, which takes a context-sensitive grammar and a constraint and adds the constraint to the grammar. Currently, Herb.jl only has propagators constraints. These constraints each have a corresponding propagate function that removes all options that violate that constraint from the domain. At the moment, there are three propagator constraints:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"ComesAfter(rule, predecessors): It is only possible to use rule rule when predecessors are in its path to the root.\nForbidden(sequence): Forbids the derivation specified as a path in an expression tree.\nOrdered(order): Rules have to be used in the specified order. That is, rule at index K can only be used if rules at indices [1...K-1] are used in the left subtree of the current expression.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Below, an example is given of a context-sensitive grammar with a ComesAfter constraint:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.addconstraint!(g₈, HerbConstraints.ComesAfter(1, [9]))","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1-element Vector{Main.HerbCore.Constraint}:\n Main.HerbConstraints.ComesAfter(1, [9])","category":"page"},{"location":"tutorials/defining_grammars/#Probabilistic-grammars","page":"Defining Grammars in Herb.jl","title":"Probabilistic grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Herb.jl also supports probabilistic grammars. These grammars allow the user to assign a probability to each rule in the grammar. A probabilistic grammar can be defined in a very similar way to a standard grammar, but has some slightly different syntax:","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₉ = HerbGrammar.@pcfgrammar begin\n 0.4 : Int = |(0:9)\n 0.2 : Int = Int + Int\n 0.1 : Int = Int * Int\n 0.3 : Int = x\nend\n\nfor r ∈ 1:length(g₃.rules)\n p = HerbGrammar.probability(g₈, r)\n\n println(\"$p : $r\")\nend","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"0.07692307692307693 : 1\n0.07692307692307693 : 2\n0.07692307692307693 : 3\n0.07692307692307693 : 4\n0.07692307692307693 : 5\n0.07692307692307693 : 6\n0.07692307692307693 : 7\n\n\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155\n┌ Warning: Requesting probability in a non-probabilistic grammar.\n│ Uniform distribution is assumed.\n└ @ Main.HerbGrammar d:\\GitHub\\HerbGrammar.jl\\src\\grammar_base.jl:155","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"The numbers before each rule represent the probability assigned to that rule. The total probability for each return type should add up to 1.0. If this isn't the case, Herb.jl will normalize the probabilities.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"If a single line in the grammar definition represents multiple rules, such as 0.4 : Int = |(0:9), the probability will be evenly divided over all these rules.","category":"page"},{"location":"tutorials/defining_grammars/#File-writing","page":"Defining Grammars in Herb.jl","title":"File writing","text":"","category":"section"},{"location":"tutorials/defining_grammars/#Saving-and-loading-context-free-grammars","page":"Defining Grammars in Herb.jl","title":"Saving & loading context-free grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"If you want to store a grammar on the disk, you can use the store_cfg, read_cfg and functions to store and read grammars respectively. The store_cfg grammar can also be used to store probabilistic grammars. Reading probabilistic grammars can be done using read_pcfg. The stored grammar files can also be opened using a text editor to be modified, as long as the contents of the file doesn't violate the syntax for defining grammars.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.store_cfg(\"demo.txt\", g₇)","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.read_cfg(\"demo.txt\")","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int * Int\n12: Int = x\n13: Int = Int - Int","category":"page"},{"location":"tutorials/defining_grammars/#Saving-and-loading-context-sensitive-grammars","page":"Defining Grammars in Herb.jl","title":"Saving & loading context-sensitive grammars","text":"","category":"section"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"Saving and loading context-sensitive grammars is very similar to how it is done with context-free grammars. The only difference is that an additional file is created for the constraints. The file that contains the grammars can be edited and can also be read using the reader for context-free grammars. The file that contains the constraints cannot be edited.","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"HerbGrammar.store_csg(\"demo.grammar\", \"demo.constraints\", g₈)\ng₈, g₈.constraints","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"(1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x\n, Main.HerbCore.Constraint[Main.HerbConstraints.ComesAfter(1, [9])])","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"g₉ = HerbGrammar.read_csg(\"demo.grammar\", \"demo.constraints\")\ng₉, g₉.constraints","category":"page"},{"location":"tutorials/defining_grammars/","page":"Defining Grammars in Herb.jl","title":"Defining Grammars in Herb.jl","text":"(1: Int = 0\n2: Int = 1\n3: Int = 2\n4: Int = 3\n5: Int = 4\n6: Int = 5\n7: Int = 6\n8: Int = 7\n9: Int = 8\n10: Int = 9\n11: Int = Int + Int\n12: Int = Int * Int\n13: Int = x\n, Main.HerbCore.Constraint[Main.HerbConstraints.ComesAfter(1, [9])])","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"CurrentModule=Herb","category":"page"},{"location":"#[Herb.jl](https://github.com/Herb-AI/Herb.jl)","page":"Herb.jl","title":"Herb.jl","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"A library for defining and efficiently solving program synthesis tasks in Julia.","category":"page"},{"location":"#Why-Herb.jl?","page":"Herb.jl","title":"Why Herb.jl?","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"When writing research software we almost always investigate highly specific properties or algorithms of our domain, leading to us building the tools from scratch over and over again. The very same holds for the field of program synthesis: Tools are hard to run, benchmarks are hard to get and prepare, and its hard to adapt our existing code to a novel idea.","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb.jl will take care of this for you and helps you defining, solving and extending your program synthesis problems.","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb.jl provides...","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"a unified and universal framework for program synthesis\nHerb.jl allows you to describe all sorts of program synthesis problems using context-free grammars\na number of state-of-the-art benchmarks and solvers already implemented and usable out-of-the-box","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb.jl's sub-packages provide fast and easily extendable implementations of ","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"various static and dynamic search strategies,\nlearning search strategies, sampling techniques and more,\nconstraint formulation and propagation, \neasy grammar formulation and usage,\nwide-range of usable program interpreters and languages + the possibility to use your own, and \nefficient data formulation.","category":"page"},{"location":"#Why-Julia?","page":"Herb.jl","title":"Why Julia?","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Julia is a perfect fit for program synthesis due to numerous reasons. Starting from scientific reasons like speed of execution and composability over to practical reasons like speed of writing Julia code. For a full ode on why to use Julia, please see the WhyJulia manifesto.","category":"page"},{"location":"#Sub-Modules","page":"Herb.jl","title":"Sub-Modules","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Herb's functionality is distributed among several sub-packages:","category":"page"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"HerbCore.jl: The core of Herb.jl defining core concepts to avoid circular dependencies.\nHerbGrammar.jl:\nHerbData.jl:\nHerbInterpret.jl:\nHerbSearch.jl:\nHerbConstraints.jl:","category":"page"},{"location":"#Basics","page":"Herb.jl","title":"Basics","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"Pages = [\"install.md\", \"get_started.md\", \"concepts.md\"]","category":"page"},{"location":"#Advanced-content","page":"Herb.jl","title":"Advanced content","text":"","category":"section"},{"location":"","page":"Herb.jl","title":"Herb.jl","text":"","category":"page"}] } diff --git a/dev/tutorials/advanced_search/index.html b/dev/tutorials/advanced_search/index.html index de83f57..d00d489 100644 --- a/dev/tutorials/advanced_search/index.html +++ b/dev/tutorials/advanced_search/index.html @@ -246,4 +246,4 @@ problem = Problem(examples) solution = search(g₅, problem, :Element) -@assert test_with_input(SymbolTable(g₅), solution, Dict(:x => 3)) == 5 +@assert test_with_input(SymbolTable(g₅), solution, Dict(:x => 3)) == 5 diff --git a/dev/tutorials/defining_grammars/index.html b/dev/tutorials/defining_grammars/index.html index 5201513..f64e72c 100644 --- a/dev/tutorials/defining_grammars/index.html +++ b/dev/tutorials/defining_grammars/index.html @@ -250,4 +250,4 @@ 11: Int = Int + Int 12: Int = Int * Int 13: Int = x -, Main.HerbCore.Constraint[Main.HerbConstraints.ComesAfter(1, [9])]) +, Main.HerbCore.Constraint[Main.HerbConstraints.ComesAfter(1, [9])]) diff --git a/dev/tutorials/getting_started_with_herb/index.html b/dev/tutorials/getting_started_with_herb/index.html index 36bd810..da44d1e 100644 --- a/dev/tutorials/getting_started_with_herb/index.html +++ b/dev/tutorials/getting_started_with_herb/index.html @@ -28,4 +28,4 @@ expr = Herb.HerbSearch.search(g, problem, :Real, enumerator=Herb.HerbSearch.get_dfs_enumerator, max_depth=4, max_size=30, max_time=180) print(expr)
      nothing

      We see that our synthesizer can find a program to construct the value 168, though a fun experiment would be trying to get the value 167, what do you think would happen? If you want you can try below.

      In any case, this concludes our first introduction to the Herb.jl program synthesis framework. You can see more examples in this repository, or explore yourself. Enjoy!

      problem = Herb.HerbData.Problem([Herb.HerbData.IOExample(Dict(:x => x), 167) for x ∈ 1:5], "example2")
       expr = Herb.HerbSearch.search(g, problem, :Real)
      -println(expr)
      +println(expr)