use super::Edge;
use crate::types::CenterIdx;
use crate::{space::Point, PointCount};
use std::collections::VecDeque;
#[derive(Debug)]
pub(super) struct State<'a> {
pub center_of: Vec<Option<CenterIdx>>, pub max_flow: PointCount, reassign: Vec<Vec<VecDeque<&'a Point>>>, unassigned: Vec<VecDeque<&'a Point>>, pub next_to_non_private: Vec<Option<CenterIdx>>, pub number_of_covered_points: Vec<PointCount>, pub edge_present: Vec<Vec<bool>>, }
impl<'a> State<'a> {
pub fn reassign_pop(&mut self, c1: CenterIdx, c2: CenterIdx) -> Option<&'a Point> {
self.clean_reassign(c1, c2);
self.reassign[c1][c2].pop_front()
}
pub fn reassign_push(&mut self, c1: CenterIdx, c2: CenterIdx, p: &'a Point) {
self.reassign[c1][c2].push_back(p);
}
pub fn reassign_is_empty(&mut self, c1: CenterIdx, c2: CenterIdx) -> bool {
self.clean_reassign(c1, c2);
self.reassign[c1][c2].is_empty()
}
fn clean_reassign(&mut self, c1: CenterIdx, c2: CenterIdx) {
while !self.reassign[c1][c2].is_empty() {
let p = self.reassign[c1][c2].front().unwrap().idx();
if self.center_of[p].is_none()
|| self.center_of[p].unwrap() != c1
|| !self.edge_present[c2][p]
{
self.reassign[c1][c2].pop_front(); } else {
break;
}
}
}
pub fn unassigned_pop(&mut self, c: CenterIdx) -> Option<&'a Point> {
self.clean_unassigned(c);
self.unassigned[c].pop_front()
}
pub fn unassigned_push(&mut self, c: CenterIdx, p: &'a Point) {
self.unassigned[c].push_back(p);
}
pub fn unassigned_is_empty(&mut self, c: CenterIdx) -> bool {
self.clean_unassigned(c);
self.unassigned[c].is_empty()
}
fn clean_unassigned(&mut self, c: CenterIdx) {
while !self.unassigned[c].is_empty() {
let p = self.unassigned[c].front().unwrap().idx();
if self.center_of[p].is_some() || !self.edge_present[c][p] {
self.unassigned[c].pop_front(); } else {
break;
}
}
}
}
pub(super) fn initialize_state<'a>(
n: PointCount,
k: PointCount,
privacy_bound_zero: bool,
) -> State<'a> {
State {
center_of: vec![None; n], max_flow: 0,
reassign: (0..k)
.map(|_| (0..k).map(|_| VecDeque::new()).collect())
.collect(),
unassigned: (0..k).map(|_| VecDeque::new()).collect(),
next_to_non_private: (0..k)
.map(|l| if privacy_bound_zero { None } else { Some(l) })
.collect(), number_of_covered_points: vec![0; k],
edge_present: vec![vec!(false; n); k],
}
}
pub(super) fn add_edge<'a>(
e: Edge<'a>,
i: CenterIdx,
k: PointCount,
privacy_bound: PointCount,
state: &mut State<'a>,
) {
let c = e.left;
let x = e.right;
if c > i {
return;
}
debug_assert!(
!state.edge_present[c][x.idx()],
"Edge {:?} was present before",
e
);
state.edge_present[c][x.idx()] = true;
match state.center_of[x.idx()] {
None => {
state.unassigned_push(c, x);
}
Some(center_of_x) => {
state.reassign_push(center_of_x, c, x);
if state.next_to_non_private[center_of_x].is_none()
&& state.next_to_non_private[c].is_some()
{
state.next_to_non_private[center_of_x] = Some(c);
update_reachability(vec![center_of_x], k, state) }
}
}
augment_flow(k, privacy_bound, i, state); }
pub(super) fn remove_edge<'a>(
e: Edge<'a>,
i: CenterIdx,
k: PointCount,
privacy_bound: PointCount,
state: &mut State<'a>,
) {
let c = e.left;
let x = e.right;
if c > i {
return;
}
debug_assert!(state.edge_present[c][x.idx()], "Edge was present before");
state.edge_present[c][x.idx()] = false;
match state.center_of[x.idx()] {
None => {
rebuild_reachability(k, privacy_bound, state);
}
Some(center_of_x) => {
if center_of_x == c {
state.max_flow -= 1;
state.number_of_covered_points[c] -= 1;
state.center_of[x.idx()] = None;
rebuild_reachability(k, privacy_bound, state);
augment_flow(k, privacy_bound, i, state); } else {
rebuild_reachability(k, privacy_bound, state);
}
}
}
}
fn augment_flow(k: PointCount, privacy_bound: PointCount, i: CenterIdx, state: &mut State<'_>) {
let mut v = 0;
while v <= i {
if !state.unassigned_is_empty(v) && state.next_to_non_private[v].is_some() {
break;
}
v += 1;
}
if v == i + 1 {
return;
}
let mut x = state.unassigned_pop(v).unwrap();
debug_assert_eq!(state.center_of[x.idx()], None, "WAIT: p is not unassigned");
state.center_of[x.idx()] = Some(v); state.number_of_covered_points[v] += 1; state.max_flow += 1;
while state.number_of_covered_points[v] > privacy_bound {
let w = state.next_to_non_private[v].unwrap();
x = state.reassign_pop(v, w).unwrap();
debug_assert_eq!(
state.center_of[x.idx()],
Some(v),
"WAIT: p was not assigned to v!"
);
state.number_of_covered_points[v] -= 1;
state.center_of[x.idx()] = Some(w); state.reassign_push(w, v, x);
state.number_of_covered_points[w] += 1;
v = w;
}
rebuild_reachability(k, privacy_bound, state); }
fn rebuild_reachability(k: PointCount, privacy_bound: PointCount, state: &mut State) {
state.next_to_non_private = (0..k)
.map(|c| {
if state.number_of_covered_points[c] < privacy_bound {
Some(c)
} else {
None
}
})
.collect();
update_reachability(
(0..k)
.filter(|c| state.next_to_non_private[*c].is_some())
.collect(),
k,
state,
);
}
fn update_reachability(start_centers: Vec<CenterIdx>, k: PointCount, state: &mut State) {
let mut queue: VecDeque<CenterIdx> = VecDeque::with_capacity(k);
for c in start_centers {
queue.push_back(c);
}
while !queue.is_empty() {
let w = queue.pop_front().unwrap();
for v in 0..k {
if !state.reassign_is_empty(v, w) && state.next_to_non_private[v].is_none() {
state.next_to_non_private[v] = Some(w);
queue.push_back(v);
}
}
}
}