Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Bottom up iterator #107

Draft
wants to merge 59 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
8b46d5b
Merge branch 'dev' of https://github.com/Herb-AI/HerbSearch.jl into dev
Feb 28, 2024
469bee5
Initial Bottom Up Search Procedure with Concrete Implementation
IvanValBozhanin Apr 1, 2024
548436b
Included Doc
IvanValBozhanin Apr 1, 2024
1f2c562
Doc fixed
IvanValBozhanin Apr 1, 2024
a9d59af
Initial commit
IvanValBozhanin Apr 1, 2024
1fb7ff4
Fixed merge conflicts and removed unnecessary file
Apr 2, 2024
533b9d0
Fixed documentation, hashing & other small issues
Apr 3, 2024
57e7994
Fixed documentation, hashing & other small issues
Apr 3, 2024
4e18781
Merge branch 'bottom-up-iterator' of github.com:Herb-AI/HerbSearch.jl…
Apr 3, 2024
5ad6c9b
Have a dictionary for each symbol
TudorMagirescu Apr 4, 2024
45d2d9e
Merged master
TudorMagirescu Apr 4, 2024
83c58ea
Integrated the constraint solver into the bottom-up search
TudorMagirescu Apr 5, 2024
a5246e3
Merge branch 'dev' into bottom-up-iterator
ReubenJ May 17, 2024
3d85e55
Merge branch 'dev' of github.com:Herb-AI/HerbSearch.jl into dev
TudorMagirescu May 19, 2024
6c3a25f
Merge branch 'dev' into bottom-up-iterator
TudorMagirescu May 19, 2024
4e6f1c0
Fixed the tests
TudorMagirescu May 19, 2024
e87b302
Merge branch 'bottom-up-iterator' of github.com:Herb-AI/HerbSearch.jl…
TudorMagirescu May 19, 2024
cc19aab
Started modifying the interface
TudorMagirescu Jul 8, 2024
1c03b43
Fixed the bottom up iterator
TudorMagirescu Jul 11, 2024
61f7fd0
Changed the way the next rules are stored
TudorMagirescu Jul 11, 2024
3fbf3a3
Refactor TopDownIterator to introduce new abstracy types for BFS and …
pwochner Oct 16, 2024
947a499
Merge branch 'master' into bottom-up-iterator
TudorMagirescu Oct 20, 2024
cc56b4c
Added type hierarchies for BottomUp and other useful abstractions.
TudorMagirescu Oct 20, 2024
dfb25df
Improve docstrings.
pwochner Oct 21, 2024
b3c3b29
Tidy up some of the docstrings.
pwochner Oct 21, 2024
4317852
Fix wrong signature in docs.
pwochner Oct 21, 2024
3b4759b
Utilize the nested iterator abstraction. Add tests and documentation.
TudorMagirescu Oct 21, 2024
5c3b8e0
Remove unused package.
TudorMagirescu Oct 21, 2024
70653f2
Bottom-Up implementation using UniformTrees initial commit
TudorMagirescu Nov 5, 2024
b19323c
Made observational equivalence an optional optimization instead of it…
TudorMagirescu Nov 13, 2024
31a21d5
Merge branch 'bottom-up-iterator' into bottom-up-uniform-trees
TudorMagirescu Nov 13, 2024
69cce6d
Update TagBot.yml
pwochner Nov 14, 2024
b70e247
Merge pull request #123 from Herb-AI/pwochner-patch-1
pwochner Nov 14, 2024
07761b7
Add max_size
THinnerichs Nov 14, 2024
14a814b
Add max_size
THinnerichs Nov 14, 2024
412df7d
Fixed bug related to partitioning of rules
TudorMagirescu Nov 14, 2024
e56d18e
Small tweak for Julia 1.12 world age change
Keno Nov 20, 2024
40cf2cd
If observation equivalence is enabled, don't return programs that crash
TudorMagirescu Nov 20, 2024
e325e7f
Merge branch 'bottom-up-uniform-trees' into bottom-up-iterator
TudorMagirescu Nov 20, 2024
d50413b
Fixed test group name
TudorMagirescu Nov 20, 2024
a9719e3
Merge pull request #122 from Herb-AI/iterator-hierarchy
ReubenJ Nov 27, 2024
c4c6deb
Merge pull request #128 from Keno/kf/latestworld
ReubenJ Dec 4, 2024
97a0718
Removed FixedShapedIterator
THinnerichs Nov 23, 2024
47616a5
Remove non-existent symbols from export
ReubenJ Dec 10, 2024
00fdacf
Fix compat bounds for standard libraries
ReubenJ Dec 10, 2024
88ac91f
Switch to separate test `Project.toml` structure
ReubenJ Dec 11, 2024
b9ad9ab
Bump minor version number
ReubenJ Dec 11, 2024
9ff0f71
Merge pull request #131 from Herb-AI/remove_fixedshape_iterator
THinnerichs Dec 11, 2024
290b2be
CompatHelper: bump compat for HerbSpecification to 0.2, (keep existin…
Nov 16, 2024
e369d69
Remove support for `[email protected]`
ReubenJ Dec 11, 2024
058ac94
Update types to reflect changes to `IOExample`s
ReubenJ Dec 12, 2024
13e24a7
Merge pull request #127 from Herb-AI/compathelper/new_version/2024-11…
THinnerichs Dec 12, 2024
220e1aa
CompatHelper: bump compat for HerbGrammar to 0.5, (keep existing compat)
Dec 13, 2024
fb17824
Remove usage of `SymbolTable` constructor`
ReubenJ Dec 16, 2024
17fc9d2
Bump patch version
ReubenJ Dec 16, 2024
c03cecd
Remove support for `[email protected]`
ReubenJ Dec 17, 2024
1a23938
Consistent (non-)use of carets in `[compat]`
ReubenJ Jan 21, 2025
8fe642a
Merge pull request #132 from Herb-AI/compathelper/new_version/2024-12…
ReubenJ Jan 21, 2025
1fce0a5
Fixed failing tests
TudorMagirescu Feb 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,3 @@ jobs:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
27 changes: 10 additions & 17 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "HerbSearch"
uuid = "3008d8e8-f9aa-438a-92ed-26e9c7b4829f"
authors = ["Sebastijan Dumancic <[email protected]>", "Jaap de Jong <[email protected]>", "Nicolae Filat <[email protected]>", "Piotr Cichoń <[email protected]>", "Tilman Hinnerichs <[email protected]>"]
version = "0.3.1"
version = "0.4.1"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Expand All @@ -10,25 +10,18 @@ HerbCore = "2b23ba43-8213-43cb-b5ea-38c12b45bd45"
HerbGrammar = "4ef9e186-2fe5-4b24-8de7-9f7291f24af7"
HerbInterpret = "5bbddadd-02c5-4713-84b8-97364418cca7"
HerbSpecification = "6d54aada-062f-46d8-85cf-a1ceaf058a06"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

[compat]
DataStructures = "0.17,0.18"
HerbConstraints = "^0.2.0"
HerbCore = "^0.3.0"
HerbGrammar = "^0.4.0"
HerbInterpret = "^0.1.3"
HerbSpecification = "^0.1.0"
MLStyle = "^0.4.17"
StatsBase = "^0.34"
julia = "^1.8"

[extras]
LegibleLambdas = "f1f30506-32fe-5131-bd72-7c197988f9e5"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "LegibleLambdas"]
HerbConstraints = "0.2.0"
HerbCore = "0.3.0"
HerbGrammar = "0.5"
HerbInterpret = "0.1.3"
HerbSpecification = "0.2"
MLStyle = "0.4.17"
Random = "1.8.0"
StatsBase = "0.34"
julia = "1.8"
14 changes: 10 additions & 4 deletions src/HerbSearch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ include("uniform_iterator.jl")

include("heuristics.jl")

include("fixed_shaped_iterator.jl")
include("bottom_up_iterators/nested_rulenode_iterator.jl")
include("bottom_up_iterators/nested_uniform_iterator.jl")
include("bottom_up_iterators/bottom_up_iterator.jl")
include("bottom_up_iterators/bottom_up_depth_iterator.jl")
include("bottom_up_iterators/bottom_up_uniform_iterator.jl")

include("top_down_iterator.jl")

include("evaluate.jl")
Expand All @@ -42,8 +47,6 @@ export
ProgramIterator,
@programiterator,

ContextSensitivePriorityEnumerator,

heuristic_leftmost,
heuristic_rightmost,
heuristic_random,
Expand All @@ -56,7 +59,6 @@ export
optimal_program,
suboptimal_program,

FixedShapedIterator,
UniformIterator,
next_solution!,

Expand All @@ -66,6 +68,10 @@ export
DFSIterator,
MLFSIterator,

BottomUpIterator,
BUDepthIterator,
BUUniformIterator,

MHSearchIterator,
VLSNSearchIterator,
SASearchIterator,
Expand Down
200 changes: 200 additions & 0 deletions src/bottom_up_iterators/bottom_up_depth_iterator.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
Base.@doc """
@programiterator BUDepthIterator(problem::Union{Nothing, Problem{Vector{IOExample}}}=nothing, obs_equivalence::Bool=false) <: BottomUpIterator

Implementation of the `BottomUpIterator`. Iterates through complete programs in increasing order of their depth.
""" BUDepthIterator
@programiterator BUDepthIterator(
problem::Any=nothing, # TODO: Look into this usage of `Any`.
obs_equivalence::Bool=false
) <: BottomUpIterator

"""
struct BUDepthBank <: BottomUpBank

Specialization of `BottomUpState`'s `BottomUpBank` type. Holds a `Dict` mapping `Symbols` to `Vectors` of `RuleNodes` of that `Symbol`.
"""
struct BUDepthBank <: BottomUpBank
rulenodes_by_symbol::Dict{Symbol, Vector{RuleNode}}
end

"""
struct BUDepthData <: BottomUpData

Specialization of `BottomUpState`'s `BottomUpData` type. Contains the following:
* `nested_rulenode_iterator::NestedRulenodeIterator`: Iterator generating `RuleNodes` using a grammar rule to combine existing `RuleNodes` from the `bank`.
* `new_programs::Vector{RuleNode}`: Programs generated at the current depth level. Will be appended to the `bank` when starting a new depth level.
* `rules::Queue{Int}`: Grammar rules left to be used at the current depth level.
* `depth::Int`: Current depth.
"""
mutable struct BUDepthData <: BottomUpData
nested_rulenode_iterator::NestedRulenodeIterator
new_programs::Vector{RuleNode}
rules::Queue{Int}
depth::Int
end

"""
order(iter::BUDepthIterator)::Queue{Int}

Returns the non-terminal rules in the order in which they appear in the grammar.
"""
function order(
iter::BUDepthIterator
)::Queue{Int}
grammar::ContextSensitiveGrammar = get_grammar(iter.solver)
rules::Queue{Int} = Queue{Int}()

for (rule_index, is_terminal) ∈ enumerate(grammar.isterminal)
if !is_terminal
enqueue!(rules, rule_index)
end
end

return rules
end

"""
init_bank(iter::BUDepthIterator)::BUDepthBank

Returns an initialized object of type `BUDepthBank`. For each symbol in the grammar (i.e. key in the dictionary), an empty `Vector{RuleNode}` (i.e. value in the dictionary) is allocated.
"""
function init_bank(
iter::BUDepthIterator
)::BUDepthBank
grammar::ContextSensitiveGrammar = get_grammar(iter.solver)
rulenodes_by_symbol::Dict{Symbol, Vector{RuleNode}} = Dict{Symbol, Vector{RuleNode}}()

for symbol ∈ grammar.types
rulenodes_by_symbol[symbol] = Vector{RuleNode}()
end

return BUDepthBank(rulenodes_by_symbol)
end

"""
init_data(iter::BUDepthIterator)::BUDepthData

Returns an initialized object of type `BUDepthData`. The initialization consists of the following:
* `nested_rulenode_iterator` is set to an empty `NestedRulenodeIterator`.
* `rules` contains the indeces of terminal rules in the grammar.
* `new_programs` is an empty `Vector{RuleNode}`.
* `depth` is set to 1.
"""
function init_data(
iter::BUDepthIterator
)::BUDepthData
grammar::ContextSensitiveGrammar = get_grammar(iter.solver)

empty_nested_iterator::NestedRulenodeIterator = NestedRulenodeIterator()
depth::Int = 1

rules::Queue{Int} = Queue{Int}()
for (rule_index, is_terminal) ∈ enumerate(grammar.isterminal)
if is_terminal
enqueue!(rules, rule_index)
end
end

return BUDepthData(empty_nested_iterator, Vector{RuleNode}(), rules, depth)
end

"""
create_program!(iter::BUDepthIterator, bank::BUDepthBank, data::BUDepthData)::Union{Nothing, RuleNode}

Returns the next program in `BUDepthIterator`'s iteration. Performs the following steps:
1. Check whether `data.nested_rulenode_iterator` contains any program.
2. Otherwise, pick the next rule from `data.rules` and generate all combinations of `RuleNodes` from the bank that could be combined using this rule.
3. If `data.rules` is empty, call `_increase_depth!` and go to step 2.
"""
function create_program!(
iter::BUDepthIterator,
bank::BUDepthBank,
data::BUDepthData
)::Union{Nothing, RuleNode}
program::Union{RuleNode, Nothing} = get_next_rulenode!(data.nested_rulenode_iterator)

while isnothing(program)
grammar::ContextSensitiveGrammar = get_grammar(iter.solver)

if isempty(data.rules)
_increase_depth!(iter, bank, data, grammar)

if data.depth > get_max_depth(iter.solver)
return nothing
end
end

data.nested_rulenode_iterator = _create_nested_rulenode_iterator(iter, bank, data, grammar)
program = get_next_rulenode!(data.nested_rulenode_iterator)
end

return program
end

"""
update_state!(::BUDepthIterator, ::BUDepthBank, data::BUDepthData, program::RuleNode)::Nothing

Appends the `program` to `data.new_programs`.
"""
function update_state!(
::BUDepthIterator,
::BUDepthBank,
data::BUDepthData,
program::RuleNode
)::Nothing
push!(data.new_programs, program)
return nothing
end

"""
_create_nested_rulenode_iterator(::BUDepthIterator, bank::BUDepthBank, data::BUDepthData, grammar::ContextSensitiveGrammar)::NestedRulenodeIterator

Creates a new `NestedRulenodeIterator` iterating through `RuleNodes` having the root the current rule in `data.rules`.
The childrens of the root will be all combinations of `RuleNodes` of matching `Symbol` types from the `bank`.
"""
function _create_nested_rulenode_iterator(
::BUDepthIterator,
bank::BUDepthBank,
data::BUDepthData,
grammar::ContextSensitiveGrammar,
)::NestedRulenodeIterator
rule::Int = dequeue!(data.rules)

if grammar.isterminal[rule]
return NestedRulenodeIterator([Tuple{}()], rule)
end

childtypes::Vector{Symbol} = grammar.childtypes[rule]
children_combinations::Vector{Vector{RuleNode}} = map(symbol -> bank.rulenodes_by_symbol[symbol], childtypes)

return NestedRulenodeIterator(Iterators.product(children_combinations...), rule)
end

"""
_increase_depth!(iter::BUDepthIterator, bank::BUDepthBank, data::BUDepthData, grammar::ContextSensitiveGrammar)::Nothing

Performs the following steps required when the depth is increased:
* Increase `data.depth`.
* Create a new `data.rules` queue consisting of the indices of non-terminal rules in the grammar.
* Copy all programs from `data.new_programs` to the `bank`.
* Go to Step 2.
"""
function _increase_depth!(
iter::BUDepthIterator,
bank::BUDepthBank,
data::BUDepthData,
grammar::ContextSensitiveGrammar
)::Nothing
data.rules = order(iter)
data.depth += 1

rulenodes_by_symbol::Dict{Symbol, Vector{RuleNode}} = bank.rulenodes_by_symbol

for program ∈ data.new_programs
symbol::Symbol = grammar.types[program.ind]
push!(rulenodes_by_symbol[symbol], program)
end

empty!(data.new_programs)
return nothing
end
Loading