import { Node, NodeType } from "../model/Argument"; import { CertusContext, FZ } from "../model/Context"; import { EvaluationError } from "../parser/Evaluator"; import { EliminativeMacro } from "./EliminativeMacro"; import { MaxMacro, MinMacro } from "./MinAndMax"; export class MinEliminativeMacro extends EliminativeMacro { constructor(name?: string | undefined) { super(name || "min_elim"); } public evaluate(ctx: CertusContext): FZ { const root: Node = ctx.getRoot(); const nodes = this.getNodesFromContext(ctx); const P = nodes.filter(n => NodeType.checkSubType(NodeType.PREMISE, n.type)); const D = nodes.filter(n => NodeType.checkSubType(NodeType.DEFEATER, n.type)); if (P.length == 0 && D.length == 0) { return ctx.getDefaultCanonical(root.type); } else { const CS = ctx.getCanonicalSets(); const pScores = P.map(x => this.scoreNode(ctx, x, CS)); const dScores = D.map(x => this.scoreNode(ctx, x, CS)); let result: number; if (NodeType.checkSubType(NodeType.PREMISE, root.type)) { result = Math.min(...pScores, ...dScores.map(x => -1*x)) ; } else if (NodeType.checkSubType(NodeType.DEFEATER, root.type)) { result = Math.min(...pScores.map(p => -1*p), ...dScores) ; } else { throw new EvaluationError(`Unknown alternative while evaluating ${this.name}.`) } return this.scoreToSet(result, CS); } } public expand(ctx: CertusContext, target?: string): string { const nodes = this.getNodesFromContext(ctx); const root = ctx.getRoot(); const premises = nodes.filter(n => NodeType.checkSubType(NodeType.PREMISE, n.type)).map(p => p.id); const defeaters = nodes.filter(n => NodeType.checkSubType(NodeType.DEFEATER, n.type)).map(d => d.id); if (target) { if (premises.length == 0 && defeaters.length == 0) { return `${target} is ${ctx.getDefaultCanonical(root.type)}` } const args: string[] = []; for (const p of premises) { if (NodeType.checkSubType(NodeType.PREMISE, root.type)) { args.push(p) } else if (NodeType.checkSubType(NodeType.DEFEATER, root.type)) { args.push(`invert ${p}`) } } for (const d of defeaters) { if (NodeType.checkSubType(NodeType.DEFEATER, root.type)) { args.push(d) } else if (NodeType.checkSubType(NodeType.PREMISE, root.type)) { args.push(`invert ${d}`) } } return `${target} is min(${args.join(", ")})` } else { throw new EvaluationError(`${this.name} macro expansion requires an assignment target, none provided.`) } } } export class MaxEliminativeMacro extends MaxMacro { constructor(name?: string | undefined) { super(name || "max_elim"); } public evaluate(ctx: CertusContext): FZ { const root: Node = ctx.getRoot(); const nodes = this.getNodesFromContext(ctx); const P = nodes.filter(n => NodeType.checkSubType(NodeType.PREMISE, n.type)); const D = nodes.filter(n => NodeType.checkSubType(NodeType.DEFEATER, n.type)); if (P.length == 0 && D.length == 0) { return ctx.getDefaultCanonical(root.type); } else { const CS = ctx.getCanonicalSets(); const pScores = P.map(x => this.scoreNode(ctx, x, CS)); const dScores = D.map(x => this.scoreNode(ctx, x, CS)); let result: number; if (NodeType.checkSubType(NodeType.PREMISE, root.type)) { result = Math.max(...pScores, ...dScores.map(x => -1*x)) ; } else if (NodeType.checkSubType(NodeType.DEFEATER, root.type)) { result = Math.max(...pScores.map(p => -1*p), ...dScores) ; } else { throw new EvaluationError(`Unknown alternative while evaluating ${this.name}.`) } return this.scoreToSet(result, CS); } } public expand(ctx: CertusContext, target?: string): string { const nodes = this.getNodesFromContext(ctx); const root = ctx.getRoot(); const premises = nodes.filter(n => NodeType.checkSubType(NodeType.PREMISE, n.type)).map(p => p.id); const defeaters = nodes.filter(n => NodeType.checkSubType(NodeType.DEFEATER, n.type)).map(d => d.id); if (target) { if (premises.length == 0 && defeaters.length == 0) { return `${target} is ${ctx.getDefaultCanonical(root.type)}` } const args: string[] = []; for (const p of premises) { if (NodeType.checkSubType(NodeType.PREMISE, root.type)) { args.push(p) } else if (NodeType.checkSubType(NodeType.DEFEATER, root.type)) { args.push(`invert ${p}`) } } for (const d of defeaters) { if (NodeType.checkSubType(NodeType.DEFEATER, root.type)) { args.push(d) } else if (NodeType.checkSubType(NodeType.PREMISE, root.type)) { args.push(`invert ${d}`) } } return `${target} is max(${args.join(", ")})` } else { throw new EvaluationError(`${this.name} macro expansion requires an assignment target, none provided.`) } } }