1use std::{
2 cell::{Cell, RefCell, UnsafeCell}, collections::{hash_map::Entry, HashMap, HashSet}, default, f64::consts::E, fs, future::Future, pin::pin, sync::atomic::AtomicBool, task::Poll, time::{self, Duration, Instant}
3};
4
5use derive_more::{Constructor, Deref, From, Into};
6use futures::StreamExt;
7use itertools::Itertools;
8use simple_rc_async::{sync::{broadcast, broadcastque}, task::{self, JoinHandle}};
9
10use crate::{
11 backward::{ Deducer, DeducerEnum, Problem}, debg, debg2, expr::{
12 cfg::{Cfg, ProdRule}, context::Context, Expr
13 }, forward::{data::{size, substr}, enumeration::ProdRuleEnumerateExt, executor}, galloc::AllocForAny, info, log, parser::problem::PBEProblem, solutions::CONDITIONS, text::parsing::{ParseInt, TextObjData}, utils::UnsafeCellExt, value::{ConstValue, Type, Value}, warn
14};
15use crate::expr;
16use super::{bridge::Bridge, data::{self, all_eq, size::EV, Data}};
17
18pub trait EnumFn = FnMut(Expr, Value) -> Result<(), ()>;
19
20pub static STOP_SIGNAL: AtomicBool = AtomicBool::new(false);
27
28pub struct TaskWaitingCost {
30 sender: broadcastque::Sender<()>,
31 cur_cost: usize,
32}
33
34impl Default for TaskWaitingCost {
35 fn default() -> Self {
37 Self::new()
38 }
39}
40
41impl TaskWaitingCost {
42 pub fn new() -> Self {
44 TaskWaitingCost { sender: broadcastque::channel(), cur_cost: 0 }
45 }
46
47 pub async fn inc_cost(&mut self, problem: &mut Problem, amount: usize) {
51 let mut rv: broadcastque::Reciever<()> = self.sender.reciever();
52 problem.used_cost += amount;
53 let amount = problem.used_cost as isize - self.cur_cost as isize;
54 if amount > 0 {
55 for _ in 0..amount {
56 let _ = rv.next().await;
57 }
58 }
59 }
60
61 pub fn release_cost_limit(&mut self, count: usize) {
65 self.sender.send((), count);
66 }
67}
68
69pub struct Executor {
85 pub ctx: Context,
86 pub cfg: Cfg,
87 pub deducers: Vec<DeducerEnum>,
89 pub data: Vec<Data>,
91 pub counter: Cell<usize>,
93 pub subproblem_count: Cell<usize>,
95 pub cur_size: Cell<usize>,
97 pub cur_nt: Cell<usize>,
99 pub waiting_tasks: UnsafeCell<TaskWaitingCost>,
102 pub top_task: UnsafeCell<JoinHandle<&'static Expr>>,
104 expr_collector: UnsafeCell<Vec<EV>>,
105 pub bridge: Bridge,
107 pub start_time: time::Instant,
109}
110
111impl Executor {
112 pub fn problem_count(&self) -> usize{
114 self.subproblem_count.get()
115 }
116 pub fn new(ctx: Context, cfg: Cfg) -> Self {
118 let data = Data::new(&cfg, &ctx);
119 let deducers = (0..cfg.len()).map(|i, | DeducerEnum::from_nt(&cfg, &ctx, i)).collect_vec();
120 let exec = Self { counter: 0.into(), subproblem_count: 0.into(), ctx, cfg, data, deducers, expr_collector: Vec::new().into(),
121 cur_size: 0.into(), cur_nt: 0.into(), waiting_tasks: TaskWaitingCost::new().into(),
122 top_task: task::spawn(futures::future::pending()).into(), bridge: Bridge::new(),
123 start_time: Instant::now() };
124 TextObjData::build_trie(&exec);
125 exec
126 }
127 pub fn top_task(&self) -> &mut JoinHandle<&'static Expr> {
128 unsafe { self.top_task.as_mut() }
129 }
130 pub fn collect_expr(&self, e: &'static Expr, v: Value) {
132 unsafe { self.expr_collector.as_mut().push((e, v)) }
133 }
134 pub fn waiting_tasks(&self) -> &mut TaskWaitingCost {
136 unsafe { self.waiting_tasks.as_mut() }
137 }
138 pub fn extract_expr_collector(&self) -> Vec<EV> {
140 UnsafeCellExt::replace(&self.expr_collector, Vec::new())
141 }
142 pub fn cur_data(&self) -> &Data {
144 &self.data[self.cur_nt.get()]
145 }
146 #[inline]
147 pub async fn solve_task(&'static self, problem: Problem) -> &'static Expr {
149 if let Some(e) = self.data[problem.nt].all_eq.at(problem.value) {
150 return e;
151 }
152 self.subproblem_count.update(|x| x+1);
153 task::spawn(self.deducers[problem.nt].deduce(self, problem)).await
154 }
155 #[inline]
156 pub async fn generate_condition(&'static self, problem: Problem, result: &'static Expr) -> &'static Expr {
158 if problem.value.is_all_true() { return result; }
159 let left = pin!(self.solve_task(problem));
160 let right = pin!(self.solve_task(problem.with_value(problem.value.bool_not())));
161 let cond = futures::future::select(left, right).await;
162 match cond {
163 futures::future::Either::Left((c, _)) =>
164 expr!(Ite {c} {result} "").galloc(),
165 futures::future::Either::Right((c, _)) =>
166 expr!(Ite {c} "" {result}).galloc(),
167 }
168 }
169 pub fn solve_top_blocked(self) -> &'static Expr {
171 let problem = Problem::root(0, self.ctx.output);
172 let this = unsafe { (&self as *const Executor).as_ref::<'static>().unwrap() };
173 this.subproblem_count.update(|x| x+1);
174 *this.top_task() = task::spawn(this.deducers[problem.nt].deduce(this, problem));
175 let _ = this.run();
176 self.bridge.abort_all();
177 if let Poll::Ready(r) = this.top_task().poll_rc_nocx() {
178 r
179 } else { panic!("should not reach here.") }
180 }
189
190 pub fn solve_top_with_limit(self) -> Option<&'static Expr> {
192 let problem = Problem::root(0, self.ctx.output);
193 let this = unsafe { (&self as *const Executor).as_ref::<'static>().unwrap() };
194 this.subproblem_count.update(|x| x+1);
195 *this.top_task() = task::spawn(this.deducers[problem.nt].deduce(this, problem));
196 let _ = this.run();
197 self.bridge.abort_all();
198 if let Poll::Ready(r) = this.top_task().poll_rc_nocx() {
199 Some(r)
200 } else { None }
201 }
202
203 pub fn size(&self) -> usize { self.cur_size.get() }
205
206 pub fn nt(&self) -> usize { self.cur_nt.get() }
208
209 pub fn count(&self) -> usize { self.counter.get() }
211
212 #[inline]
213 pub fn enum_expr(&'static self, e: Expr, v: Value) -> Result<(), ()> {
215 if self.counter.get() % 10000 == 1 {
216 if self.counter.get() % 300000 == 1 {
217 info!("Searching size={} [{}] - {:?} {:?} {}", self.cur_size.get(), self.counter.get(), e, v, self.subproblem_count.get());
218 }
219 self.waiting_tasks().release_cost_limit(self.cfg.config.increase_cost_limit);
220 self.bridge.check();
221 }
222 self.counter.update(|x| x + 1);
223 if self.ctx.output.ty() != Type::Bool && v.ty() == Type::Bool {
224 self.collect_condition(&e);
225 } else if let Some(e) = self.cur_data().update(self, e, v)? {
226 self.collect_expr(e,v);
227 }
228 if self.top_task().is_ready() || (Instant::now() - self.start_time).as_millis() >= self.cfg.config.time_limit as u128 {
229 return Err(());
230 }
231 while STOP_SIGNAL.load(std::sync::atomic::Ordering::Relaxed) { std::hint::spin_loop() }
232 Ok(())
233 }
234 fn collect_condition(&'static self, e: &Expr) {
236 if let Some(x) = CONDITIONS.lock().as_mut() { x.insert(e) }
237 }
238 fn run(&'static self) -> Result<(), ()> {
240 let _ = self.extract_expr_collector();
241 for size in 1 ..self.cfg.config.size_limit {
242 for (nt, ntdata) in self.cfg.iter().enumerate() {
243 self.cur_size.set(size);
244 self.cur_nt.set(nt);
245 info!("Enumerating size={} nt={} with - {}", size, ntdata.name, self.counter.get());
246 self.cur_data().to.enumerate(self)?;
247 for rule in &ntdata.rules {
248 rule.enumerate(self)?;
249 }
250
251 self.cur_data().size.add(size, self.extract_expr_collector());
252 }
253 }
254 Ok(())
255 }
256 }
287