1use crate::literal::{Lit, Var};
15#[allow(unused_imports)]
16use crate::prelude::*;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum PhaseMode {
21 Saved,
23 Target,
25 Random,
27}
28
29#[derive(Debug, Default, Clone)]
31pub struct TargetPhaseStats {
32 pub target_used: u64,
34 pub saved_used: u64,
36 pub random_used: u64,
38 pub target_updates: u64,
40}
41
42pub struct TargetPhaseSelector {
44 saved_phase: Vec<bool>,
46 target_phase: Vec<bool>,
48 use_target: Vec<bool>,
50 decay: f64,
52 confidence: Vec<f64>,
54 stats: TargetPhaseStats,
56}
57
58impl TargetPhaseSelector {
59 pub fn new(num_vars: usize, decay: f64) -> Self {
61 Self {
62 saved_phase: vec![false; num_vars],
63 target_phase: vec![false; num_vars],
64 use_target: vec![false; num_vars],
65 decay,
66 confidence: vec![0.0; num_vars],
67 stats: TargetPhaseStats::default(),
68 }
69 }
70
71 pub fn resize(&mut self, num_vars: usize) {
73 self.saved_phase.resize(num_vars, false);
74 self.target_phase.resize(num_vars, false);
75 self.use_target.resize(num_vars, false);
76 self.confidence.resize(num_vars, 0.0);
77 }
78
79 #[must_use]
81 pub fn stats(&self) -> &TargetPhaseStats {
82 &self.stats
83 }
84
85 pub fn save_phase(&mut self, var: Var, phase: bool) {
87 self.saved_phase[var.index()] = phase;
88 }
89
90 pub fn set_target(&mut self, var: Var, phase: bool, confidence_boost: f64) {
92 let idx = var.index();
93 self.target_phase[idx] = phase;
94 self.confidence[idx] += confidence_boost;
95
96 if self.confidence[idx] > 1.0 {
98 self.use_target[idx] = true;
99 self.stats.target_updates += 1;
100 }
101 }
102
103 pub fn on_conflict_literal(&mut self, lit: Lit) {
105 self.set_target(lit.var(), lit.sign(), 0.5);
108 }
109
110 pub fn on_learned_clause(&mut self, clause: &[Lit]) {
112 if clause.len() <= 5 {
114 for &lit in clause {
115 self.set_target(lit.var(), lit.sign(), 0.2);
116 }
117 }
118 }
119
120 pub fn decay_confidence(&mut self) {
122 for conf in &mut self.confidence {
123 *conf *= self.decay;
124 if *conf < 0.5 {
126 }
128 }
129 }
130
131 pub fn get_phase(&mut self, var: Var, mode: PhaseMode) -> bool {
133 let idx = var.index();
134
135 match mode {
136 PhaseMode::Saved => {
137 self.stats.saved_used += 1;
138 self.saved_phase[idx]
139 }
140 PhaseMode::Target => {
141 if self.use_target[idx] && self.confidence[idx] > 0.5 {
142 self.stats.target_used += 1;
143 self.target_phase[idx]
144 } else {
145 self.stats.saved_used += 1;
146 self.saved_phase[idx]
147 }
148 }
149 PhaseMode::Random => {
150 self.stats.random_used += 1;
151 (idx & 1) == 0
153 }
154 }
155 }
156
157 pub fn reset_targets(&mut self) {
159 for use_target in &mut self.use_target {
160 *use_target = false;
161 }
162 for conf in &mut self.confidence {
163 *conf = 0.0;
164 }
165 }
166
167 #[must_use]
169 pub fn get_confidence(&self, var: Var) -> f64 {
170 self.confidence[var.index()]
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn test_target_phase_creation() {
180 let selector = TargetPhaseSelector::new(10, 0.95);
181 assert_eq!(selector.saved_phase.len(), 10);
182 assert_eq!(selector.target_phase.len(), 10);
183 assert_eq!(selector.confidence.len(), 10);
184 }
185
186 #[test]
187 fn test_save_phase() {
188 let mut selector = TargetPhaseSelector::new(10, 0.95);
189 let var = Var::new(0);
190
191 selector.save_phase(var, true);
192 assert!(selector.saved_phase[var.index()]);
193
194 let phase = selector.get_phase(var, PhaseMode::Saved);
195 assert!(phase);
196 }
197
198 #[test]
199 fn test_target_phase() {
200 let mut selector = TargetPhaseSelector::new(10, 0.95);
201 let var = Var::new(0);
202
203 selector.set_target(var, true, 2.0);
205
206 let phase = selector.get_phase(var, PhaseMode::Target);
207 assert!(phase);
208 assert!(selector.get_confidence(var) > 1.0);
209 }
210
211 #[test]
212 fn test_confidence_decay() {
213 let mut selector = TargetPhaseSelector::new(10, 0.5);
214 let var = Var::new(0);
215
216 selector.set_target(var, true, 2.0);
217 let initial_conf = selector.get_confidence(var);
218
219 selector.decay_confidence();
220 let decayed_conf = selector.get_confidence(var);
221
222 assert!(decayed_conf < initial_conf);
223 assert!((decayed_conf - initial_conf * 0.5).abs() < 0.001);
224 }
225
226 #[test]
227 fn test_on_conflict_literal() {
228 let mut selector = TargetPhaseSelector::new(10, 0.95);
229 let lit = Lit::pos(Var::new(0));
230
231 selector.on_conflict_literal(lit);
232 assert!(selector.get_confidence(lit.var()) > 0.0);
233 }
234
235 #[test]
236 fn test_reset_targets() {
237 let mut selector = TargetPhaseSelector::new(10, 0.95);
238 let var = Var::new(0);
239
240 selector.set_target(var, true, 2.0);
241 assert!(selector.get_confidence(var) > 0.0);
242
243 selector.reset_targets();
244 assert_eq!(selector.get_confidence(var), 0.0);
245 }
246
247 #[test]
248 fn test_stats() {
249 let mut selector = TargetPhaseSelector::new(10, 0.95);
250 let var = Var::new(0);
251
252 selector.get_phase(var, PhaseMode::Saved);
253 assert_eq!(selector.stats().saved_used, 1);
254
255 selector.get_phase(var, PhaseMode::Random);
256 assert_eq!(selector.stats().random_used, 1);
257 }
258}