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

FixedShapedSolver #29

Merged
merged 49 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a53cc81
Add is_subdomain
Whebon Feb 9, 2024
6ee3176
Replace `_pattern_match_with_hole`, `_pattern_match`, `_rulenode_matc…
Whebon Feb 24, 2024
350794e
Add Solver stub
Whebon Feb 24, 2024
e25314a
Scaffolding of the `Solver`
Whebon Feb 25, 2024
01d3154
Add support for bychildtypes
Whebon Feb 25, 2024
cc600cc
Add DataStructures for the PriorityQueue class
Whebon Feb 25, 2024
3189b01
Reorganize code over multiple files
Whebon Feb 25, 2024
d6c3f27
Test basic functionality of the Solver
Whebon Feb 26, 2024
fb51e07
Add `VarNode` and refactor `MatchNode` -> `RuleNode`
Whebon Mar 1, 2024
ab769c7
Add `fill_hole!` for the `FixedShapedIterator`
Whebon Mar 1, 2024
7036d55
Add path-based tree manipulations and the Forbidden constraint
Whebon Mar 2, 2024
8fbdef7
add `is_feasible` and `get_node_path`
Whebon Mar 5, 2024
a8c932e
Add `SolverStatistics` to track the number of propagations
Whebon Mar 6, 2024
6e0af03
Add path based propagation triggers (on_tree_manipulation is a `Dict`)
Whebon Mar 6, 2024
fe5c18c
Move `max_depth` and `max_size` to the Solver
Whebon Mar 7, 2024
b263f7a
Add post method to differentiate between rescheduling and posting new…
Whebon Mar 7, 2024
70d24de
Remove legacy code
Whebon Mar 7, 2024
d56f674
Add `make_less_than_or_equal!` and test cases
Whebon Mar 8, 2024
7ab0ee6
Commit to `is_feasible` checks over try-catch blocks
Whebon Mar 8, 2024
6d367e4
Add tests for `Forbidden` and `Ordered` GrammarConstraints
Whebon Mar 9, 2024
1f278a8
Add new implementation of `LocalOrdered`
Whebon Mar 9, 2024
2239275
Add jump starts for the solver, and fix tiebreakers in `make_less_tha…
Whebon Mar 9, 2024
bb5c0d1
Add tests for Forbidden and Ordered constraints
Whebon Mar 9, 2024
4838177
Add the jump start to `Solver` constructor
Whebon Mar 10, 2024
8e3120d
Ensure newly added holes are simplified (FSH of domain size 1 should …
Whebon Mar 11, 2024
d5d49c7
Add constraintless iteration of fixed shaped trees
Whebon Mar 14, 2024
dbe3f95
Add `GenericSolver` and make the forbidden constraint compatible with…
Whebon Mar 14, 2024
00868b7
Add `isfilled` for `StateFixedShapedHole`s
Whebon Mar 15, 2024
39a3f43
Add constraint deactivation for the fixed shaped solver
Whebon Mar 15, 2024
49e5738
Add the `FixedShapedSolver` as an inner procedure of the top down ite…
Whebon Mar 15, 2024
45fbb8f
Make tree manipulations able to mark the fixed shaped solver as infea…
Whebon Mar 15, 2024
fa99259
Remove `StateConstraint` and replace it with an `isactive::Dict{Const…
Whebon Mar 18, 2024
4ef2a1a
`state_id` to `current_state_id`
Whebon Mar 19, 2024
7aee045
Move `isfilled` and `get_rule` to HerbCore
Whebon Mar 19, 2024
3039740
Replace `on_tree_manipulation` with `activeconstraints`
Whebon Mar 19, 2024
bf9985e
Remove `propagate_on_tree_manipulation` in favor of constraint deacti…
Whebon Mar 21, 2024
be2f706
Refactor `.ind` to `get_rule`
Whebon Mar 21, 2024
210b403
Collapse two cases of StateFixedShapedHole
Whebon Mar 21, 2024
ccbe3c4
Refactor `pattern_match` to support `DomainRuleNode`s
Whebon Mar 22, 2024
bf648bb
Specify that propagatable constraint must be `LocalConstraint`s
Whebon Mar 25, 2024
eaa003f
Remove `make_state_int`
Whebon Mar 25, 2024
4316939
Fix a bug related an edge case of the FixedShapedSolver
Whebon Mar 26, 2024
f1afe38
Add the `Contains` constraint
Whebon Mar 26, 2024
a936f90
Rename is_feasible and activeconstraints
Whebon Mar 27, 2024
5c6e547
Add `is_domain_increasing` to `substitute!`
Whebon Mar 28, 2024
b61fadd
Add documentation
Whebon Mar 28, 2024
1690499
Tabs to spaces, Grammar to AbstractGrammar; minor changes to docs and…
THinnerichs Apr 2, 2024
3d026d8
Add documentation for `propagate!` functions
Whebon Apr 2, 2024
3dd9dce
merge solver into dfs-solver
THinnerichs Apr 3, 2024
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: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ docs/site/
# committed for packages, but should be committed for applications that require a static
# environment.
Manifest.toml

12 changes: 7 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
name = "HerbConstraints"
uuid = "1fa96474-3206-4513-b4fa-23913f296dfc"
authors = ["Jaap de Jong <[email protected]>"]
version = "0.1.0"
version = "0.2.0"

[deps]
HerbGrammar = "4ef9e186-2fe5-4b24-8de7-9f7291f24af7"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
HerbCore = "2b23ba43-8213-43cb-b5ea-38c12b45bd45"
HerbGrammar = "4ef9e186-2fe5-4b24-8de7-9f7291f24af7"
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"

[compat]
julia = "1.8"
HerbCore = "0.1.0"
HerbGrammar = "0.1.0"
HerbCore = "^0.2.0"
HerbGrammar = "^0.2.1"
julia = "^1.8"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
167 changes: 96 additions & 71 deletions src/HerbConstraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,110 +2,135 @@ module HerbConstraints

using HerbCore
using HerbGrammar
using DataStructures
using MLStyle

"""
PropagatorConstraint <: Constraint
abstract type GrammarConstraint <: Constraint
Whebon marked this conversation as resolved.
Show resolved Hide resolved

Abstract type representing all propagator constraints.
Each propagator constraint has an implementation of a [`propagate`](@ref)-function that takes

- the [`PropagatorConstraint`](@ref)
- a [`Grammar`](@ref)
- a [`GrammarContext`](@ref), which most importantly contains the tree and the location
in the tree where propagation should take place.
- The `domain` which the [`propagate`](@ref)-function prunes.

The [`propagate`](@ref)-function returns a tuple containing

- The pruned `domain`
- A list of new [`LocalConstraint`](@ref)s
Abstract type representing all user-defined constraints.
Each grammar constraint has a related [LocalConstraint](@ref) that is responsible for propagating the constraint at a specific location in the tree.
Grammar constraints should implement `on_new_node` to post a [`LocalConstraint`](@ref) at that new node
"""
abstract type PropagatorConstraint <: Constraint end
abstract type GrammarConstraint <: Constraint end

"""
abstract type LocalConstraint <: Constraint

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

- the [`LocalConstraint`](@ref)
- a [`Grammar`](@ref)
- a [`GrammarContext`](@ref), which most importantly contains the tree and the location
in the tree where propagation should take place.
- The `domain` which the [`propagate`](@ref)-function prunes.
Each local constraint contains a `path` that points to a specific location in the tree.
The constraint is propagated on any tree manipulation at or below that `path`.

The [`propagate`](@ref)-function returns a tuple containing

- The pruned `domain`
- A list of new [`LocalConstraint`](@ref)s
Each local constraint should implement a [`propagate!`](@ref)-function.
Inside the [`propagate!`](@ref) function, the constraint can use the following solver functions:
- `remove!`: Elementary tree manipulation. Removes a value from a domain. (other tree manipulations are: `remove_above!`, `remove_below!`, `remove_all_but!`)
- `deactivate!`: Prevent repropagation. Call this as soon as the constraint is satisfied.
- `mark_infeasible!`: Report a non-trivial inconsistency. Call this if the constraint can never be satisfied. An empty domain is considered a trivial inconsistency, such inconsistencies are already handled by tree manipulations.
- `isfeasible`: Check if the current tree is still feasible. Return from the propagate function, as soon as infeasibility is detected.

!!! warning
By default, [`LocalConstraint`](@ref)s are only propagated once.
Constraints that have to be propagated more frequently should return
themselves in the list of new local constraints.
Constraints that have to be propagated more frequently should subscribe to an event. This part of the solver is still WIP.
Currently, the solver supports only one type of subscription: `propagate_on_tree_manipulation!`.
"""
abstract type LocalConstraint <: Constraint end
Whebon marked this conversation as resolved.
Show resolved Hide resolved

@enum PropagateFailureReason unchanged_domain=1
PropagatedDomain = Union{PropagateFailureReason, Vector{Int}}
include("csg_annotated/csg_annotated.jl")

include("matchfail.jl")
include("matchnode.jl")
include("context.jl")
include("patternmatch.jl")
include("rulenodematch.jl")
include("varnode.jl")
include("domainrulenode.jl")

include("csg_annotated/csg_annotated.jl")
include("solver/solver.jl")
include("solver/solverstatistics.jl")
include("solver/generic_solver/state.jl")
include("solver/generic_solver/generic_solver.jl")
include("solver/generic_solver/treemanipulations.jl")

include("propagatorconstraints/comesafter.jl")
include("propagatorconstraints/forbidden_path.jl")
include("propagatorconstraints/require_on_left.jl")
include("propagatorconstraints/forbidden.jl")
include("propagatorconstraints/ordered.jl")
include("propagatorconstraints/condition.jl")
include("propagatorconstraints/one_of.jl")
include("solver/fixed_shaped_solver/state_manager.jl")
include("solver/fixed_shaped_solver/state_sparse_set.jl")
include("solver/fixed_shaped_solver/state_fixed_shaped_hole.jl")
include("solver/fixed_shaped_solver/fixed_shaped_solver.jl")
include("solver/fixed_shaped_solver/fixed_shaped_solver_treemanipulations.jl")
include("solver/domainutils.jl")

include("patternmatch.jl")
include("lessthanorequal.jl")

include("localconstraints/local_forbidden.jl")
include("localconstraints/local_ordered.jl")
include("localconstraints/local_condition.jl")
include("localconstraints/local_one_of.jl")

export
AbstractMatchNode,
MatchNode,
MatchVar,
matchnode2expr,
include("localconstraints/local_contains.jl")

GrammarContext,
addparent!,
copy_and_insert,
include("grammarconstraints/forbidden.jl")
include("grammarconstraints/ordered.jl")
include("grammarconstraints/contains.jl")

contains_var,

PropagatorConstraint,
export
GrammarConstraint,
LocalConstraint,
PropagateFailureReason,
PropagatedDomain,

propagate,
DomainRuleNode,
VarNode,
pattern_match,
check_tree,

generateconstraints!,

ComesAfter,
ForbiddenPath,
RequireOnLeft,

#grammar constraints
Forbidden,
Ordered,
Condition,
OneOf,
Contains,

#local constraints
LocalForbidden,
LocalOrdered,
LocalCondition
LocalOrdered,
LocalOneOf
LocalContains,

#public solver functions
GenericSolver,
Solver,
State,
new_state!,
save_state!,
load_state!,
isfeasible,
get_state,
get_tree,
get_grammar,
get_state,
get_node_at_location,
get_hole_at_location,
get_max_depth,
get_max_size,
get_tree_size,

#tree manipulations
remove!,
remove_all_but!,
substitute!,

#domainutils
is_subdomain,
partition,
are_disjoint,
get_intersection,

#solverstatistics
track!,

#functions related to stateful objects
restore!,
StateInt,
get_value,
set_value!,
increment!,
decrement!,

#fixed shaped solver
next_solution!,
FixedShapedSolver,

#state fixed shaped hole
StateFixedShapedHole,
statefixedshapedhole2rulenode

end # module HerbConstraints
39 changes: 0 additions & 39 deletions src/context.jl

This file was deleted.

14 changes: 8 additions & 6 deletions src/csg_annotated/csg_annotated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ end
```
"""
macro csgrammar_annotated(expression)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is still necessary?

# collect and remove labels
# collect and remove labels
labels = _get_labels!(expression)

# parse rules, get constraints from annotations
Expand Down Expand Up @@ -92,19 +92,21 @@ macro csgrammar_annotated(expression)

# determine parameters
alltypes = collect(keys(bytype))
is_terminal = [isterminal(rule, alltypes) for rule ∈ rules]
is_eval = [iseval(rule) for rule ∈ rules]
childtypes = [get_childtypes(rule, alltypes) for rule ∈ rules]
domains = Dict(type => BitArray(r ∈ bytype[type] for r ∈ 1:length(rules)) for type ∈ alltypes)
is_terminal = [isterminal(rule, alltypes) for rule ∈ rules]
is_eval = [iseval(rule) for rule ∈ rules]
childtypes = [get_childtypes(rule, alltypes) for rule ∈ rules]
bychildtypes = [BitVector([childtypes[i1] == childtypes[i2] for i2 ∈ 1:length(rules)]) for i1 ∈ 1:length(rules)]
domains = Dict(type => BitArray(r ∈ bytype[type] for r ∈ 1:length(rules)) for type ∈ alltypes)

return ContextSensitiveGrammar(
rules,
types,
is_terminal,
is_eval,
bytype,
domains,
domains,
childtypes,
bychildtypes,
nothing,
constraints
)
Expand Down
17 changes: 17 additions & 0 deletions src/domainrulenode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
struct DomainRuleNode <: AbstractRuleNode

Matches any 1 rule in its domain.
Example usage:

DomainRuleNode(Bitvector((0, 0, 1, 1)), [RuleNode(1), RuleNode(1)])

This matches `RuleNode(3, [RuleNode(1), RuleNode(1)])` and `RuleNode(4, [RuleNode(1), RuleNode(1)])` and `Hole({3, 4}, [RuleNode(1), RuleNode(1)])`
"""
struct DomainRuleNode <: AbstractRuleNode
domain::BitVector
children::Vector{AbstractRuleNode}
end

#DomainRuleNode(get_domain(grammar, sym), [])
DomainRuleNode(domain::BitVector) = DomainRuleNode(domain, [])
26 changes: 26 additions & 0 deletions src/grammarconstraints/contains.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Contains <: GrammarConstraint
This [`GrammarConstraint`] enforces that a given `rule` appears in the program tree at least once.
"""
struct Contains <: GrammarConstraint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contains is a verb and should hence not be used as a struct name; also not very descriptive. Better use ContainsConstraint

rule::Int
end

function on_new_node(solver::Solver, contraint::Contains, path::Vector{Int})
if length(path) == 0
#only post a local constraint at the root
post!(solver, LocalContains(path, contraint.rule))
end
end

"""
check_tree(c::Forbidden, g::AbstractGrammar, tree::RuleNode)::Bool

Checks if the given [`AbstractRuleNode`](@ref) tree abides the [`Forbidden`](@ref) constraint.
"""
function check_tree(contraint::Contains, tree::AbstractRuleNode)::Bool
if get_rule(tree) == contraint.rule
return true
end
return any(check_tree(contraint, child) for child ∈ get_children(tree))
end
Loading
Loading