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