use crate::{
control::{util_outputs, ContextDerivation, ReasonContext},
entity::{BudgetValue, Judgement, JudgementV1, Sentence, ShortFloat, Task},
global::Float,
inference::{Budget, BudgetFunctions},
};
use navm::output::Output;
#[derive(Debug, Clone)]
pub(in crate::inference) enum SolutionResult {
Rejected,
NewSolution {
updated_question_priority: ShortFloat,
params_to_activate_task: Option<(BudgetValue, JudgementV1)>,
new_output: Option<Output>,
},
}
#[must_use]
pub(in crate::inference) fn try_solution_calculate(
belief: &impl Judgement,
question_task: &Task,
budget_threshold: Float, ) -> SolutionResult {
use SolutionResult::*;
debug_assert!(question_task.is_question(), "要解决的必须是「问题」");
let problem = question_task.as_question().unwrap();
let new_q = BudgetValue::solution_quality(question_task, belief);
if let Some(old_best) = question_task.best_solution() {
let old_q = BudgetValue::solution_quality(question_task, old_best);
if old_q >= new_q {
return Rejected;
}
}
let new_output = match question_task.is_input() {
true => Some(util_outputs::output_answer(belief)),
false => None,
};
let budget = BudgetValue::solution_eval(problem, belief, question_task);
let parent_belief = question_task.parent_belief();
let updated_question_priority = ShortFloat::min(question_task.priority(), !new_q);
let params_to_activate_task = match budget.budget_above_threshold(budget_threshold) {
true => parent_belief.map(|belief| (budget, belief.clone())),
false => None,
};
NewSolution {
new_output,
updated_question_priority,
params_to_activate_task,
}
}
pub(in crate::inference) fn try_solution_apply_task(
result: &SolutionResult,
question_task: &mut Task,
solution: &JudgementV1,
) {
use SolutionResult::*;
match result {
Rejected => {}
NewSolution {
updated_question_priority,
..
} => {
question_task.set_best_solution(solution.clone());
question_task.set_priority(*updated_question_priority);
}
}
}
pub(in crate::inference) fn try_solution_apply_context(
result: SolutionResult,
solution: &JudgementV1,
context: &mut impl ReasonContext,
) {
use SolutionResult::*;
match result {
Rejected => {}
NewSolution {
new_output,
params_to_activate_task,
..
} => {
if let Some((budget, candidate_belief)) = params_to_activate_task {
context.activated_task(budget, solution, &candidate_belief);
}
if let Some(output) = new_output {
context.report(output);
}
}
}
}