pddl-workspace
Version:
166 lines • 7.11 kB
JavaScript
"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