UNPKG

pddl-workspace

Version:
166 lines 7.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PddlPlannerOutputParser = void 0; const ProblemInfo_1 = require("../ProblemInfo"); const DomainInfo_1 = require("../DomainInfo"); const PddlSyntaxTree_1 = require("./PddlSyntaxTree"); const DocumentPositionResolver_1 = require("../DocumentPositionResolver"); const XmlPlanBuilder_1 = require("./XmlPlanBuilder"); const PddlPlanBuilder_1 = require("./PddlPlanBuilder"); const PddlPlanParser_1 = require("./PddlPlanParser"); /** * Parses plan in the PDDL form incrementally - line/buffer at a time. * It can parse a continuous output of a planner, which may contain multiple plans. */ class PddlPlannerOutputParser { constructor(domain, problem, options, onPlanReady) { this.domain = domain; this.problem = problem; this.options = options; this.onPlanReady = onPlanReady; this.plans = []; this.endOfBufferToBeParsedNextTime = ''; this.planTimeScale = 1; this.planBuilder = new PddlPlanBuilder_1.PddlPlanBuilder(options.epsilon); this.pddlPlanParser = new PddlPlanParser_1.PddlPlanParser(); } setPlanMetaData(makespan, metric, statesEvaluated, _elapsedTimeInSeconds, planTimeScale) { this.planBuilder.setMakespan(makespan); this.planBuilder.setMetric(metric); this.planBuilder.setStatesEvaluated(statesEvaluated); this.planTimeScale = planTimeScale; } /** * Appends and parses the planner output. * @param text planner output */ appendBuffer(text) { const textString = this.endOfBufferToBeParsedNextTime + text; this.endOfBufferToBeParsedNextTime = ''; let lastEndLine = 0; let nextEndLine; while ((nextEndLine = textString.indexOf('\n', lastEndLine)) > -1) { const nextLine = textString.substring(lastEndLine, nextEndLine + 1); if (nextLine.trim()) { this.appendLine(nextLine.trim()); } lastEndLine = nextEndLine + 1; } if (textString.length > lastEndLine) { this.endOfBufferToBeParsedNextTime = textString.substring(lastEndLine); } } async appendXplan(planXml) { if (this.xmlPlanBuilder) { throw new Error("Mix of incremental XML parsing and full plan appending is not supported."); } const xmlPlanBuilder = new XmlPlanBuilder_1.XmlPlanBuilder(this.planTimeScale); xmlPlanBuilder.appendLine(planXml); const steps = await xmlPlanBuilder.getPlanSteps(); steps.forEach(step => this.appendStep(step)); this.onPlanFinished(); return this.getPlans(); } /** * Parses one line of parser output. * @param outputLine one line of planner output */ appendLine(outputLine) { if (this.xmlPlanBuilder || XmlPlanBuilder_1.XmlPlanBuilder.isXmlStart(outputLine)) { (this.xmlPlanBuilder || (this.xmlPlanBuilder = new XmlPlanBuilder_1.XmlPlanBuilder(this.planTimeScale))).appendLine(outputLine); if (this.xmlPlanBuilder.isComplete()) { // extract plan this.xmlPlanBuilder.getPlanSteps() .then(steps => { steps.forEach(step => this.appendStep(step)); this.xmlPlanBuilder = undefined; this.onPlanFinished(); }) .catch(reason => { console.log(reason); }); } return; } const planStep = this.pddlPlanParser.parse(outputLine, undefined, this.planBuilder); if (planStep) { // this line is a plan step this.appendStep(planStep); } else { // this line is NOT a plan step if (this.planBuilder.parsingPlan) { this.planBuilder.parsingPlan = false; this.onPlanFinished(); } this.pddlPlanParser.parsePlanQuality(outputLine, this.planBuilder); } this.planBuilder.outputText += outputLine; } /** * Appends plan step. Use this when the plan does not need parsing. * @param planStep plan step to add to the plan */ appendStep(planStep) { this.planBuilder.add(planStep); if (!this.planBuilder.parsingPlan) { this.planBuilder.parsingPlan = true; } } /** * Call this when the planning engine stopped. This flushes the last line in the buffered output through the parsing * and adds the last plan to the collection of plans. */ onPlanFinished() { var _a; if (this.endOfBufferToBeParsedNextTime.trim().length) { this.appendLine(this.endOfBufferToBeParsedNextTime.trim()); this.endOfBufferToBeParsedNextTime = ''; } if (this.planBuilder.getSteps().length > 0 || this.plans.length < ((_a = this.options.minimumPlansExpected) !== null && _a !== void 0 ? _a : 1)) { this.plans.push(this.planBuilder.build(this.domain, this.problem)); this.planBuilder = new PddlPlanBuilder_1.PddlPlanBuilder(this.options.epsilon); } else { // patch the previous plan metric and makespan if printed after the plan if (this.plans.length > 0) { const lastPlan = this.plans[this.plans.length - 1]; if (this.planBuilder.getMetric() !== undefined && !lastPlan.isMetricDefined()) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion lastPlan.metric = this.planBuilder.getMetric(); } } } if (this.onPlanReady) { this.onPlanReady.apply(this, [this.plans]); } } /** Gets current plan's provisional makespan. */ getCurrentPlanMakespan() { return this.planBuilder.getMakespan(); } /** * Gets all plans. */ getPlans() { return this.plans; } static parseOnePlan(planText, planUri, epsilon) { const dummyDomain = new DomainInfo_1.DomainInfo(planUri, 1, 'domain', PddlSyntaxTree_1.PddlSyntaxTree.EMPTY, new DocumentPositionResolver_1.SimpleDocumentPositionResolver('')); const dummyProblem = new ProblemInfo_1.ProblemInfo(planUri, 1, 'problem', 'domain', PddlSyntaxTree_1.PddlSyntaxTree.EMPTY, new DocumentPositionResolver_1.SimpleDocumentPositionResolver('')); const parser = new PddlPlannerOutputParser(dummyDomain, dummyProblem, { minimumPlansExpected: 1, epsilon: epsilon }); parser.appendBuffer(planText); parser.onPlanFinished(); const plans = parser.getPlans(); if (plans.length === 1) { return plans[0]; } else { throw new Error(`Unexpected number of expected plans (${plans.length}) in file ${planUri.toString()}.`); } } } exports.PddlPlannerOutputParser = PddlPlannerOutputParser; //# sourceMappingURL=PddlPlannerOutputParser.js.map