diff --git a/docs/src/api/branching.md b/docs/src/api/branching.md index 9f526cf87..eb2ab23df 100644 --- a/docs/src/api/branching.md +++ b/docs/src/api/branching.md @@ -19,7 +19,7 @@ the children of the current node of the branch-and-bound tree. Coluna provides the following function for this step: ```@docs -select! +Branching.select! ``` It works as follows. @@ -41,39 +41,39 @@ At last, it returns the candidates kept. ### Branching rule ```@docs -AbstractBranchingRule -apply_branching_rule +Branching.AbstractBranchingRule +Branching.apply_branching_rule ``` ### Candidate ```@docs -AbstractBranchingCandidate -getdescription -get_lhs -get_local_id -get_children -set_children! -get_parent -generate_children! +Branching.AbstractBranchingCandidate +Branching.getdescription +Branching.get_lhs +Branching.get_local_id +Branching.get_children +Branching.set_children! +Branching.get_parent +Branching.generate_children! ``` ### Selection criterion ```@docs -AbstractSelectionCriterion -select_candidates! +Branching.AbstractSelectionCriterion +Branching.select_candidates! ``` ### Branching API ```@docs -get_selection_nb_candidates -branching_context_type -new_context -get_int_tol -get_rules -get_selection_criterion +Branching.get_selection_nb_candidates +Branching.branching_context_type +Branching.new_context +Branching.get_int_tol +Branching.get_rules +Branching.get_selection_criterion ``` Method `advanced_select!` is part of the API but presented just below. @@ -88,7 +88,7 @@ additional kpis about each branching candidates. Coluna provides the following function for this step. ```@docs -advanced_select! +Branching.advanced_select! ``` Coluna has two default implementation for this method: @@ -118,25 +118,25 @@ restrict the number of retained candidates until only one is left. ### Strong Branching API ```@docs -get_units_to_restore_for_conquer -get_phases -get_score -get_conquer -get_max_nb_candidates +Branching.get_units_to_restore_for_conquer +Branching.get_phases +Branching.get_score +Branching.get_conquer +Branching.get_max_nb_candidates ``` Following methods are part of the API but have default implementation. We advise to not change them. ```@docs -perform_branching_phase! -eval_children_of_candidate! -eval_child_of_candidate! +Branching.perform_branching_phase! +Branching.eval_children_of_candidate! +Branching.eval_child_of_candidate! ``` #### Score ```@docs -AbstractBranchingScore -compute_score +Branching.AbstractBranchingScore +Branching.compute_score ``` \ No newline at end of file diff --git a/docs/src/api/storage.jl b/docs/src/api/storage.jl index b8df52fea..49cbcf332 100644 --- a/docs/src/api/storage.jl +++ b/docs/src/api/storage.jl @@ -24,8 +24,8 @@ # provides two methods to do both actions: # ```@docs -# create_record -# restore_from_record! +# ColunaBase.create_record +# ColunaBase.restore_from_record! # ``` # ## Example @@ -111,7 +111,7 @@ end # There is a tutorial about the tree search interface. # We define the node data structure. -mutable struct Node <: ClA.AbstractNode +mutable struct Node <: Coluna.TreeSearch.AbstractNode depth::Int id::Int branch_description::String @@ -123,13 +123,13 @@ mutable struct Node <: ClA.AbstractNode end end -ClA.get_root(node::Node) = isnothing(node.parent) ? node : ClA.root(node.parent) -ClA.get_parent(node::Node) = node.parent +Coluna.TreeSearch.get_root(node::Node) = isnothing(node.parent) ? node : Coluna.Treesearch.root(node.parent) +Coluna.TreeSearch.get_parent(node::Node) = node.parent # We define the search space data structure. # Note that we keep the storage in the search space because we have access to this # data structure throughout the whole tree search execution. -mutable struct FullExplSearchSpace <: ClA.AbstractSearchSpace +mutable struct FullExplSearchSpace <: Coluna.TreeSearch.AbstractSearchSpace nb_nodes_generated::Int formulation::Formulation solution::Tuple{Vector{Float64},Float64} @@ -141,7 +141,7 @@ mutable struct FullExplSearchSpace <: ClA.AbstractSearchSpace end # We implement the method that returns the root node. -function ClA.new_root(space::FullExplSearchSpace, _) +function Coluna.TreeSearch.new_root(space::FullExplSearchSpace, _) space.nb_nodes_generated += 1 return Node(nothing, 1, "", nothing) end @@ -248,20 +248,20 @@ end; # We define the method `children` of the tree search API. # It evaluates the current node and then generates its children. -function ClA.children(space::FullExplSearchSpace, current, _, _) +function Coluna.TreeSearch.children(space::FullExplSearchSpace, current, _, _) evaluate_current_node(space, current) return create_children(space, current) end # We don't define specific stopping criterion. -ClA.stop(::FullExplSearchSpace, _) = false +Coluna.TreeSearch.stop(::FullExplSearchSpace, _) = false # We return the best solution and the record at each node to make sure the example worked. -ClA.tree_search_output(space::FullExplSearchSpace, _) = space.record_ids_per_node, space.solution +Coluna.TreeSearch.tree_search_output(space::FullExplSearchSpace, _) = space.record_ids_per_node, space.solution # We run the example. search_space = FullExplSearchSpace(formulation) -ClA.tree_search(ClA.DepthFirstStrategy(), search_space, nothing, nothing) +Coluna.TreeSearch.tree_search(Coluna.TreeSearch.DepthFirstStrategy(), search_space, nothing, nothing) # ## API @@ -282,9 +282,9 @@ ClA.tree_search(ClA.DepthFirstStrategy(), search_space, nothing, nothing) # Entities can be in the storage unit, the model, or in both of them. # ```@docs -# record_type -# storage_unit_type -# new_storage_unit -# new_record -# restore_from_record! +# ColunaBase.record_type +# ColunaBase.storage_unit_type +# ColunaBase.new_storage_unit +# ColunaBase.new_record +# ColunaBase.restore_from_record! # ``` \ No newline at end of file diff --git a/docs/src/api/treesearch.jl b/docs/src/api/treesearch.jl index f336f1c4f..dc0f8fe87 100644 --- a/docs/src/api/treesearch.jl +++ b/docs/src/api/treesearch.jl @@ -89,7 +89,7 @@ end # We start by defining the node. Take a look at the API section to see # the list of methods you need to implement. -struct Node <: ClA.AbstractNode +struct Node <: Coluna.TreeSearch.AbstractNode depth::Int solution::Vector{Float64} var_lbs::Vector{Int} @@ -127,8 +127,8 @@ struct Node <: ClA.AbstractNode end end -ClA.get_root(node::Node) = isnothing(node.parent) ? node : ClA.root(node.parent) -ClA.get_parent(node::Node) = node.parent +Coluna.TreeSearch.get_root(node::Node) = isnothing(node.parent) ? node : ClA.root(node.parent) +Coluna.TreeSearch.get_parent(node::Node) = node.parent # Then, we define the search spaces. Take a look at the API section to see @@ -158,13 +158,13 @@ ClA.get_conquer(sp::BtSearchSpace) = sp.conquer_alg ClA.get_divide(sp::BtSearchSpace) = sp.divide_alg ClA.get_previous(sp::BtSearchSpace) = sp.previous ClA.set_previous!(sp::BtSearchSpace, previous) = sp.previous = previous -ClA.stop(sp::BtSearchSpace, _) = false +Coluna.TreeSearch.stop(sp::BtSearchSpace, _) = false # Then, we implement the search space of the diving. mutable struct DivingSearchSpace <: ClA.AbstractColunaSearchSpace formulation::Formulation - starting_node_in_bt::ClA.AbstractNode # change node + starting_node_in_bt::Coluna.TreeSearch.AbstractNode # change node cost_of_best_solution::Float64 conquer_alg divide_alg @@ -177,7 +177,7 @@ ClA.get_conquer(sp::DivingSearchSpace) = sp.conquer_alg ClA.get_divide(sp::DivingSearchSpace) = sp.divide_alg ClA.get_previous(sp::DivingSearchSpace) = sp.previous ClA.set_previous!(sp::DivingSearchSpace, previous) = sp.previous = previous -ClA.stop(sp::DivingSearchSpace, _) = false +Coluna.TreeSearch.stop(sp::DivingSearchSpace, _) = false # ## Writing algorithms @@ -186,7 +186,7 @@ ClA.stop(sp::DivingSearchSpace, _) = false # At each node, we define an algorithm `ComputeSolCost` that compute the cost of the # solution and returns its value. -@with_kw struct ComputeSolCost <: ClA.AbstractAlgorithm +@with_kw struct ComputeSolCost <: Coluna.AlgoAPI.AbstractAlgorithm log::String = "compute solution cost" end @@ -209,7 +209,7 @@ end # for a given variable x, both branches x <= 0 & x >= 1 or only branch x = 0 depending on # parameters chosen. -@with_kw struct Divide <: ClA.AbstractAlgorithm +@with_kw struct Divide <: Coluna.AlgoAPI.AbstractAlgorithm log::String = "classic divide" create_both_branches::Bool = true end @@ -240,13 +240,13 @@ end # - `Divide` with parameter `create_both_branches` equals to `false` as divide strategy # - `Coluna.Algorithm.DepthFirstStrategy` as explore strategy -@with_kw struct Diving <: ClA.AbstractAlgorithm +@with_kw struct Diving <: Coluna.AlgoAPI.AbstractAlgorithm conqueralg = ComputeSolCost(log="compute solution cost of Diving tree") dividealg = Divide( log = "divide for diving", create_both_branches = false ) - explore = ClA.DepthFirstStrategy() + explore = Coluna.TreeSearch.DepthFirstStrategy() end struct DivingInput @@ -255,8 +255,8 @@ end function ClA.run!(algo::Diving, env, model::Formulation, input::DivingInput) LOG_ && println("~~~~~~~~ Diving starts ~~~~~~~~") - diving_space = ClA.new_space(ClA.search_space_type(algo), algo, model, input) - output = ClA.tree_search(algo.explore, diving_space, env, input) + diving_space = Coluna.TreeSearch.new_space(Coluna.TreeSearch.search_space_type(algo), algo, model, input) + output = Coluna.TreeSearch.tree_search(algo.explore, diving_space, env, input) LOG_ && println("~~~~~~~~ end of Diving ~~~~~~~~") return output end @@ -264,7 +264,7 @@ end # We define the algorithm that will conquer each node of the binary tree algorithm. # It runs the `ComputeSolCost` algorithm and then the diving algorithm if the two first # variables have been fixed (i.e. if depth == 2). -@with_kw struct BtConquer <: ClA.AbstractAlgorithm +@with_kw struct BtConquer <: Coluna.AlgoAPI.AbstractAlgorithm compute = ComputeSolCost(log = "compute solution cost for Binary tree") heuristic = Diving() end @@ -284,17 +284,17 @@ end # - `Divide` with parameter `create_both_branches` equals to `false` as divide strategy # - `Coluna.Algorithm.DepthFirstStrategy` as explore strategy -@with_kw struct BinaryTree <: ClA.AbstractAlgorithm +@with_kw struct BinaryTree <: Coluna.AlgoAPI.AbstractAlgorithm conqueralg = BtConquer() dividealg = Divide() - explore = ClA.DepthFirstStrategy() + explore = Coluna.TreeSearch.DepthFirstStrategy() end # Look at how we call the generic tree search implementation. function ClA.run!(algo::BinaryTree, env, reform, input) - search_space = ClA.new_space(ClA.search_space_type(algo), algo, reform, input) - return ClA.tree_search(algo.explore, search_space, env, input) + search_space = Coluna.TreeSearch.new_space(Coluna.TreeSearch.search_space_type(algo), algo, reform, input) + return Coluna.TreeSearch.tree_search(algo.explore, search_space, env, input) end # ## Implementing tree search interface @@ -304,24 +304,24 @@ end # So there is a 1-to-n relation between tree search algorithm configurations and search space. # because one search space can be used by several tree search algorithms configuration. -ClA.search_space_type(::BinaryTree) = BtSearchSpace -ClA.search_space_type(::Diving) = DivingSearchSpace +Coluna.TreeSearch.search_space_type(::BinaryTree) = BtSearchSpace +Coluna.TreeSearch.search_space_type(::Diving) = DivingSearchSpace # Now, we implement the method that calls the constructor of a search space. # The type of the search space is known from above method. # A search space may receive information from the tree-search algorithm. # The `model`, and `input` arguments are the same than those received by the tree search algorithm. -ClA.new_space(::Type{BtSearchSpace}, alg, model, input) = +Coluna.TreeSearch.new_space(::Type{BtSearchSpace}, alg, model, input) = BtSearchSpace(model, alg.conqueralg, alg.dividealg) -ClA.new_space(::Type{DivingSearchSpace}, alg, model, input) = +Coluna.TreeSearch.new_space(::Type{DivingSearchSpace}, alg, model, input) = DivingSearchSpace(model, input.starting_node_in_parent_algorithm, alg.conqueralg, alg.dividealg) # We implement the method that returns the root node. # The definition of the root node depends on the search space. -ClA.new_root(::BtSearchSpace, input) = Node() -ClA.new_root(space::DivingSearchSpace, input) = +Coluna.TreeSearch.new_root(::BtSearchSpace, input) = Node() +Coluna.TreeSearch.new_root(space::DivingSearchSpace, input) = Node(space.starting_node_in_bt) # Then, we implement the method that converts the branching rules into nodes for the tree @@ -387,8 +387,8 @@ ClA.get_input(::Divide, space::DivingSearchSpace, node::Node) = # We return the cost of the best solution found. # We write one method for each search space. -ClA.tree_search_output(space::BtSearchSpace, _) = space.cost_of_best_solution -ClA.tree_search_output(space::DivingSearchSpace, _) = space.cost_of_best_solution +Coluna.TreeSearch.tree_search_output(space::BtSearchSpace, _) = space.cost_of_best_solution +Coluna.TreeSearch.tree_search_output(space::DivingSearchSpace, _) = space.cost_of_best_solution # ## Run the example @@ -413,55 +413,55 @@ output = ClA.run!(BinaryTree(), env, model, input) # ### Search space # ```@docs -# AbstractSearchSpace -# search_space_type -# new_space +# Coluna.TreeSearch.AbstractSearchSpace +# Coluna.TreeSearch.search_space_type +# Coluna.TreeSearch.new_space # ``` # ### Node # ```@docs -# AbstractNode -# new_root -# get_root -# get_parent -# get_priority +# Coluna.TreeSearch.AbstractNode +# Coluna.TreeSearch.new_root +# Coluna.TreeSearch.get_root +# Coluna.TreeSearch.get_parent +# Coluna.TreeSearch.get_priority # ``` # Additional methods needed for Coluna's algorithms: # ```@docs -# get_opt_state -# get_records -# get_branch_description -# isroot +# Coluna.TreeSearch.get_opt_state +# Coluna.TreeSearch.get_records +# Coluna.TreeSearch.get_branch_description +# Coluna.TreeSearch.isroot # ``` # ### Tree search algorithm # ```@docs -# AbstractExploreStrategy -# tree_search -# children -# stop -# tree_search_output +# Coluna.TreeSearch.AbstractExploreStrategy +# Coluna.TreeSearch.tree_search +# Coluna.TreeSearch.children +# Coluna.TreeSearch.stop +# Coluna.TreeSearch.tree_search_output # ``` # ### Tree search algorithm for Coluna # ```@docs -# AbstractColunaSearchSpace +# Coluna.Algorithm.AbstractColunaSearchSpace # ``` # The `children` method has a specific implementation for `AbstractColunaSearchSpace`` # that involves following methods: # ```@docs -# get_previous -# set_previous! -# node_change! -# get_divide -# get_reformulation -# get_input -# after_conquer! -# new_children +# Coluna.Algorithm.get_previous +# Coluna.Algorithm.set_previous! +# Coluna.Algorithm.node_change! +# Coluna.Algorithm.get_divide +# Coluna.Algorithm.get_reformulation +# Coluna.Algorithm.get_input +# Coluna.Algorithm.after_conquer! +# Coluna.Algorithm.new_children # ``` diff --git a/src/ColunaBase/recordmanager.jl b/src/ColunaBase/recordmanager.jl index 646f38544..919c65158 100644 --- a/src/ColunaBase/recordmanager.jl +++ b/src/ColunaBase/recordmanager.jl @@ -67,11 +67,7 @@ function create_record(storage, ::Type{StorageUnitType}) where {StorageUnitType< ) end -""" - restore_from_record!(storage, record) -Restores the state of the storage unit using the record that was previously generated. -""" function restore_from_record!(storage::NewStorage, record::RecordType) where {RecordType} storage_unit_manager = _get_storage_unit_manager!(storage, storage_unit_type(RecordType)) restore_from_record!(storage.model, storage_unit_manager.storage_unit, record)