use std::cmp;
use std::fmt::Debug;
use std::hash::Hash;
use crate::{Measure, SeqPair};
pub mod archetype;
pub trait Operation<T>: Clone + Debug + Eq + Hash {
fn backtrack(
&self,
seq_pair: &SeqPair<T>,
source_idx: usize,
target_idx: usize,
) -> Option<(usize, usize)>;
fn cost(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Option<usize>
where
T: Eq;
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct IndexedOperation<O>
where
O: Debug,
{
operation: O,
source_idx: usize,
target_idx: usize,
}
impl<O> IndexedOperation<O>
where
O: Debug,
{
pub fn new(operation: O, source_idx: usize, target_idx: usize) -> Self {
IndexedOperation {
operation,
source_idx,
target_idx,
}
}
pub fn operation(&self) -> &O {
&self.operation
}
pub fn source_idx(&self) -> usize {
self.source_idx
}
pub fn target_idx(&self) -> usize {
self.target_idx
}
}
pub(crate) trait Backtrack<T> {
type Operation: Operation<T>;
fn backtrack(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Option<Self::Operation>
where
T: Eq;
fn backtracks(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Vec<Self::Operation>
where
T: Eq;
}
impl<M, T> Backtrack<T> for M
where
M: Measure<T>,
{
type Operation = M::Operation;
fn backtrack(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Option<Self::Operation>
where
T: Eq,
{
for op in self.operations() {
if let Some(cost) = op.cost(seq_pair, cost_matrix, source_idx, target_idx) {
if cost == cost_matrix[source_idx][target_idx] {
return Some(op.clone());
}
}
}
None
}
fn backtracks(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Vec<Self::Operation>
where
T: Eq,
{
let mut ops = Vec::new();
for op in self.operations() {
if let Some(cost) = op.cost(seq_pair, cost_matrix, source_idx, target_idx) {
if cost == cost_matrix[source_idx][target_idx] {
ops.push(op.clone());
}
}
}
ops
}
}
pub(crate) trait BestCost<T> {
type Operation: Operation<T>;
fn best_cost(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Option<usize>
where
T: Eq;
}
impl<M, T> BestCost<T> for M
where
M: Measure<T>,
{
type Operation = M::Operation;
fn best_cost(
&self,
seq_pair: &SeqPair<T>,
cost_matrix: &[Vec<usize>],
source_idx: usize,
target_idx: usize,
) -> Option<usize>
where
T: Eq,
{
let mut best = None;
for op in self.operations() {
if let Some(cost) = op.cost(seq_pair, cost_matrix, source_idx, target_idx) {
best = best
.map(|best_cost| cmp::min(cost, best_cost))
.or(Some(cost))
}
}
best
}
}