import {
LogicalSystem,
Operation,
InputFormat,
LogicResult,
LogicError
} from './types.js';
import {
createUnsupportedOperationError,
createCommandError,
errorTemplates,
errorSuggestions,
exampleTemplates
} from './errorHandler.js';
import { SyllogisticLogic } from './systems/syllogistic.js';
import { PropositionalLogic } from './systems/propositional.js';
import { PredicateLogic } from './systems/predicate.js';
import { MathematicalLogic } from './systems/mathematical.js';
import { ModalLogic } from './systems/modal.js';
import { TemporalLogicSystem } from './systems/temporal.js';
import { FuzzyLogicSystem } from './systems/fuzzy.js';
import { DeonticLogicSystem } from './systems/deontic.js';
import { SMTLogic } from './systems/smt.js';
import { ProbabilisticLogic } from './systems/probabilistic.js';
import { ASPLogic } from './systems/asp.js';
import { NaturalLanguageProcessor } from './preprocessors/naturalLanguageProcessor.js';
import { logicCache } from './utils/cache.js';
import { Loggers } from './utils/logger.js';
const logger = Loggers.manager;
/**
* Central manager for logic operations
* Routes requests to the appropriate logical system
*/
export class LogicManager {
private syllogisticLogic: SyllogisticLogic;
private propositionalLogic: PropositionalLogic;
private predicateLogic: PredicateLogic;
private mathematicalLogic: MathematicalLogic;
private modalLogic: ModalLogic;
private temporalLogic: TemporalLogicSystem;
private fuzzyLogic: FuzzyLogicSystem;
private deonticLogic: DeonticLogicSystem;
private smtLogic: SMTLogic;
private probabilisticLogic: ProbabilisticLogic;
private aspLogic: ASPLogic;
private nlpProcessor: NaturalLanguageProcessor;
constructor() {
this.syllogisticLogic = new SyllogisticLogic();
this.propositionalLogic = new PropositionalLogic();
this.predicateLogic = new PredicateLogic();
this.mathematicalLogic = new MathematicalLogic();
this.modalLogic = new ModalLogic();
this.temporalLogic = new TemporalLogicSystem();
this.fuzzyLogic = new FuzzyLogicSystem();
this.deonticLogic = new DeonticLogicSystem();
this.smtLogic = new SMTLogic();
this.probabilisticLogic = new ProbabilisticLogic();
this.aspLogic = new ASPLogic();
this.nlpProcessor = new NaturalLanguageProcessor();
}
/**
* Set the modal system for modal logic operations
* @param system The modal system to use (K, T, D, B, K4, KB, S4, S5, KD45)
*/
setModalSystem(system: string): void {
this.modalLogic.setModalSystem(system as any);
}
/**
* Process a logical operation
* @param system The logical system to use
* @param operation The operation to perform
* @param input Input text or structured data
* @param format Input format
* @param additionalContext Optional additional context (e.g., modal system)
* @returns Operation result
*/
async process(
system: LogicalSystem,
operation: Operation,
input: string | any,
format: InputFormat = 'natural',
additionalContext?: string
): Promise<LogicResult> {
// Auto-detect the system if 'auto' is specified
if (system === 'auto') {
system = this.detectSystem(input);
}
// Generate cache key (include additionalContext for proper cache isolation)
const cacheKey = logicCache.generateCacheKey(
system,
operation,
typeof input === 'string' ? input : JSON.stringify(input),
format + (additionalContext ? `:${additionalContext}` : '')
);
// Check cache first
const cachedResult = logicCache.get<LogicResult>(cacheKey);
if (cachedResult !== undefined) {
logger.debug('Cache hit for logic operation', {
system,
operation,
format
});
return cachedResult;
}
// Process the request
let result: LogicResult;
// Route to the appropriate system
switch (system) {
case 'syllogistic':
result = this.syllogisticLogic.process(operation, input, format);
break;
case 'propositional':
result = this.propositionalLogic.process(operation, input, format);
break;
case 'predicate':
result = this.predicateLogic.process(operation, input, format);
break;
case 'mathematical':
result = this.mathematicalLogic.process(operation, input, format);
break;
case 'modal':
result = this.modalLogic.process(operation, input, format);
break;
case 'temporal':
result = this.temporalLogic.process(operation, input, format);
break;
case 'fuzzy':
result = this.fuzzyLogic.process(operation, input, format);
break;
case 'deontic':
result = this.deonticLogic.process(operation, input, format);
break;
case 'smt':
result = await this.smtLogic.process(operation, input, format);
break;
case 'probabilistic':
result = await this.probabilisticLogic.process(operation, input, format);
break;
case 'asp':
result = await this.aspLogic.process(operation, input, format);
break;
default:
result = createUnsupportedOperationError(
'auto',
operation,
`Try specifying a valid logical system: syllogistic, propositional, predicate, mathematical, modal, temporal, fuzzy, deontic, smt, probabilistic, or asp.`,
`${operation} --system=propositional --input="P → Q"`
);
}
// Cache the result (only cache successful results)
logger.debug('Result status:', { status: result.status });
if (result.status === 'success') {
logicCache.set(cacheKey, result);
logger.debug('Cached logic operation result', {
system,
operation,
format,
cacheKey
});
} else {
logger.debug('Not caching result due to status', {
status: result.status,
system,
operation
});
}
return result;
}
/**
* Detect the logical system based on input
* @param input Input text or structured data
* @returns Detected logical system
*/
private detectSystem(input: string | any): LogicalSystem {
if (typeof input !== 'string') {
// If structured data is provided, determine from its structure
return this.detectSystemFromStructure(input);
} else {
// Use the NLP processor to analyze the content type
return this.detectSystemFromText(input);
}
}
/**
* Detect system from structured data
* @param input Structured input
* @returns Detected logical system
*/
private detectSystemFromStructure(input: any): LogicalSystem {
// If structured data is provided, try to determine from its structure
if ('majorPremise' in input && 'minorPremise' in input) {
return 'syllogistic';
} else if ('premises' in input && 'conclusion' in input) {
// Check if it's propositional or predicate logic
const containsQuantifiers = JSON.stringify(input).includes('"quantifier"');
return containsQuantifiers ? 'predicate' : 'propositional';
} else if ('type' in input) {
// Check formula type
const containsQuantifiers =
input.type === 'quantified' ||
JSON.stringify(input).includes('"quantifier"');
const containsPredicates =
input.type === 'predicate' ||
JSON.stringify(input).includes('"predicate"');
if (containsQuantifiers || containsPredicates) {
return 'predicate';
} else {
return 'propositional';
}
} else if ('terms' in input && 'constraints' in input) {
return 'mathematical';
}
// Default fallback
return 'propositional';
}
/**
* Detect system from text using NLP
* @param input Text input
* @returns Detected logical system
*/
private detectSystemFromText(input: string): LogicalSystem {
// Use the NLP processor for enhanced content detection
const nlpResult = this.nlpProcessor.preprocess(input);
// If NLP detected the system with high confidence, use it
if (nlpResult.context.confidence >= 0.7) {
return nlpResult.context.detectedSystem;
}
// Otherwise, use the content type for detection
switch (nlpResult.type) {
case 'mathematical':
return 'mathematical';
case 'logical':
// Check for system-specific indicators in patterns
if (nlpResult.context.patterns.includes('quantifier')) {
return 'syllogistic';
} else if (nlpResult.context.patterns.includes('predicate')) {
return 'predicate';
} else {
return 'propositional';
}
case 'mixed':
// For mixed content, do more sophisticated detection
return this.detectMixedSystem(input, nlpResult.context.patterns);
default:
// Fall back to basic text analysis
return this.detectSystemBasicAnalysis(input);
}
}
/**
* Detect system for mixed content
* @param input Input text
* @param patterns Detected patterns
* @returns Detected logical system
*/
private detectMixedSystem(input: string, patterns: string[]): LogicalSystem {
// If sequence detection or equation solving is involved, it's mathematical
if (patterns.includes('sequence-detection') || patterns.includes('equation-solving')) {
return 'mathematical';
}
// If quantifiers are involved, it's syllogistic or predicate
if (patterns.includes('quantifier')) {
// Check for predicate patterns
if (/\w+\([^)]*\)/.test(input) || /∀|∃/.test(input)) {
return 'predicate';
} else {
return 'syllogistic';
}
}
// Default to propositional for most mixed content
return 'propositional';
}
/**
* Detect system using basic text analysis (fallback)
* @param input Input text
* @returns Detected logical system
*/
private detectSystemBasicAnalysis(input: string): LogicalSystem {
const text = input.toLowerCase();
// Look for ASP/answer set programming patterns
if (
text.includes('answer set') ||
text.includes('stable model') ||
text.includes('choice rule') ||
text.includes('find all') ||
text.includes('all ways') ||
text.includes('all solutions') ||
text.includes('enumerate all') ||
text.includes('all possible') ||
text.includes('typically') ||
text.includes('by default') ||
text.includes('unless') ||
text.includes('normally') ||
text.includes('schedule') ||
text.includes('scheduling') ||
text.includes('assign') ||
text.includes('assignment') ||
text.includes('allocate') ||
text.includes('allocation') ||
text.includes('color') ||
text.includes('coloring') ||
text.includes('placement') ||
text.includes('configuration') ||
/{[^}]+}/.test(text) || // Choice rule syntax
text.includes(':- ') || // Constraint/rule syntax
/:\s*not\s+\w+\s*\//.test(text) // Default syntax
) {
return 'asp';
}
// Look for probabilistic/uncertain reasoning patterns
if (
text.includes('probability') ||
text.includes('likely') ||
text.includes('uncertain') ||
text.includes('belief') ||
text.includes('bayesian') ||
text.includes('evidence') ||
text.includes('prior') ||
text.includes('posterior') ||
/P\([\w\s|]+\)/.test(text) || // P(X|Y) notation
/\d+\.\d+::/.test(text) || // 0.7::fact notation
/\d+%.*?(?:chance|probability)/.test(text) // 30% chance
) {
return 'probabilistic';
}
// Look for SMT/constraint solving patterns
if (
text.includes('constraint') ||
text.includes('satisf') ||
text.includes('optimize') ||
text.includes('maximize') ||
text.includes('minimize') ||
text.includes('subject to') ||
/find.*where/.test(text) ||
/(integer|real|boolean)\s+(variable|programming)/.test(text)
) {
return 'smt';
}
// Look for mathematical patterns
if (
/\d+\s*,\s*\d+/.test(text) || // Number sequences like "1, 2, 3"
/[+\-*/=<>]/.test(text) || // Mathematical operators
text.includes('sequence') ||
text.includes('pattern') ||
text.includes('next') ||
/\b\d+\b/.test(text) // Contains numbers
) {
return 'mathematical';
}
// Look for predicate logic indicators
if (
text.includes('∀') ||
text.includes('∃') ||
text.includes('forall') ||
text.includes('exists') ||
/\w+\([^)]*\)/.test(text) // Simple check for predicates like P(x)
) {
return 'predicate';
}
// Look for modal logic indicators
if (
text.includes('□') ||
text.includes('◇') ||
text.includes('necessary') ||
text.includes('possible') ||
text.includes('necessarily') ||
text.includes('possibly') ||
text.includes('must') ||
text.includes('might')
) {
return 'modal';
}
// Look for temporal logic indicators
if (
text.includes('always') ||
text.includes('eventually') ||
text.includes('next') ||
text.includes('until') ||
text.includes('globally') ||
text.includes('finally') ||
/\b[GFX]\s*[a-z]/i.test(text) ||
/\bU\b/.test(text)
) {
return 'temporal';
}
// Look for fuzzy logic indicators
if (
text.includes('very') ||
text.includes('somewhat') ||
text.includes('slightly') ||
text.includes('degree') ||
text.includes('membership') ||
text.includes('fuzzy') ||
/\b\d+\.\d+\)/.test(text) ||
/\bIS\b/i.test(text)
) {
return 'fuzzy';
}
// Look for deontic logic indicators
if (
text.includes('obligatory') ||
text.includes('permitted') ||
text.includes('forbidden') ||
text.includes('must') ||
text.includes('may') ||
text.includes('should') ||
text.includes('ought') ||
/\b[OPF]\s*\(/i.test(text)
) {
return 'deontic';
}
// Look for propositional logic indicators
if (
text.includes('→') ||
text.includes('↔') ||
text.includes('∧') ||
text.includes('∨') ||
text.includes('¬') ||
text.includes('implies') ||
(text.includes('if') && text.includes('then'))
) {
return 'propositional';
}
// Look for syllogistic logic indicators
if (
(text.includes('all') || text.includes('no') ||
text.includes('some') || text.includes('are')) &&
!text.includes('∀') && !text.includes('∃')
) {
return 'syllogistic';
}
// Default to propositional logic if can't determine
return 'propositional';
}
}