#![deny(missing_docs)]
use bit_set::BitSet;
use derive_more::{From, Into};
use event_simulation::{BorrowedSimulation, MultiSimulation, OwnedSimulation, SimulationInfo};
use indexmap::{IndexMap, IndexSet};
use thiserror::Error;
use std::{convert::Infallible, fmt::Display};
mod edit;
mod streams;
pub use edit::EditMultilinearInfo;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Into, From)]
pub struct Event(pub usize);
impl Display for Event {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "E{}", self.0)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Into, From)]
pub struct Aspect(pub usize);
impl Display for Aspect {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "C{}", self.0)
}
}
#[derive(Copy, Clone)]
pub struct Transition {
pub from: usize,
pub to: usize,
}
trait TransitionGetter {
type Opposite: TransitionGetter;
fn get(transition: &Transition) -> usize;
}
struct From;
impl TransitionGetter for From {
type Opposite = To;
#[inline]
fn get(transition: &Transition) -> usize {
transition.from
}
}
struct To;
impl TransitionGetter for To {
type Opposite = From;
#[inline]
fn get(transition: &Transition) -> usize {
transition.to
}
}
impl Transition {
#[inline]
fn value(value: usize) -> Self {
Self {
from: value,
to: value,
}
}
#[inline]
fn new(from: usize, to: usize) -> Self {
Self { from, to }
}
#[inline]
fn get<T: TransitionGetter>(&self) -> usize {
T::get(self)
}
pub fn is_change(&self) -> bool {
self.from != self.to
}
}
#[derive(Copy, Clone)]
pub struct Change {
aspect: Aspect,
transition: Transition,
}
impl Change {
pub fn condition(aspect: Aspect, value: usize) -> Self {
Self {
aspect,
transition: Transition::value(value),
}
}
pub fn transition(aspect: Aspect, from: usize, to: usize) -> Self {
Self {
aspect,
transition: Transition::new(from, to),
}
}
}
#[derive(Clone)]
struct AspectNode {
dependent_events: IndexSet<Event>,
changed_events: BitSet,
}
#[derive(Clone)]
pub struct EventNode {
changes: Vec<IndexMap<Aspect, Transition>>,
changed_events: BitSet,
}
impl EventNode {
pub fn iter(&self) -> impl Iterator<Item = impl Iterator<Item = (Aspect, Transition)>> {
self.changes.iter().map(|change| {
change
.iter()
.map(|(&aspect, &transition)| (aspect, transition))
})
}
}
impl EventNode {
#[inline]
fn action_index<T: TransitionGetter>(&self, state: &[usize]) -> Option<usize> {
fn check<T: TransitionGetter>(
change: &IndexMap<Aspect, Transition>,
state: &[usize],
) -> bool {
for (&aspect, &transition) in change {
if transition.get::<T>() != state[aspect.0] {
return false;
}
}
true
}
for (i, change) in self.changes.iter().enumerate() {
if check::<T>(change, state) {
return Some(i);
}
}
None
}
fn check_action<T: TransitionGetter>(&self, state: &[usize]) -> bool {
self.action_index::<T>(state).is_some()
}
unsafe fn invoke_action<T: TransitionGetter>(&self, state: &mut [usize]) {
let index = unsafe { self.action_index::<T>(state).unwrap_unchecked() };
for (&aspect, &transition) in &self.changes[index] {
state[aspect.0] = transition.get::<T::Opposite>();
}
}
}
#[derive(Default, Clone)]
pub struct MultilinearInfo {
events: Vec<EventNode>,
aspects: Vec<AspectNode>,
}
impl MultilinearInfo {
pub fn iter(&self) -> impl Iterator<Item = (Event, &EventNode)> {
self.events
.iter()
.enumerate()
.map(|(i, event_node)| (Event(i), event_node))
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct AspectValue {
aspect: Aspect,
value: usize,
}
#[derive(Clone)]
struct ChangeSet {
from: IndexSet<AspectValue>,
to: IndexSet<AspectValue>,
}
impl ChangeSet {
fn create(&mut self, map: &IndexMap<Aspect, Transition>) -> Self {
let mut from = IndexSet::new();
let mut to = IndexSet::new();
for (&aspect, &transition) in map {
let from_value = AspectValue {
aspect,
value: transition.from,
};
if !self.from.swap_remove(&from_value) {
from.insert(from_value);
}
let to_value = AspectValue {
aspect,
value: transition.to,
};
if !self.to.swap_remove(&to_value) {
to.insert(to_value);
}
}
Self { from, to }
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Error)]
pub enum InvalidChangeError {
#[error("Only one change per aspect is allowed for each event")]
DuplicateAspect,
#[error("Conflicting changes might cause ambiguous behavior")]
ConflictingChanges,
}
pub struct EventEdit<'a> {
index: usize,
info: &'a mut MultilinearInfo,
}
impl EventEdit<'_> {
pub fn event(self) -> Event {
Event(self.index)
}
pub fn add_change(&mut self, changes: &[Change]) -> Result<(), InvalidChangeError> {
let mut from = IndexSet::new();
let mut to = IndexSet::new();
let mut map = IndexMap::new();
for &Change { aspect, transition } in changes {
if map.insert(aspect, transition).is_some() {
return Err(InvalidChangeError::DuplicateAspect);
}
from.insert(AspectValue {
aspect,
value: transition.from,
});
to.insert(AspectValue {
aspect,
value: transition.to,
});
}
let new_changes = ChangeSet { from, to };
let node = unsafe { self.info.events.get_unchecked(self.index) };
for change in &node.changes {
let mut new_changes = new_changes.clone();
let changes = new_changes.create(change);
if !changes.from.iter().any(|changed_value| {
new_changes
.from
.iter()
.any(|new_value| changed_value.aspect == new_value.aspect)
}) || !changes.to.iter().any(|changed_value| {
new_changes
.to
.iter()
.any(|new_value| changed_value.aspect == new_value.aspect)
}) {
return Err(InvalidChangeError::ConflictingChanges);
}
}
for &aspect in map.keys() {
let aspect = &mut self.info.aspects[aspect.0];
aspect.changed_events.insert(self.index);
for &modify_event in &aspect.dependent_events {
self.info.events[modify_event.0]
.changed_events
.insert(self.index);
}
}
let node = unsafe { self.info.events.get_unchecked_mut(self.index) };
for (&aspect, transition) in &map {
let aspect = &mut self.info.aspects[aspect.0];
if transition.is_change() {
aspect.dependent_events.insert(Event(self.index));
}
node.changed_events.union_with(&aspect.changed_events);
}
node.changes.push(map);
Ok(())
}
pub fn with_change(mut self, changes: &[Change]) -> Result<Self, InvalidChangeError> {
self.add_change(changes)?;
Ok(self)
}
}
impl MultilinearInfo {
pub fn new() -> Self {
Self::default()
}
pub fn add_aspect(&mut self) -> Aspect {
let index = self.aspects.len();
self.aspects.push(AspectNode {
dependent_events: IndexSet::new(),
changed_events: BitSet::new(),
});
Aspect(index)
}
pub fn add_event(&mut self) -> EventEdit<'_> {
let index = self.events.len();
self.events.push(EventNode {
changes: Vec::new(),
changed_events: BitSet::new(),
});
EventEdit { index, info: self }
}
#[inline]
pub fn edit_event(&mut self, Event(index): Event) -> Option<EventEdit<'_>> {
if index > self.events.len() {
return None;
}
Some(unsafe { self.edit_event_unchecked(Event(index)) })
}
pub unsafe fn edit_event_unchecked(&mut self, Event(index): Event) -> EventEdit<'_> {
EventEdit { index, info: self }
}
}
#[derive(Clone)]
pub struct MultilinearState {
values: Vec<usize>,
callables: BitSet,
revertables: BitSet,
}
impl MultilinearState {
fn from_values(info: &MultilinearInfo, values: Vec<usize>) -> Self {
let mut callables = BitSet::new();
let mut revertables = BitSet::new();
for (index, event) in info.events.iter().enumerate() {
if event.check_action::<From>(&values) {
callables.insert(index);
}
if event.check_action::<To>(&values) {
revertables.insert(index);
}
}
Self {
values,
callables,
revertables,
}
}
fn update_events(&mut self, event: &EventNode, info: &MultilinearInfo) {
for event in &event.changed_events {
let event_node = &info.events[event];
if event_node.check_action::<From>(&self.values) {
self.callables.insert(event);
} else {
self.callables.remove(event);
}
if event_node.check_action::<To>(&self.values) {
self.revertables.insert(event);
} else {
self.revertables.remove(event);
}
}
}
}
pub struct EventContainer<'a> {
iter: bit_set::Iter<'a, u32>,
}
impl Iterator for EventContainer<'_> {
type Item = Event;
fn next(&mut self) -> Option<Event> {
self.iter.next().map(Event)
}
}
impl SimulationInfo for MultilinearInfo {
type StateLoadingError = Infallible;
type State = MultilinearState;
type AccessData = [usize];
type LoadData = Vec<usize>;
type Event = Event;
type EventContainer<'a>
= EventContainer<'a>
where
Self: 'a;
#[inline]
fn default_state(&self) -> MultilinearState {
MultilinearState::from_values(self, vec![0; self.aspects.len()])
}
#[inline]
fn load_state(&self, data: Vec<usize>) -> Result<MultilinearState, Infallible> {
Ok(MultilinearState::from_values(self, data))
}
#[inline]
unsafe fn clone_state(&self, state: &MultilinearState) -> MultilinearState {
state.clone()
}
#[inline]
unsafe fn data<'a>(&self, state: &'a MultilinearState) -> &'a [usize] {
&state.values
}
#[inline]
fn callables(state: &MultilinearState) -> EventContainer<'_> {
EventContainer {
iter: state.callables.iter(),
}
}
#[inline]
fn callable(state: &MultilinearState, event: Event) -> bool {
state.callables.contains(event.0)
}
unsafe fn call(&self, state: &mut MultilinearState, event: Event) {
let event = &self.events[event.0];
unsafe { event.invoke_action::<From>(&mut state.values) };
state.update_events(event, self);
}
#[inline]
fn revertables(state: &MultilinearState) -> EventContainer<'_> {
EventContainer {
iter: state.revertables.iter(),
}
}
#[inline]
fn revertable(state: &MultilinearState, event: Event) -> bool {
state.revertables.contains(event.0)
}
unsafe fn revert(&self, state: &mut MultilinearState, event: Event) {
let event = &self.events[event.0];
unsafe { event.invoke_action::<To>(&mut state.values) };
state.update_events(event, self);
}
}
pub type MultilinearSimulation = OwnedSimulation<MultilinearInfo>;
pub type BorrowedMultilinearSimulation<'a> = BorrowedSimulation<'a, MultilinearInfo>;
pub type MultiMultilinearSimulation = MultiSimulation<MultilinearInfo>;