1use serde::{Deserialize, Serialize};
3
4use crate::I;
5
6pub type Cost = i32;
8
9pub type Score = i32;
11
12#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
15#[cfg_attr(feature = "clap", derive(clap::Args))]
16pub struct CostModel {
17 #[cfg_attr(feature = "clap", clap(long, default_value_t = 1, value_name = "COST"))]
21 pub sub: Cost,
22 #[cfg_attr(feature = "clap", clap(long, default_value_t = 0, value_name = "COST"))]
26 pub open: Cost,
27 #[cfg_attr(feature = "clap", clap(long, default_value_t = 1, value_name = "COST"))]
29 pub extend: Cost,
30}
31
32impl CostModel {
33 pub fn unit() -> Self {
34 Self {
35 sub: 1,
36 open: 0,
37 extend: 1,
38 }
39 }
40 pub fn is_unit(&self) -> bool {
41 self == &Self::unit()
42 }
43 pub fn linear(sub: Cost, indel: Cost) -> Self {
44 Self {
45 sub,
46 open: 0,
47 extend: indel,
48 }
49 }
50 pub fn is_linear(&self) -> bool {
51 self.open == 0
52 }
53 pub fn affine(sub: Cost, open: Cost, extend: Cost) -> Self {
54 Self { sub, open, extend }
55 }
56 pub fn is_affine(&self) -> bool {
57 self.open > 0
58 }
59
60 pub fn sub(&self) -> Cost {
62 self.sub
63 }
64 pub fn maybe_sub(&self) -> Option<Cost> {
66 Some(self.sub)
67 }
68 pub fn ins(&self, len: I) -> Cost {
70 self.open + len * self.extend
71 }
72 pub fn del(&self, len: I) -> Cost {
74 self.open + len * self.extend
75 }
76}
77
78#[derive(Debug, Eq, PartialEq, Clone, Copy)]
79pub struct ScoreModel {
80 pub r#match: Score,
82 pub sub: Score,
84 pub open: Score,
86 pub extend: Score,
88
89 pub factor: i32,
90}
91
92impl ScoreModel {
93 const OFFSET: i32 = 1;
94
95 pub fn from_costs(cm: CostModel) -> Self {
96 let factor;
97 if cm.sub > 2 && cm.extend > 1 {
98 factor = 1;
99 } else if cm.sub == 1 {
100 factor = 3;
101 } else {
102 factor = 2;
103 }
104
105 Self {
106 r#match: Self::OFFSET * 2,
107 sub: -cm.sub * factor + Self::OFFSET * 2,
109 open: -cm.open * factor,
111 extend: -cm.extend * factor + Self::OFFSET,
113 factor,
114 }
115 }
116
117 pub fn global_cost(&self, score: Score, a_len: usize, b_len: usize) -> Cost {
118 let path_len = (a_len + b_len) as i32;
119 let s = -score + path_len * Self::OFFSET;
120 s / self.factor
126 }
127}