1#ifndef ZONOOPT_BRANCH_AND_BOUND_
2#define ZONOOPT_BRANCH_AND_BOUND_
18#include <condition_variable>
22#include <memory_resource>
30namespace ZonoOpt::detail
35 explicit BranchAndBound(
const MI_data& data);
41 std::pair<std::vector<OptSolution>, OptSolution> multi_solve(
int max_sols = std::numeric_limits<int>::max());
44 void warmstart(
const Eigen::Vector<zono_float, -1>& xi_ws,
const Eigen::Vector<zono_float, -1>& u_ws)
53 std::pmr::synchronized_pool_resource* pool_ptr;
55 explicit NodeDeleter(std::pmr::synchronized_pool_resource* pool_ptr) : pool_ptr(pool_ptr)
59 void operator()(Node* node)
const
64 pool_ptr->deallocate(node,
sizeof(Node),
alignof(Node));
71 bool operator()(
const std::unique_ptr<Node, NodeDeleter>& n1,
72 const std::unique_ptr<Node, NodeDeleter>& n2)
const
74 return n1->solution.J > n2->solution.J;
80 bool operator()(
const std::pair<int, zono_float>& v1,
81 const std::pair<int, zono_float>& v2)
const
83 if (v1.second != v2.second)
return v1.second < v2.second;
84 return v1.first < v2.first;
88 template <
typename T,
typename Comp=std::less<T>>
91 ThreadSafeSet<T, Comp>& thread_tags;
93 bool specified =
false;
95 explicit ThreadGuard(ThreadSafeSet<T, Comp>& thread_tags): thread_tags(thread_tags)
99 void specify_tag(
const T& tag)
104 this->specified =
true;
105 this->thread_tags.add(tag);
112 this->thread_tags.remove(tag);
117 std::pmr::synchronized_pool_resource pool;
120 PriorityQueuePrunable<std::unique_ptr<Node, NodeDeleter>, NodeCompare> node_queue;
121 PriorityQueuePrunable<std::unique_ptr<Node, NodeDeleter>, NodeCompare> dive_queue;
122 mutable std::mutex pq_mtx;
123 mutable std::mutex incumbent_mtx;
124 std::condition_variable pq_cv_bnb, pq_cv_admm_fp;
127 bool multi_sol =
false;
128 std::shared_ptr<ADMM_data> bnb_data, admm_fp_data;
130 std::atomic<bool> converged =
false;
131 std::atomic<bool> done =
false;
132 std::atomic<bool> feasible =
false;
133 std::atomic<bool> admm_fp_incumbent =
false;
134 std::atomic<long int> qp_iter = 0;
135 std::atomic<int> iter = 0;
136 std::atomic<int> iter_admm_fp = 0;
137 std::atomic<zono_float> J_max = std::numeric_limits<zono_float>::infinity();
138 ThreadSafeAccess<Eigen::Vector<
zono_float, -1>> z, x, u;
139 std::atomic<zono_float> primal_residual = std::numeric_limits<zono_float>::infinity();
140 std::atomic<zono_float> dual_residual = std::numeric_limits<zono_float>::infinity();
141 ThreadSafeIncrementable<double> total_startup_time{0.0};
142 ThreadSafeIncrementable<double> total_run_time{0.0};
143 ThreadSafeSet<std::pair<int, zono_float>, JThreadCompare> J_threads;
144 ThreadSafeVector<OptSolution> solutions;
145 std::uniform_int_distribution<int> uniform_dist{0, std::numeric_limits<int>::max()};
152 std::unique_ptr<Node, NodeDeleter> make_node(
const std::shared_ptr<ADMM_data>& admm_data);
154 std::unique_ptr<Node, NodeDeleter> clone_node(
const std::unique_ptr<Node, NodeDeleter>& other);
157 std::variant<OptSolution, std::pair<std::vector<OptSolution>, OptSolution>> solver_core(
158 int max_sols = std::numeric_limits<int>::max());
161 void solve_and_branch(
const std::unique_ptr<Node, NodeDeleter>& node);
163 void admm_fp_solve(
const std::unique_ptr<ADMM_FP_solver>& node);
166 bool is_integer_feasible(
const Eigen::Ref<
const Eigen::Vector<zono_float, -1>> xb)
const;
169 void branch_most_frac(
const std::unique_ptr<Node, NodeDeleter>& node);
174 void admm_fp_loop(std::unique_ptr<ADMM_FP_solver>&& node);
177 void push_node(std::unique_ptr<Node, NodeDeleter>&& node);
180 void push_dive_node(std::unique_ptr<Node, NodeDeleter>&& node);
186 bool check_bin_equal(
const OptSolution& sol1,
const OptSolution& sol2)
const;
189 bool is_box_integer(
const Box& box)
const;
Convex and mixed-integer ADMM implementations used within ZonoOpt.
Data structures for mixed-integer optimization in ZonoOpt library.
Optimization settings and solution data structures for ZonoOpt library.
#define zono_float
Defines the floating-point type used in ZonoOpt.
Definition ZonoOpt.hpp:45