/**
* ASP Optimizer
* Handles optimization problems with multi-criteria objectives
*/
import { ASPProgram, ASPOptimizationProblem, OptimizationResult, OptimizationObjective } from '../../types.js';
import { ClingoSolver } from './clingoSolver.js';
import { ASPParser } from '../../parsers/aspParser.js';
export class ASPOptimizer {
private solver: ClingoSolver;
private parser: ASPParser;
constructor() {
this.solver = new ClingoSolver();
this.parser = new ASPParser();
}
/**
* Solve optimization problem
*/
async optimize(problem: ASPOptimizationProblem): Promise<OptimizationResult> {
// Convert objectives to weak constraints
const programWithOptimization = this.addOptimizationToProgram(
problem.program,
problem.objectives
);
// Convert to Clingo syntax
const clingoProgram = this.parser.toClingoSyntax(programWithOptimization);
// Solve with optimization enabled
const solution = await this.solver.solve(clingoProgram, {
optimization: true,
maxModels: 0 // Find all optimal
});
// Find optimal models
const optimalModels = solution.answerSets.filter(as => as.isOptimal);
const optimumCost = optimalModels.length > 0 ? (optimalModels[0].cost || []) : [];
const result: OptimizationResult = {
optimalModels,
optimumCost,
totalModelsChecked: solution.totalModels,
improvementTrace: [],
explanation: this.generateOptimizationExplanation(optimalModels, problem.objectives)
};
return result;
}
/**
* Add optimization objectives as weak constraints
*/
private addOptimizationToProgram(
program: ASPProgram,
objectives: OptimizationObjective[]
): ASPProgram {
const newProgram = { ...program };
if (!newProgram.weakConstraints) {
newProgram.weakConstraints = [];
}
// Convert each objective to weak constraint
for (const objective of objectives) {
const weight = objective.direction === 'minimize' ? objective.weight : -objective.weight;
newProgram.weakConstraints.push({
type: 'weak',
body: [
{
atom: {
predicate: objective.expression,
terms: [],
negation: 'none'
},
negation: 'none'
}
],
weight,
priority: objective.priority
});
}
return newProgram;
}
/**
* Generate explanation of optimization result
*/
private generateOptimizationExplanation(
optimalModels: any[],
objectives: OptimizationObjective[]
): string {
if (optimalModels.length === 0) {
return 'No feasible solutions found.';
}
let explanation = `Found ${optimalModels.length} optimal solution(s).\n\n`;
explanation += 'Optimization objectives (by priority):\n';
const sortedObjectives = [...objectives].sort((a, b) => b.priority - a.priority);
for (const obj of sortedObjectives) {
explanation += ` Priority ${obj.priority}: ${obj.direction} ${obj.expression}`;
if (obj.description) {
explanation += ` (${obj.description})`;
}
explanation += '\n';
}
return explanation;
}
}