Skip to main content

chai/contexts/
default.rs

1//! 数据结构的定义
2
3use crate::config::{基本信息, 安排, 安排描述, 广义码位, 简码模式, 简码规则, 配置};
4use crate::contexts::{
5    上下文, 合并初始决策, 展开变量, 应用生成器, 拓扑排序, 条件, 条件安排, 补充存在性条件
6};
7use crate::encoders::default::简码数量;
8use crate::interfaces::默认输入;
9use crate::optimizers::决策;
10use crate::{
11    formatted_local_now, 元素, 元素图, 原始当量信息, 原始键位分布信息, 可编码对象, 最大元素数量, 最大按键组合长度, 最大词长, 棱镜, 码表项, 编码, 编码信息, 键
12};
13use crate::{最大元素编码长度, 错误};
14use indexmap::IndexMap;
15use regex::Regex;
16use rustc_hash::FxHashMap;
17use serde_yaml::to_string;
18
19/// 将用户提供的输入转换为内部数据结构,并提供了一些实用的方法
20#[derive(Debug, Clone)]
21pub struct 默认上下文 {
22    pub 配置: 配置,
23    pub 词列表: Vec<可编码对象>,
24    pub 键位分布信息: 原始键位分布信息,
25    pub 当量信息: 原始当量信息,
26    pub 初始决策: 默认决策,
27    pub 决策空间: 默认决策空间,
28    pub 棱镜: 棱镜,
29    pub 选择键: Vec<键>,
30    pub 元素图: 元素图,
31    pub 保存原始决策空间: IndexMap<String, Vec<安排描述>>,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum 默认安排 {
36    键位([(元素, usize); 最大元素编码长度]),
37    归并(元素),
38    未选取,
39}
40
41impl 默认安排 {
42    pub fn from(原始安排: &安排, 棱镜: &棱镜, 元素: &String) -> Result<Self, 错误> {
43        match 原始安排 {
44            安排::Basic(_) | 安排::Advanced(_) => {
45                let 归一化映射值 = 原始安排.normalize();
46                let mut 安排 = [(0, 0); 最大元素编码长度];
47                for (序号, 映射键) in 归一化映射值.iter().enumerate() {
48                    if let 广义码位::Ascii(x) = 映射键 {
49                        if let Some(键) = 棱镜.键转数字.get(x) {
50                            安排[序号] = (*as usize, 0);
51                        } else {
52                            return Err(
53                                format!("元素 {元素} 的编码中的字符 {x} 并不在字母表中").into()
54                            );
55                        }
56                    } else if let 广义码位::Reference { element, index } = 映射键 {
57                        if let Some(元素编号) = 棱镜.元素转数字.get(element) {
58                            安排[序号] = (*元素编号, *index);
59                        } else {
60                            return Err(format!(
61                                "元素 {元素} 的编码中的引用元素 {element} 并不存在"
62                            )
63                            .into());
64                        }
65                    } else {
66                        return Err(format!("元素 {元素} 的编码格式不正确").into());
67                    }
68                }
69                Ok(默认安排::键位(安排))
70            }
71            安排::Grouped { element } => {
72                if let Some(元素编号) = 棱镜.元素转数字.get(element) {
73                    Ok(默认安排::归并(*元素编号))
74                } else {
75                    Err(format!("元素 {元素} 的编码中的引用元素 {element} 并不存在").into())
76                }
77            }
78            安排::Unused(_) => Ok(默认安排::未选取),
79        }
80    }
81
82    pub fn to(&self, 棱镜: &棱镜) -> 安排 {
83        match self {
84            默认安排::归并(引用元素) => 安排::Grouped {
85                element: 棱镜.数字转元素[引用元素].clone(),
86            },
87            默认安排::键位(取值) => {
88                let mut 列表 = vec![];
89                for (元素, 位置) in 取值 {
90                    if *元素 == 0 {
91                        break;
92                    } else if 棱镜.数字转键.contains_key(&(*元素 as u64)) {
93                        let 键 = 棱镜.数字转键[&(*元素 as u64)];
94                        列表.push(广义码位::Ascii(键));
95                    } else {
96                        let 元素名称 = 棱镜.数字转元素[元素].clone();
97                        列表.push(广义码位::Reference {
98                            element: 元素名称,
99                            index: *位置,
100                        });
101                    }
102                }
103                if 列表.iter().all(|x| matches!(x, 广义码位::Ascii(_))) {
104                    安排::Basic(
105                        列表
106                            .iter()
107                            .map(|x| match x {
108                                广义码位::Ascii(c) => *c,
109                                _ => unreachable!(),
110                            })
111                            .collect(),
112                    )
113                } else {
114                    安排::Advanced(列表)
115                }
116            }
117            默认安排::未选取 => 安排::Unused(()),
118        }
119    }
120}
121
122type 默认条件安排 = 条件安排<默认安排>;
123
124#[derive(Debug, Clone)]
125pub struct 默认决策 {
126    pub 元素: Vec<默认安排>,
127}
128
129impl 默认决策 {
130    pub fn 允许(&self, 条件安排: &默认条件安排) -> bool {
131        for 条件 in &条件安排.条件 {
132            if 条件.谓词 != (self.元素[条件.元素] == 条件.值) {
133                return false;
134            }
135        }
136        return true;
137    }
138}
139
140#[derive(Debug, Clone)]
141pub struct 默认决策变化 {
142    pub 增加元素: Vec<元素>,
143    pub 减少元素: Vec<元素>,
144    pub 移动元素: Vec<元素>,
145}
146
147impl 默认决策变化 {
148    pub fn 新建(
149        增加元素: Vec<元素>, 减少元素: Vec<元素>, 移动元素: Vec<元素>
150    ) -> Self {
151        Self {
152            增加元素,
153            减少元素,
154            移动元素,
155        }
156    }
157
158    pub fn 不变() -> Self {
159        Self::新建(vec![], vec![], vec![])
160    }
161}
162
163impl 决策 for 默认决策 {
164    type 变化 = 默认决策变化;
165    fn 除法(旧变化: &Self::变化, 新变化: &Self::变化) -> Self::变化 {
166        let mut res = 默认决策变化 {
167            增加元素: 旧变化.减少元素.clone(),
168            减少元素: 旧变化.增加元素.clone(),
169            移动元素: 旧变化.移动元素.clone(),
170        };
171        for 元素 in &新变化.增加元素 {
172            res.增加元素.push(*元素);
173        }
174        for 元素 in &新变化.减少元素 {
175            res.减少元素.push(*元素);
176        }
177        for 元素 in &新变化.移动元素 {
178            res.移动元素.push(*元素);
179        }
180        res
181    }
182}
183
184#[derive(Debug, Clone)]
185pub struct 默认决策空间 {
186    pub 元素: Vec<Vec<默认条件安排>>,
187}
188
189impl 上下文 for 默认上下文 {
190    type 决策 = 默认决策;
191    fn 序列化(&self, 决策: &Self::决策) -> String {
192        let mut 新配置 = self.配置.clone();
193        let mut info = 新配置.info.clone().unwrap_or(基本信息 {
194            name: None,
195            description: None,
196            version: None,
197            author: None,
198        });
199        info.version = Some(formatted_local_now());
200        新配置.info = Some(info);
201        let mut mapping = IndexMap::new();
202        for (i, 安排) in 决策.元素.iter().enumerate() {
203            if i < self.棱镜.进制 as usize {
204                continue;
205            }
206            let 元素名称 = self.棱镜.数字转元素[&i].clone();
207            let mapped = 安排.to(&self.棱镜);
208            if mapped != 安排::Unused(()) {
209                mapping.insert(元素名称, mapped);
210            }
211        }
212        新配置.form.mapping = mapping;
213        新配置.form.mapping_space = Some(self.保存原始决策空间.clone());
214        to_string(&新配置).unwrap()
215    }
216}
217
218impl 默认上下文 {
219    pub fn 新建(输入: 默认输入) -> Result<Self, 错误> {
220        let (初始决策, 决策空间, 元素图, 选择键, 棱镜, 保存原始决策空间) =
221            Self::构建棱镜和初始决策(&输入.配置)?;
222        let 最大码长 = 输入.配置.encoder.max_length;
223        let 词列表 = 棱镜.预处理词列表(输入.词列表, 最大码长)?;
224        Ok(Self {
225            配置: 输入.配置,
226            词列表,
227            键位分布信息: 输入.原始键位分布信息.clone(),
228            当量信息: 输入.原始当量信息.clone(),
229            初始决策,
230            棱镜,
231            选择键,
232            决策空间,
233            元素图,
234            保存原始决策空间,
235        })
236    }
237
238    pub fn 构建棱镜和初始决策(
239        配置: &配置,
240    ) -> Result<(默认决策, 默认决策空间, 元素图, Vec<键>, 棱镜, IndexMap<String, Vec<安排描述>>), 错误> {
241        // 1. 构建初始决策和决策空间
242        let mut 原始决策 = 配置.form.mapping.clone();
243        let mut 原始决策空间 = 配置.form.mapping_space.clone().unwrap_or_default();
244        let 原始变量映射 = 配置.form.mapping_variables.clone().unwrap_or_default();
245        let 原始生成器列表 = 配置.form.mapping_generators.clone().unwrap_or_default();
246        // 合并初始决策
247        合并初始决策(&mut 原始决策空间, &mut 原始决策);
248        // 在合并之后克隆一份原始决策空间,以便后续使用
249        let 保存原始决策空间 = 原始决策空间.clone();
250        // 应用生成器
251        应用生成器(&mut 原始决策空间, &原始生成器列表);
252        // 展开变量
253        展开变量(&mut 原始决策空间, &原始变量映射);
254        // 补充存在性条件
255        补充存在性条件(&mut 原始决策空间);
256        // 拓扑排序
257        let (排序后元素名称, 原始元素图) = 拓扑排序(&原始决策空间)?;
258
259        // 2. 构建棱镜
260        let mut 键转数字: FxHashMap<char, 键> = FxHashMap::default();
261        let mut 数字转键: FxHashMap<键, char> = FxHashMap::default();
262        let mut 元素转数字: FxHashMap<String, 元素> = FxHashMap::default();
263        let mut 数字转元素: FxHashMap<元素, String> = FxHashMap::default();
264        let 原始选择键 = 配置.encoder.select_keys.clone().unwrap_or(vec!['_']);
265        if 原始选择键.is_empty() {
266            return Err("选择键不能为空!".into());
267        }
268        for in 配置.form.alphabet.chars().chain(原始选择键.iter().cloned()) {
269            if 键转数字.contains_key(&键) {
270                return Err("编码键有重复!".into());
271            };
272            let 键编号 = 键转数字.len() + 1;
273            键转数字.insert(键, 键编号 as 键);
274            数字转键.insert(键编号 as 键, 键);
275            元素转数字.insert(键.to_string(), 键编号);
276            数字转元素.insert(键编号, 键.to_string());
277        }
278        let 进制 = 键转数字.len() as 键 + 1;
279        let 选择键 = 原始选择键.iter().map(|k| 键转数字[k]).collect();
280        for 元素名称 in &排序后元素名称 {
281            let 元素编号 = 元素转数字.len() + 1;
282            元素转数字.insert(元素名称.clone(), 元素编号);
283            数字转元素.insert(元素编号, 元素名称.clone());
284        }
285        let mut 棱镜 = 棱镜 {
286            键转数字,
287            数字转键,
288            元素转数字,
289            数字转元素,
290            进制,
291            可选元素位图索引: FxHashMap::default(),
292        };
293
294        // 3. 使用棱镜构建初始决策和决策空间
295        let (初始决策, 决策空间, 元素图) = Self::构建初始决策和决策空间(
296            &棱镜,
297            &排序后元素名称,
298            &原始决策,
299            &原始决策空间,
300            &原始元素图,
301        )?;
302
303        // 4. 确定可选元素(安排可能为 未选取 的元素)并建立紧凑位图索引
304        for (元素编号, 安排列表) in 决策空间.元素.iter().enumerate() {
305            if 安排列表.iter().any(|ca| ca.安排 == 默认安排::未选取) {
306                let 位图索引 = 棱镜.可选元素位图索引.len();
307                棱镜.可选元素位图索引.insert(元素编号, 位图索引);
308            }
309        }
310        if 棱镜.可选元素位图索引.len() > 最大元素数量 {
311            return Err(format!(
312                "可选元素数量 {} 超过了最大可选元素数量 {}",
313                棱镜.可选元素位图索引.len(),
314                最大元素数量
315            )
316            .into());
317        }
318
319        Ok((初始决策, 决策空间, 元素图, 选择键, 棱镜, 保存原始决策空间))
320    }
321
322    pub fn 构建初始决策和决策空间(
323        棱镜: &棱镜,
324        排序后元素名称: &Vec<String>,
325        原始决策: &IndexMap<String, 安排>,
326        原始决策空间: &IndexMap<String, Vec<安排描述>>,
327        原始元素图: &FxHashMap<String, Vec<String>>,
328    ) -> Result<(默认决策, 默认决策空间, 元素图), 错误> {
329        // 3. 使用棱镜构建初始决策和决策空间
330        let mut 初始决策 = 默认决策 { 元素: vec![] };
331        let mut 决策空间 = 默认决策空间 { 元素: vec![] };
332        let mut 元素图: FxHashMap<元素, Vec<_>> = FxHashMap::default();
333        for k in 0..棱镜.进制 {
334            let 安排 = 默认安排::键位([(k as usize, 0), (0, 0), (0, 0), (0, 0)]);
335            let 条件安排 = 默认条件安排 {
336                安排: 安排.clone(),
337                条件: vec![],
338                分数: 0.0,
339            };
340            初始决策.元素.push(安排);
341            决策空间.元素.push(vec![条件安排]);
342        }
343        for 元素名称 in 排序后元素名称 {
344            let 原始安排 = &原始决策[元素名称];
345            let mut 安排列表 = vec![];
346            let 原始安排列表 = 原始决策空间[元素名称].clone();
347            let 编号 = 棱镜.元素转数字[元素名称];
348            let 安排 = 默认安排::from(原始安排, &棱镜, 元素名称)?;
349            for 其余原始安排 in &原始安排列表 {
350                let mut 条件列表 = vec![];
351                for c in 其余原始安排.condition.clone().unwrap_or_default() {
352                    if let Some(条件元素) = 棱镜.元素转数字.get(&c.element) {
353                        条件列表.push(条件 {
354                            元素: *条件元素,
355                            谓词: c.op == "是",
356                            值: 默认安排::from(&c.value, &棱镜, &c.element)?,
357                        });
358                    }
359                }
360                let 条件字根安排 = 默认条件安排 {
361                    安排: 默认安排::from(&其余原始安排.value, &棱镜, 元素名称)?,
362                    条件: 条件列表,
363                    分数: 其余原始安排.score,
364                };
365                安排列表.push(条件字根安排);
366            }
367            初始决策.元素.push(安排);
368            决策空间.元素.push(安排列表);
369            let 下游 = 原始元素图.get(元素名称).unwrap();
370            let 下游编号: Vec<_> = 下游.iter().map(|x| 棱镜.元素转数字[x]).collect();
371            元素图.insert(编号, 下游编号);
372        }
373        Ok((初始决策, 决策空间, 元素图))
374    }
375
376    pub fn 生成码表(&self, 编码结果: &[编码信息]) -> Vec<码表项> {
377        let mut 码表: Vec<(usize, 码表项)> = Vec::new();
378        let 转编码 = |code: 编码| self.棱镜.数字转编码(code).iter().collect();
379        for (序号, 可编码对象) in self.词列表.iter().enumerate() {
380            let 码表项 = 码表项 {
381                词: 可编码对象.词.clone(),
382                全码: 转编码(编码结果[序号].全码.原始编码),
383                全码排名: 编码结果[序号].全码.原始编码候选位置,
384                简码: 转编码(编码结果[序号].简码.原始编码),
385                简码排名: 编码结果[序号].简码.原始编码候选位置,
386            };
387            码表.push((可编码对象.原始顺序, 码表项));
388        }
389        码表.sort_by_key(|x| x.0);
390        码表.into_iter().map(|x| x.1).collect()
391    }
392
393    /// 将编码空间内所有的编码组合预先计算好是否能自动上屏
394    /// 按照这个字符串所对应的整数为下标,存储到一个大数组中
395    pub fn 预处理自动上屏(&self) -> Result<Vec<bool>, 错误> {
396        let mut result: Vec<bool> = vec![];
397        let encoder = &self.配置.encoder;
398        let mut re: Option<Regex> = None;
399        if let Some(pattern) = &encoder.auto_select_pattern {
400            let re_or_error = Regex::new(pattern);
401            if let Ok(regex) = re_or_error {
402                re = Some(regex);
403            } else {
404                return Err(format!("正则表达式 {pattern} 无法解析").into());
405            }
406        }
407        for code in 0..self.线性表长度() {
408            let chars = self.棱镜.数字转编码(code as u64);
409            let string: String = chars.iter().collect();
410            let is_matched = if let Some(re) = &re {
411                re.is_match(&string)
412            } else if let Some(length) = encoder.auto_select_length {
413                chars.len() >= length
414            } else {
415                true
416            };
417            let is_max_length = chars.len() == encoder.max_length;
418            result.push(is_matched || is_max_length);
419        }
420        Ok(result)
421    }
422
423    pub fn 预处理简码规则(
424        &self,
425        schemes: &Vec<简码模式>,
426    ) -> Result<Vec<简码数量>, 错误> {
427        let mut compiled_schemes = Vec::new();
428        for scheme in schemes {
429            let prefix = scheme.prefix;
430            let count = scheme.count.unwrap_or(1);
431            let select_keys = if let Some(keys) = &scheme.select_keys {
432                let mut transformed_keys = Vec::new();
433                for key in keys {
434                    let transformed_key = self
435                        .棱镜
436                        .键转数字
437                        .get(key)
438                        .ok_or(format!("简码的选择键 {key} 不在全局选择键中"))?;
439                    transformed_keys.push(*transformed_key);
440                }
441                transformed_keys
442            } else {
443                self.选择键.clone()
444            };
445            if count > select_keys.len() {
446                return Err("选重数量不能高于选择键数量".into());
447            }
448            compiled_schemes.push(简码数量 {
449                prefix,
450                select_keys: select_keys[..count].to_vec(),
451            });
452        }
453        Ok(compiled_schemes)
454    }
455
456    pub fn 预处理简码配置(
457        &self,
458        原始简码配置列表: Vec<简码规则>,
459    ) -> Result<[Vec<简码数量>; 最大词长], 错误> {
460        let mut short_code: [Vec<简码数量>; 最大词长] = Default::default();
461        for config in 原始简码配置列表 {
462            match config {
463                简码规则::Equal {
464                    length_equal,
465                    schemes,
466                } => {
467                    short_code[length_equal - 1].extend(self.预处理简码规则(&schemes)?);
468                }
469                简码规则::Range {
470                    length_in_range: (from, to),
471                    schemes,
472                } => {
473                    for length in from..=to {
474                        short_code[length - 1].extend(self.预处理简码规则(&schemes)?);
475                    }
476                }
477            }
478        }
479        Ok(short_code)
480    }
481
482    pub fn 线性表长度(&self) -> usize {
483        let 组合长度 = self.配置.encoder.max_length.min(最大按键组合长度);
484        self.棱镜.进制.pow(组合长度 as u32) as usize
485    }
486}