1use qualia_core_db::solvers::linear_algebra::{
2 ConstTensorContractor, FixedLanczosEigensolver, Matrix4x4, StaticLuDecomposition, Tensor3x3x3,
3 Vector4,
4};
5use qualia_core_db::solvers::optimization::{
6 BoundedNewtonRaphson, CurveFitFunction, LevenbergMarquardtStack, NelderMeadSimplex,
7 ObjectiveFunction, RootFunction,
8};
9use qualia_core_db::solvers::quantum_optimizers::{
10 QAOAAngleOptimizer, QAOAAngles, QuantumCostFunction, SpsaCostFunction, SpsaOptimizer,
11};
12use qualia_core_db::solvers::symbolic_logic::{
13 BoundedSatSolver, Clause, DefeasibleRule, Fact, ForwardChainingDefeasible, Literal, RuleType,
14};
15use qualia_core_db::solvers::SolverConfig;
16
17fn parse_f64s(s: &str) -> Vec<f64> {
20 s.split(',')
21 .filter_map(|tok| tok.trim().parse::<f64>().ok())
22 .collect()
23}
24
25fn build_matrix4x4(v: &[f64]) -> Matrix4x4 {
26 let mut m = Matrix4x4::zero();
27 for row in 0..4 {
28 for col in 0..4 {
29 m.data[row][col] = v[row * 4 + col];
30 }
31 }
32 m
33}
34
35fn parse_matrix4x4(s: &str) -> Option<Matrix4x4> {
36 let v = parse_f64s(s);
37 if v.len() < 16 {
38 eprintln!(
39 "Need 16 comma-separated values for a 4×4 matrix, got {}.",
40 v.len()
41 );
42 return None;
43 }
44 Some(build_matrix4x4(&v))
45}
46
47fn parse_vector4(s: &str) -> Option<Vector4> {
48 let v = parse_f64s(s);
49 if v.len() < 4 {
50 eprintln!(
51 "Need 4 comma-separated values for a Vector4, got {}.",
52 v.len()
53 );
54 return None;
55 }
56 Some(Vector4::from_array([v[0], v[1], v[2], v[3]]))
57}
58
59fn build_tensor3x3x3(v: &[f64]) -> Tensor3x3x3 {
60 let mut t = Tensor3x3x3::zero();
61 for i in 0..3 {
62 for j in 0..3 {
63 for k in 0..3 {
64 t.data[i][j][k] = v[i * 9 + j * 3 + k];
65 }
66 }
67 }
68 t
69}
70
71fn parse_tensor3x3x3(s: &str) -> Option<Tensor3x3x3> {
72 let v = parse_f64s(s);
73 if v.len() < 27 {
74 eprintln!(
75 "Need 27 comma-separated values for a 3×3×3 tensor, got {}.",
76 v.len()
77 );
78 return None;
79 }
80 Some(build_tensor3x3x3(&v))
81}
82
83fn parse_params4(s: &str) -> Option<[f64; 4]> {
84 let v = parse_f64s(s);
85 if v.len() < 4 {
86 eprintln!("Need 4 comma-separated values, got {}.", v.len());
87 return None;
88 }
89 Some([v[0], v[1], v[2], v[3]])
90}
91
92fn default_config(max_iters: u32, tol: f64) -> SolverConfig {
93 SolverConfig {
94 max_iterations: max_iters,
95 tolerance: tol,
96 step_size: 0.01,
97 verbose: false,
98 }
99}
100
101pub fn run_matrix_multiply(a_str: &str, b_str: &str) {
104 let (Some(a), Some(b)) = (parse_matrix4x4(a_str), parse_matrix4x4(b_str)) else {
105 return;
106 };
107 let result = a.multiply_matrix(&b);
108 println!("Matrix A × B:");
109 print_matrix4x4(&result);
110}
111
112pub fn run_determinant(m_str: &str) {
113 let Some(m) = parse_matrix4x4(m_str) else {
114 return;
115 };
116 let det = m.determinant();
117 println!("Determinant: {det:.10e}");
118}
119
120pub fn run_solve_system(m_str: &str, v_str: &str) {
121 let (Some(a), Some(b)) = (parse_matrix4x4(m_str), parse_vector4(v_str)) else {
122 return;
123 };
124 let mut lu = StaticLuDecomposition::new(default_config(100, 1e-12));
125 match lu.solve(&a, &b) {
126 Ok(x) => {
127 println!("Solution x for Ax = b:");
128 println!(
129 " [{:.6}, {:.6}, {:.6}, {:.6}]",
130 x.data[0], x.data[1], x.data[2], x.data[3]
131 );
132 }
133 Err(e) => eprintln!("Solve failed: {e:?}"),
134 }
135}
136
137pub fn run_eigenvalues(m_str: &str, count: usize) {
138 let Some(m) = parse_matrix4x4(m_str) else {
139 return;
140 };
141 let mut solver = FixedLanczosEigensolver::new(default_config(100, 1e-8));
142 match solver.find_lowest_eigenvalues(&m, count) {
143 Ok(eigs) => {
144 let n = count.min(4);
145 println!("Lowest {n} eigenvalue(s) (Lanczos):");
146 for i in 0..n {
147 println!(" λ[{i}] = {:.10e}", eigs[i]);
148 }
149 }
150 Err(e) => eprintln!("Eigenvalue computation failed: {e:?}"),
151 }
152}
153
154pub fn run_tensor_contract(t_str: &str) {
155 let Some(ta) = parse_tensor3x3x3(t_str) else {
156 return;
157 };
158 let tb = Tensor3x3x3::zero();
159 let indices: [(usize, usize); 3] = [(0, 0), (1, 1), (2, 2)];
160 let mut contractor = ConstTensorContractor::new(default_config(1, 1e-10));
161 match contractor.contract(&ta, &tb, &indices) {
162 Ok(result) => {
163 let scalar: f64 = (0..3)
165 .flat_map(|i| (0..3).flat_map(move |j| (0..3).map(move |k| (i, j, k))))
166 .map(|(i, j, k)| result.data[i][j][k])
167 .sum();
168 println!("Tensor contraction A⊗0 trace-sum: {scalar:.10e}");
169 println!("(pass two tensors via --tensor-a and --tensor-b for a full contraction)");
170 }
171 Err(e) => eprintln!("Tensor contraction failed: {e:?}"),
172 }
173}
174
175fn print_matrix4x4(m: &Matrix4x4) {
176 for row in 0..4 {
177 println!(
178 " [{:12.6}, {:12.6}, {:12.6}, {:12.6}]",
179 m.data[row][0], m.data[row][1], m.data[row][2], m.data[row][3]
180 );
181 }
182}
183
184struct ClosureFn<F: Fn(&[f64; 4]) -> f64>(F);
187impl<F: Fn(&[f64; 4]) -> f64> ObjectiveFunction for ClosureFn<F> {
188 fn evaluate(&self, params: &[f64; 4]) -> f64 {
189 (self.0)(params)
190 }
191}
192
193struct RootClosureFn<F: Fn(f64) -> f64, D: Fn(f64) -> f64>(F, D);
194impl<F: Fn(f64) -> f64, D: Fn(f64) -> f64> RootFunction for RootClosureFn<F, D> {
195 fn evaluate(&self, x: f64) -> f64 {
196 (self.0)(x)
197 }
198 fn derivative(&self, x: f64) -> f64 {
199 (self.1)(x)
200 }
201}
202
203struct CurveFn;
204impl CurveFitFunction for CurveFn {
205 fn evaluate(&self, x: f64, p: &[f64; 4]) -> f64 {
207 p[0] * x.powi(3) + p[1] * x.powi(2) + p[2] * x + p[3]
208 }
209 fn jacobian(&self, x: f64, _p: &[f64; 4]) -> [f64; 4] {
210 [x.powi(3), x.powi(2), x, 1.0]
211 }
212}
213
214pub fn run_simplex(initial_str: &str, iterations: u32) {
217 let Some(x0) = parse_params4(initial_str) else {
218 return;
219 };
220 let cfg = default_config(iterations, 1e-8);
221 let mut solver = NelderMeadSimplex::new(x0, cfg);
222 let f = ClosureFn(|p: &[f64; 4]| {
224 let a = (1.0 - p[0]).powi(2) + 100.0 * (p[1] - p[0].powi(2)).powi(2);
225 let b = (1.0 - p[2]).powi(2) + 100.0 * (p[3] - p[2].powi(2)).powi(2);
226 a + b
227 });
228 match solver.optimize(&f) {
229 Ok(state) => {
230 let bp = solver.best_point;
231 println!("Nelder-Mead simplex (Rosenbrock 4D, {iterations} iters):");
232 println!(
233 " x = [{:.6}, {:.6}, {:.6}, {:.6}]",
234 bp[0], bp[1], bp[2], bp[3]
235 );
236 println!(" f(x) = {:.10e}", state.objective_value);
237 println!(" Converged: {}", state.converged);
238 }
239 Err(e) => eprintln!("Simplex failed: {e:?}"),
240 }
241}
242
243pub fn run_root(initial: f64, lower: f64, upper: f64, tolerance: f64) {
244 let cfg = SolverConfig {
246 max_iterations: 200,
247 tolerance,
248 step_size: 0.01,
249 verbose: false,
250 };
251 let mut solver = BoundedNewtonRaphson::new(initial, lower, upper, cfg);
252 let f = RootClosureFn(|x: f64| x * x * x - x - 1.0, |x: f64| 3.0 * x * x - 1.0);
253 match solver.find_root(&f) {
254 Ok(state) => {
255 let root = solver.get_root();
256 println!("Newton-Raphson root of f(x) = x³ − x − 1:");
257 println!(" root ≈ {root:.10e}");
258 println!(" f(root) = {:.4e}", x_cubed_minus_x_minus_one(root));
259 println!(
260 " Converged: {} ({} iters)",
261 state.converged, state.iteration
262 );
263 }
264 Err(e) => eprintln!("Root finder failed: {e:?}"),
265 }
266}
267
268fn x_cubed_minus_x_minus_one(x: f64) -> f64 {
269 x * x * x - x - 1.0
270}
271
272pub fn run_curve_fit(params_str: &str, x_str: &str, y_str: &str) {
273 let Some(p0) = parse_params4(params_str) else {
274 return;
275 };
276 let xs = parse_f64s(x_str);
277 let ys = parse_f64s(y_str);
278 if xs.is_empty() || ys.is_empty() || xs.len() != ys.len() {
279 eprintln!("x-data and y-data must be equal-length, non-empty comma-separated lists.");
280 return;
281 }
282
283 let mut xd = [0.0f64; 10];
285 let mut yd = [0.0f64; 10];
286 let n = xs.len().min(10);
287 xd[..n].copy_from_slice(&xs[..n]);
288 yd[..n].copy_from_slice(&ys[..n]);
289
290 let cfg = default_config(200, 1e-8);
291 let mut lm = LevenbergMarquardtStack::new(p0, cfg);
292 let model = CurveFn;
293 match lm.fit_curve(&model, &xd, &yd) {
294 Ok(state) => {
295 let p = lm.parameters;
296 println!("Levenberg-Marquardt curve fit (cubic: p0·x³+p1·x²+p2·x+p3):");
297 println!(
298 " params = [{:.6}, {:.6}, {:.6}, {:.6}]",
299 p[0], p[1], p[2], p[3]
300 );
301 println!(" χ² = {:.6e}", state.chi_squared);
302 println!(
303 " Converged: {} ({} iters)",
304 state.converged, state.iteration
305 );
306 }
307 Err(e) => eprintln!("Curve fit failed: {e:?}"),
308 }
309}
310
311pub fn run_ode_rk4(lambda: f64, t_start: f64, t_end: f64, y0: f64, step_size: f64) {
314 use qualia_core_db::modalities::calculus::ode_solver::{ExponentialDecay, Rk4Solver};
315 let system = ExponentialDecay::new(lambda);
316 let mut solver = Rk4Solver::new(system, step_size);
317 let result = solver.solve(t_start, t_end, y0);
318 println!("RK4 ODE (exponential decay λ={lambda}):");
319 println!(" t ∈ [{t_start}, {t_end}], y(0)={y0}, h={step_size}");
320 println!(" y(t_end) ≈ {result:.10e}");
321 println!(
322 " exact = {:.10e}",
323 y0 * (-lambda * (t_end - t_start)).exp()
324 );
325}
326
327pub fn run_ode_harmonic(omega: f64, t_start: f64, t_end: f64, y0: f64, step_size: f64) {
328 use qualia_core_db::modalities::calculus::ode_solver::{HarmonicOscillator, Rk4Solver};
329 let system = HarmonicOscillator::new(omega);
330 let mut solver = Rk4Solver::new(system, step_size);
331 let result = solver.solve(t_start, t_end, y0);
332 println!("RK4 ODE (harmonic oscillator ω={omega}):");
333 println!(" t ∈ [{t_start}, {t_end}], y(0)={y0}, h={step_size}");
334 println!(" y(t_end) ≈ {result:.10e}");
335}
336
337pub fn run_ode_bvp(t_start: f64, t_end: f64, y_left: f64, y_right: f64, threshold: f64) {
338 use qualia_core_db::modalities::calculus::ode_solver::{BvpSystem, ShootingMethod};
339
340 struct SimpleBvp {
341 lambda: f64,
342 }
343 impl BvpSystem for SimpleBvp {
344 fn derivative(&self, _t: f64, y: f64) -> f64 {
345 -self.lambda * y
346 }
347 fn boundary_left(&self, _a: f64) -> f64 {
348 0.0
349 }
350 fn boundary_right(&self, _b: f64) -> f64 {
351 0.0
352 }
353 }
354
355 let system = SimpleBvp { lambda: 1.0 };
356 let mut solver = ShootingMethod::new(system, threshold).with_max_iterations(500);
357 match solver.solve(t_start, t_end, y_left, y_right) {
358 Ok((ic, residual)) => {
359 println!("BVP shooting method (f'=-y):");
360 println!(" t ∈ [{t_start}, {t_end}]");
361 println!(" Converged IC : {ic:.8e}");
362 println!(" Residual : {residual:.4e}");
363 }
364 Err(e) => eprintln!("BVP failed to converge: {e}"),
365 }
366}
367
368pub fn run_ode_quantum_spectrum(planck_mass: f64, coupling: f64, max_n: u64, frequency: f64) {
369 use qualia_core_db::modalities::calculus::ode_solver::QuantizationMapper;
370 let qh = QuantizationMapper::new(planck_mass, coupling);
371 let spectrum = qh.compute_mass_spectrum(max_n, frequency);
372 println!("Quantum harmonic mass spectrum (M_p={planck_mass:.3e}, g={coupling:.3e}, f={frequency:.3e}):");
373 for (n, mass) in spectrum.iter().take(10) {
374 println!(" n={n:3} mass = {mass:.10e}");
375 }
376 if spectrum.len() > 10 {
377 println!(" … ({} total levels)", spectrum.len());
378 }
379}
380
381struct DemoQaoa(u8);
384
385impl QuantumCostFunction for DemoQaoa {
386 fn evaluate_quantum(&self, angles: &QAOAAngles) -> qualia_core_db::solvers::SolverResult<f64> {
387 let cost: f64 = angles.beta[..self.0 as usize]
389 .iter()
390 .map(|x| x * x)
391 .sum::<f64>()
392 + angles.gamma[..self.0 as usize]
393 .iter()
394 .map(|x| x * x)
395 .sum::<f64>();
396 Ok(cost)
397 }
398 fn evaluate_perturbed(
399 &self,
400 angles: &QAOAAngles,
401 perturbation: &QAOAAngles,
402 ) -> qualia_core_db::solvers::SolverResult<(f64, f64)> {
403 let mut plus = *angles;
404 let mut minus = *angles;
405 for i in 0..self.0 as usize {
406 plus.beta[i] += perturbation.beta[i];
407 minus.beta[i] -= perturbation.beta[i];
408 }
409 Ok((
410 self.evaluate_quantum(&plus)?,
411 self.evaluate_quantum(&minus)?,
412 ))
413 }
414 fn problem_size(&self) -> u8 {
415 self.0
416 }
417}
418
419pub fn run_quantum_qaoa(depth: u8, beta_str: &str, gamma_str: &str) {
420 let cfg = default_config(100, 1e-6);
421 let mut opt = QAOAAngleOptimizer::new(depth, cfg);
422 let betas = parse_f64s(beta_str);
423 let gammas = parse_f64s(gamma_str);
424 let mut init = QAOAAngles {
425 beta: [0.0; 10],
426 gamma: [0.0; 10],
427 };
428 for (i, &b) in betas.iter().take(10).enumerate() {
429 init.beta[i] = b;
430 }
431 for (i, &g) in gammas.iter().take(10).enumerate() {
432 init.gamma[i] = g;
433 }
434 let cost_fn = DemoQaoa(depth.min(10));
435 match opt.optimize(&cost_fn, init) {
436 Ok(state) => {
437 let final_a = opt.get_angles();
438 println!("QAOA angle optimizer (depth={depth}, demo MaxCut cost):");
439 println!(" Iterations : {}", state.iteration);
440 println!(" Quantum calls: {}", state.quantum_calls);
441 println!(" Final cost : {:.8e}", state.cost_value);
442 println!(" Converged : {}", state.converged);
443 println!(" β[0..d] = {:?}", &final_a.beta[..depth as usize]);
444 println!(" γ[0..d] = {:?}", &final_a.gamma[..depth as usize]);
445 }
446 Err(e) => eprintln!("QAOA optimization failed: {e:?}"),
447 }
448}
449
450struct DemoSpsa(#[allow(dead_code)] u8);
451
452impl SpsaCostFunction for DemoSpsa {
453 fn evaluate(&self, params: &[f64; 20], n: u8) -> qualia_core_db::solvers::SolverResult<f64> {
454 Ok(params[..n as usize].iter().map(|x| x * x).sum())
455 }
456 fn valid_parameters(&self, _p: &[f64; 20], _n: u8) -> bool {
457 true
458 }
459}
460
461pub fn run_quantum_spsa(num_params: u8, initial_str: &str) {
462 let vals = parse_f64s(initial_str);
463 let mut params = [0.0f64; 20];
464 let n = (num_params as usize).min(20).min(vals.len());
465 params[..n].copy_from_slice(&vals[..n]);
466 let cfg = default_config(200, 1e-6);
467 let mut opt = SpsaOptimizer::new(num_params, cfg);
468 let cost_fn = DemoSpsa(num_params);
469 match opt.optimize(&cost_fn, ¶ms) {
470 Ok(state) => {
471 let p = opt.get_parameters();
472 println!("SPSA optimizer (demo quadratic cost, {num_params} params):");
473 println!(" Iterations: {}", state.iteration);
474 println!(" Final cost: {:.8e}", state.cost_value);
475 println!(" Converged : {}", state.converged);
476 println!(" Params : {:?}", &p[..n]);
477 }
478 Err(e) => eprintln!("SPSA optimization failed: {e:?}"),
479 }
480}
481
482fn parse_u8s(s: &str) -> Vec<u8> {
485 s.split(',')
486 .filter_map(|t| t.trim().parse::<u8>().ok())
487 .collect()
488}
489
490pub fn run_symbolic_defeasible(facts_str: &str, rules_str: &str) {
491 let cfg = default_config(500, 1e-6);
492 let mut solver = ForwardChainingDefeasible::new(cfg);
493
494 for (idx, var) in parse_u8s(facts_str).into_iter().enumerate() {
496 let fact = Fact {
497 id: (idx as u32) + 1,
498 literal: Literal {
499 variable: var,
500 negated: false,
501 },
502 supporting_rules: [0; 3],
503 defeated: false,
504 confidence: 1.0,
505 };
506 if let Err(e) = solver.add_fact(fact) {
507 eprintln!(" Fact capacity exceeded: {e:?}");
508 break;
509 }
510 }
511
512 for (rid, rule_str) in rules_str.split(';').enumerate() {
514 let parts: Vec<&str> = rule_str.splitn(2, ':').collect();
515 if parts.len() != 2 {
516 continue;
517 }
518 let ants: Vec<u8> = parse_u8s(parts[0]);
519 let cons = parts[1].trim().parse::<u8>().unwrap_or(0);
520 let mut antecedents = [Literal {
521 variable: 0,
522 negated: false,
523 }; 5];
524 for (i, &a) in ants.iter().take(5).enumerate() {
525 antecedents[i] = Literal {
526 variable: a,
527 negated: false,
528 };
529 }
530 let rule = DefeasibleRule {
531 id: (rid as u32) + 1,
532 rule_type: RuleType::Defeasible,
533 antecedents,
534 consequent: Literal {
535 variable: cons,
536 negated: false,
537 },
538 priority: 500,
539 active: true,
540 fire_count: 0,
541 };
542 if let Err(e) = solver.add_rule(rule) {
543 eprintln!(" Rule capacity exceeded: {e:?}");
544 break;
545 }
546 }
547
548 match solver.infer() {
549 Ok(state) => {
550 println!("Defeasible logic inference:");
551 println!(" Facts at start : {}", parse_u8s(facts_str).len());
552 println!(" Facts after : {}", state.num_facts);
553 println!(" Rules fired : {}", state.rules_fired);
554 println!(" Iterations : {}", state.iteration);
555 println!(" Converged : {}", state.converged);
556 let active: Vec<u8> = solver
557 .get_facts()
558 .iter()
559 .filter(|f| f.id != 0 && !f.defeated)
560 .map(|f| f.literal.variable)
561 .collect();
562 println!(" Active literals: {active:?}");
563 }
564 Err(e) => eprintln!("Defeasible inference failed: {e:?}"),
565 }
566}
567
568pub fn run_symbolic_sat(clauses_str: &str) {
569 let cfg = default_config(1000, 1e-8);
570 let mut solver = BoundedSatSolver::new(cfg);
571
572 for (cid, clause_str) in clauses_str.split('|').enumerate() {
574 let lits: Vec<Literal> = clause_str
575 .split(',')
576 .filter_map(|tok| {
577 let tok = tok.trim();
578 let (neg, var_str) = if tok.starts_with('-') {
579 (true, &tok[1..])
580 } else {
581 (false, tok)
582 };
583 var_str.parse::<u8>().ok().map(|v| Literal {
584 variable: v,
585 negated: neg,
586 })
587 })
588 .collect();
589 let mut literals = [Literal {
590 variable: 0,
591 negated: false,
592 }; 5];
593 let n = lits.len().min(5) as u8;
594 for (i, l) in lits.iter().take(5).enumerate() {
595 literals[i] = *l;
596 }
597 let clause = Clause {
598 id: (cid as u32) + 1,
599 literals,
600 num_literals: n,
601 learned: false,
602 activity: 1.0,
603 };
604 if let Err(e) = solver.add_clause(clause) {
605 eprintln!(" Clause capacity exceeded: {e:?}");
606 break;
607 }
608 }
609
610 match solver.solve() {
611 Ok(state) => {
612 use qualia_core_db::solvers::symbolic_logic::AssignmentValue;
613 println!("SAT solver (DPLL):");
614 println!(" Iterations : {}", state.iteration);
615 println!(" Decisions : {}", state.num_decisions);
616 println!(
617 " Satisfiable : {}",
618 match state.satisfiable {
619 Some(true) => "yes",
620 Some(false) => "no",
621 None => "unknown",
622 }
623 );
624 let assignments = solver.get_assignments();
625 let assigned: Vec<_> = assignments
626 .iter()
627 .filter(|a| a.level != 0 || a.antecedent.is_some())
628 .map(|a| {
629 let v = match a.value {
630 AssignmentValue::True => "T",
631 AssignmentValue::False => "F",
632 AssignmentValue::Unassigned => "?",
633 };
634 format!("x[{}]={}", a.level, v)
635 })
636 .take(10)
637 .collect();
638 if !assigned.is_empty() {
639 println!(" Assignments : {}", assigned.join(", "));
640 }
641 }
642 Err(e) => eprintln!("SAT solve failed: {e:?}"),
643 }
644}