use std::{ops::Sub, slice};
use tuple::A2;
use crate::{Interval, LimitValues};
pub trait State {
fn is_equivalent(&self, other: &Self) -> bool;
}
pub trait TransitionSystem<S, A, C, DC>
where
C: Ord + LimitValues + Sub<C, Output = DC> + Copy,
{
fn actions_from(&self, state: &S) -> slice::Iter<A>;
fn transition(&self, state: &S, action: &A) -> S;
fn transition_cost(&self, state: &S, action: &A) -> DC;
fn reverse_actions_from(&self, state: &S) -> slice::Iter<A>;
fn reverse_transition(&self, state: &S, action: &A) -> S;
fn reverse_transition_cost(&self, state: &S, action: &A) -> DC;
fn can_wait_at(&self, state: &S) -> bool;
fn conflict(&self, moves: A2<&Move<S, A, C, DC>>) -> bool;
}
pub trait ActionCallback<Action> {
fn apply(&mut self, action: Action);
}
impl<Action, X: FnMut(Action)> ActionCallback<Action> for X {
fn apply(&mut self, action: Action) {
self(action)
}
}
pub struct Task<S, C>
where
S: State + Eq + Clone,
C: Copy,
{
pub initial_state: S,
pub goal_state: S,
pub initial_cost: C,
}
impl<S, C> Task<S, C>
where
S: State + Eq + Clone,
C: Copy,
{
pub fn new(initial_state: S, goal_state: S, initial_cost: C) -> Self {
Self {
initial_state,
goal_state,
initial_cost,
}
}
pub fn is_goal_state(&self, state: &S) -> bool {
state.is_equivalent(&self.goal_state)
}
pub fn reverse(&self) -> Self {
Self {
initial_state: self.goal_state.clone(),
goal_state: self.initial_state.clone(),
initial_cost: self.initial_cost,
}
}
}
#[derive(Debug, Clone)]
pub struct Move<S, A, C, DC>
where
C: Ord + LimitValues + Sub<C, Output = DC> + Copy,
{
pub agent: usize,
pub from: S,
pub to: S,
pub action: Option<A>,
pub interval: Interval<C, DC>,
}
impl<S, A, C, DC> Move<S, A, C, DC>
where
C: Ord + LimitValues + Sub<C, Output = DC> + Copy,
{
pub fn new(agent: usize, from: S, to: S, action: Option<A>, interval: Interval<C, DC>) -> Self {
Self {
agent,
from,
to,
action,
interval,
}
}
}