use std::fmt::{Debug, Display};
use std::sync::atomic::{AtomicU32, Ordering};
static BRANCH_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
#[derive(Clone)]
pub struct BranchComparator<BranchingFilter : IBranchFilter,DualStorage : UserDualStore> {
has_bound: bool,
_bf : PhantomData<BranchingFilter>,
_ds : PhantomData<DualStorage>
}
impl<BranchingFilter : IBranchFilter,DualStorage : UserDualStore> BranchComparator<BranchingFilter, DualStorage> {
pub fn with_bound() -> Self {
Self {
has_bound : true,
_bf : PhantomData,
_ds : PhantomData
}
}
pub fn without_bound() -> Self {
Self {
has_bound : false,
_bf : PhantomData,
_ds : PhantomData
}
}
fn score_branch(b: &Branch<BranchingFilter, DualStorage>) -> u32 {
if b.special.is_some() {
return u32::MAX;
}
10000 + b.depth
}
}
impl<BranchingFilter : IBranchFilter,DualStorage : UserDualStore> Compare<Branch<BranchingFilter, DualStorage>> for BranchComparator<BranchingFilter, DualStorage> {
fn compare(
&self,
l: &Branch<BranchingFilter, DualStorage>,
r: &Branch<BranchingFilter, DualStorage>,
) -> core::cmp::Ordering {
if let (
Some(SpecialType::LDSBranch {
taboo_filters: ref taboo_filters_l,
}),
Some(SpecialType::LDSBranch {
taboo_filters: ref taboo_filters_r,
}),
) = (&l.special, &r.special)
{
taboo_filters_r
.len()
.cmp(&taboo_filters_l.len())
.then(l.depth.cmp(&r.depth))
} else if self.has_bound {
r.old_obj_bound.total_cmp(&l.old_obj_bound)
} else {
BranchComparator::score_branch(l).cmp(&BranchComparator::score_branch(r))
}
}
}
#[derive(Debug, Clone)]
pub enum SpecialType<BranchFilter : IBranchFilter> {
Root,
Integer,
LDSBranch { taboo_filters : HashSet<BranchFilter> }
}
use core::fmt::Formatter;
use std::marker::PhantomData;
use compare::Compare;
impl<BranchFilter : IBranchFilter> Display for SpecialType<BranchFilter > {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SpecialType::Root => write!(f,"Root"),
SpecialType::Integer => write!(f,"Integer"),
LDSBranch { taboo_filters} => {
write!(f, "LDS(").unwrap();
taboo_filters.iter().for_each(|filter| write!(f, "{},", filter).unwrap());
write!(f, ")")
}
}
}
}
#[derive(Debug, Clone)]
pub struct Branch<BranchFilter, DualStore>
where
BranchFilter: IBranchFilter,
DualStore : UserDualStore
{
pub id: u32,
pub parent: u32,
pub depth: u32,
pub old_obj_bound: f64, pub old_obj_heuristic: bool,
pub old_obj_dual_center: Option<(f64,DualStore)>,
pub filters: Vec<BranchFilter>,
pub allow_heuristic_pricing : bool,
pub special: Option<SpecialType<BranchFilter>>,
}
use crate::{IBranchFilter, UserDualStore};
use crate::branch::SpecialType::LDSBranch;
use crate::misc::HashSet;
impl<BranchFilter, DualStore> Branch<BranchFilter, DualStore>
where
BranchFilter: IBranchFilter,
DualStore : UserDualStore
{
pub fn default() -> Self {
let id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id,
depth: 0,
parent: id,
old_obj_bound: f64::NEG_INFINITY,
old_obj_heuristic: false,
old_obj_dual_center : None,
allow_heuristic_pricing : true,
filters: Vec::default(),
special: Some(SpecialType::Root),
}
}
pub fn create_lds_root() -> Self {
let id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id,
depth: 0,
parent: id,
allow_heuristic_pricing : true,
old_obj_bound: f64::NEG_INFINITY,
old_obj_heuristic: false,
old_obj_dual_center : None,
filters: Vec::default(),
special: Some(SpecialType::LDSBranch {
taboo_filters : HashSet::default(),
}),
}
}
pub fn create_integer(&self, local : bool) -> Self {
let new_id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id: new_id,
parent: self.id,
depth: self.depth,
allow_heuristic_pricing : false,
old_obj_bound: self.old_obj_bound,
old_obj_heuristic: self.old_obj_heuristic,
old_obj_dual_center : self.old_obj_dual_center.clone(),
filters: if local { self.filters.clone()} else { vec![] },
special: Some(SpecialType::Integer),
}
}
pub fn upgrade_to_non_heuristic_pricing(&self) -> Self {
let new_id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id: new_id,
parent: self.id,
depth: self.depth,
allow_heuristic_pricing : false,
old_obj_bound: self.old_obj_bound,
old_obj_heuristic: self.old_obj_heuristic,
old_obj_dual_center : self.old_obj_dual_center.clone(),
filters: self.filters.clone(),
special: self.special.clone(),
}
}
pub fn create_lds_zero_child(&self, parent_obj: f64, filters_of_one_child: &[BranchFilter], parent_partial : bool, parent_dual_center : Option<(f64, DualStore)>) -> Self {
let mut taboo_list = if let Some(SpecialType::LDSBranch{ taboo_filters}) = &self.special { taboo_filters.clone()} else { unreachable!()};
for filter in filters_of_one_child {
taboo_list.insert(filter.clone());
}
let new_id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id: new_id,
parent: self.id,
depth: self.depth,
allow_heuristic_pricing : self.allow_heuristic_pricing,
old_obj_bound: parent_obj,
old_obj_heuristic: parent_partial,
old_obj_dual_center : parent_dual_center,
filters: self.filters.clone(),
special : Some(LDSBranch { taboo_filters : taboo_list})
}
}
pub fn create_lds_one_child(&self, parent_obj: f64, filter: Vec<BranchFilter>, parent_partial : bool, parent_dual_center : Option<(f64, DualStore)>) -> Self {
let mut new_filters = self.filters.clone();
new_filters.extend(filter);
let new_id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id: new_id,
parent: self.id,
depth: self.depth + 1,
old_obj_bound: parent_obj,
allow_heuristic_pricing : self.allow_heuristic_pricing,
old_obj_heuristic: parent_partial,
old_obj_dual_center : parent_dual_center,
filters: new_filters,
special : self.special.clone()
}
}
pub fn create_child(&self, parent_obj: f64, filter: Vec<BranchFilter>, parent_partial : bool, parent_dual_center : Option<(f64,DualStore)>) -> Self {
let mut new_filters = self.filters.clone();
new_filters.extend(filter);
let new_id = BRANCH_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
Branch {
id: new_id,
parent: self.id,
depth: self.depth + 1,
allow_heuristic_pricing : self.allow_heuristic_pricing,
old_obj_bound: parent_obj,
old_obj_heuristic: parent_partial,
old_obj_dual_center : parent_dual_center,
filters: new_filters,
special : None
}
}
}
#[derive(Debug, Clone)]
pub struct BranchGroup<BranchFilter, BranchGroupType>
where
BranchGroupType: Debug,
{
pub filters: Vec<Vec<BranchFilter>>,
pub branch_group_type: BranchGroupType,
}
impl<BranchFilter, BranchGroupType> BranchGroup<BranchFilter, BranchGroupType>
where
BranchGroupType: Debug,
{
pub fn new(filters : Vec<Vec<BranchFilter>>, branch_group_type: BranchGroupType) -> Self {
Self {
filters,
branch_group_type,
}
}
}