Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -461,13 +461,7 @@ impl<Var: IntegerVariable + 'static, const SYNCHRONISE: bool> Propagator
//
// However, this could mean that we potentially enqueue even though the time-table is empty
// after backtracking but has not been recalculated yet.
let result = should_enqueue(
&self.parameters,
&self.updatable_structures,
&updated_task,
context.domains(),
self.time_table.is_empty(),
);
let result = should_enqueue(&self.updatable_structures, &updated_task, context.domains());

// If there is a task which now has a mandatory part then we store it and process it when
// the `propagate` method is called
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,13 +488,7 @@ impl<Var: IntegerVariable + 'static + Debug, const SYNCHRONISE: bool> Propagator
//
// However, this could mean that we potentially enqueue even though the time-table is empty
// after backtracking but has not been recalculated yet.
let result = should_enqueue(
&self.parameters,
&self.updatable_structures,
&updated_task,
context.domains(),
self.time_table.is_empty(),
);
let result = should_enqueue(&self.updatable_structures, &updated_task, context.domains());

// If there is a task which now has a mandatory part then we store it and process it when
// the `propagate` method is called
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ pub(crate) struct Event<Var> {
/// Computer Science and Software Engineering, 2011.
#[derive(Debug, Clone)]
pub struct TimeTableOverIntervalPropagator<Var> {
/// Stores whether the time-table is empty
is_time_table_empty: bool,
/// Stores the input parameters to the cumulative constraint
parameters: CumulativeParameters<Var>,
/// Stores structures which change during the search; used to store the bounds
Expand Down Expand Up @@ -97,7 +95,6 @@ impl<Var: IntegerVariable + 'static> TimeTableOverIntervalPropagator<Var> {
let updatable_structures = UpdatableStructures::new(&parameters);

TimeTableOverIntervalPropagator {
is_time_table_empty: true,
parameters,
updatable_structures,
constraint_tag,
Expand Down Expand Up @@ -159,7 +156,6 @@ impl<Var: IntegerVariable + 'static> Propagator for TimeTableOverIntervalPropaga
&self.parameters,
self.inference_code.as_ref().unwrap(),
)?;
self.is_time_table_empty = time_table.is_empty();
// No error has been found -> Check for updates (i.e. go over all profiles and all tasks and
// check whether an update can take place)
propagate_based_on_timetable(
Expand All @@ -183,18 +179,8 @@ impl<Var: IntegerVariable + 'static> Propagator for TimeTableOverIntervalPropaga
event: OpaqueDomainEvent,
) -> EnqueueDecision {
let updated_task = Rc::clone(&self.parameters.tasks[local_id.unpack() as usize]);
// Note that it could be the case that `is_time_table_empty` is inaccurate here since it
// wasn't updated in `synchronise`; however, `synchronise` will only remove profiles
// meaning that `is_time_table_empty` will always return `false` when it is not
// empty and it might return `false` even when the time-table is not empty *but* it
// will never return `true` when the time-table is not empty.
let result = should_enqueue(
&self.parameters,
&self.updatable_structures,
&updated_task,
context.domains(),
self.is_time_table_empty,
);

let result = should_enqueue(&self.updatable_structures, &updated_task, context.domains());

update_bounds_task(
context.domains(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ use crate::propagators::cumulative::time_table::propagation_handler::create_conf
/// Computer Science and Software Engineering, 2011.
#[derive(Debug, Clone)]
pub struct TimeTablePerPointPropagator<Var> {
/// Stores whether the time-table is empty
is_time_table_empty: bool,
/// Stores the input parameters to the cumulative constraint
parameters: CumulativeParameters<Var>,
/// Stores structures which change during the search; used to store the bounds
Expand Down Expand Up @@ -89,7 +87,6 @@ impl<Var: IntegerVariable + 'static> TimeTablePerPointPropagator<Var> {
let updatable_structures = UpdatableStructures::new(&parameters);

TimeTablePerPointPropagator {
is_time_table_empty: true,
parameters,
updatable_structures,
constraint_tag,
Expand Down Expand Up @@ -149,7 +146,6 @@ impl<Var: IntegerVariable + 'static> Propagator for TimeTablePerPointPropagator<
self.inference_code.as_ref().unwrap(),
&self.parameters,
)?;
self.is_time_table_empty = time_table.is_empty();
// No error has been found -> Check for updates (i.e. go over all profiles and all tasks and
// check whether an update can take place)
propagate_based_on_timetable(
Expand All @@ -173,18 +169,8 @@ impl<Var: IntegerVariable + 'static> Propagator for TimeTablePerPointPropagator<
event: OpaqueDomainEvent,
) -> EnqueueDecision {
let updated_task = Rc::clone(&self.parameters.tasks[local_id.unpack() as usize]);
// Note that it could be the case that `is_time_table_empty` is inaccurate here since it
// wasn't updated in `synchronise`; however, `synchronise` will only remove profiles
// meaning that `is_time_table_empty` will always return `false` when it is not
// empty and it might return `false` even when the time-table is not empty *but* it
// will never return `true` when the time-table is not empty.
let result = should_enqueue(
&self.parameters,
&self.updatable_structures,
&updated_task,
context.domains(),
self.is_time_table_empty,
);

let result = should_enqueue(&self.updatable_structures, &updated_task, context.domains());

// Note that the non-incremental proapgator does not make use of `result.updated` since it
// propagates from scratch anyways
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ pub(crate) struct ShouldEnqueueResult<Var> {
/// such task exists). This method should be called in the
/// [`ConstraintProgrammingPropagator::notify`] method.
pub(crate) fn should_enqueue<Var: IntegerVariable + 'static>(
parameters: &CumulativeParameters<Var>,
updatable_structures: &UpdatableStructures<Var>,
updated_task: &Rc<Task<Var>>,
mut context: Domains,
empty_time_table: bool,
) -> ShouldEnqueueResult<Var> {
pumpkin_assert_extreme!(
context.lower_bound(&updated_task.start_variable)
Expand Down Expand Up @@ -79,28 +77,8 @@ pub(crate) fn should_enqueue<Var: IntegerVariable + 'static>(
});
}

result.decision = if parameters.options.allow_holes_in_domain {
// If there are updates then propagations might occur due to new mandatory parts being
// added. However, if there are no updates then because we allow holes in the domain, no
// updates can occur so we can skip propagation!
if updatable_structures.has_updates() || result.update.is_some() {
EnqueueDecision::Enqueue
} else {
EnqueueDecision::Skip
}
} else {
// If the time-table is empty and we have not received any updates (e.g. no mandatory parts
// have been introduced since the last propagation) then we can determine that no
// propagation will take place. It is not sufficient to check whether there have
// been no updates since it could be the case that a task which has been updated can
// now propagate due to an existing profile (this is due to the fact that we only
// propagate bounds and (currently) do not create holes in the domain!).
if !empty_time_table || updatable_structures.has_updates() || result.update.is_some() {
EnqueueDecision::Enqueue
} else {
EnqueueDecision::Skip
}
};
result.decision = EnqueueDecision::Enqueue;

result
}

Expand Down Expand Up @@ -201,7 +179,7 @@ fn debug_check_whether_profiles_are_maximal_and_sorted<'a, Var: IntegerVariable
pub(crate) fn propagate_based_on_timetable<'a, Var: IntegerVariable + 'static>(
context: &mut PropagationContext,
inference_code: &InferenceCode,
time_table: impl Iterator<Item = &'a ResourceProfile<Var>> + Clone,
time_table: impl ExactSizeIterator<Item = &'a ResourceProfile<Var>> + Clone,
parameters: &CumulativeParameters<Var>,
updatable_structures: &mut UpdatableStructures<Var>,
) -> PropagationStatusCP {
Expand All @@ -223,6 +201,11 @@ pub(crate) fn propagate_based_on_timetable<'a, Var: IntegerVariable + 'static>(
"All of the fixed tasks should be fixed at this point"
);

if time_table.len() == 0 {
// No propagation can take place since the time-table is empty
return Ok(());
}

if parameters.options.generate_sequence {
propagate_sequence_of_profiles(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ impl<Var: IntegerVariable + 'static> UpdatableStructures<Var> {
}
}

/// Returns whether there are any updates stored which have not been processed
pub(crate) fn has_updates(&self) -> bool {
!self.updated_tasks.is_empty()
}

/// Returns the next updated task and removes it from the updated list
pub(crate) fn pop_next_updated_task(&mut self) -> Option<Rc<Task<Var>>> {
if self.updated_tasks.is_empty() {
Expand Down
Loading