pddl-workspace
v11.2.0
Published
PDDL Workspace
Downloads
1,638
Readme
PDDL parsing and workspace
Install this package using npm install pddl-workspace
.
PDDL Parser
Disclaimer: this is not a full PDDL syntax parser. Its purpose is to provide language support in VS Code, so mode than a parser, it is a syntax tree builder. In other words, the parser does not give access to complete PDDL object model, but works even in incomplete or syntactically incorrect documents. You could however successfully use it to extract predicates, functions, actions from the PDDL files.
Example usage:
import { parser, DomainInfo, ProblemInfo, Plan, Happening, HappeningType, utils } from 'pddl-workspace';
const domain = parser.PddlDomainParser.parseText(domainText);
const problem = await parser.PddlProblemParser.parseText(problemText);
const epsilon = 0.001;
const planText = `
;;!domain: domain1
;;!problem: problem1
0.00100: (action p1 p2) [10.00]
; Makespan: 10.001
; Cost: 123.456
; States evaluated: 2`;
const plan = new parser.PddlPlanParser().parseText(planText, epsilon);
Many more usage scenarios are exercised in the unit tests in the test
folder.
Plans may appear in number of different formats. Following forms are supported:
(action)
(action objects)
time: (action)
time: (action) [duration]
time: (action) [D:<duration>; C:<actionCost>]
PDDL Numeric Expression Parser
PDDL problem files support multiple (:metric )
elements (because VAL does as well).
The numeric expression inside the metric is parsed to a syntax tree. The parser is available:
const expressionPddl = "(/ (- (cost) (minCost)) 2)";
const expression = createNumericExpressionParser(expressionPddl).getExpression();
const division = expression as Division;
division.getVariableNames(); // returns ['cost', 'minCost']
const context = new ValueMap("cost", 3, "minCost", 2);
division.evaluate(context); // returns 0.5
function createNumericExpressionParser(metricPddl: string): NumericExpressionParser {
const syntaxTree = new PddlSyntaxTreeBuilder(metricPddl).getTree();
return new NumericExpressionParser(
syntaxTree.getRootNode().getSingleNonWhitespaceChild());
}
PDDL Workspace
The workspace groups features necessary for interactive authoring of PDDL files.
And management of such files. The PddlWorkspace
class is used by the VS Code PDDL extension.
import { URI } from 'vscode-uri';
const pddlWorkspace = new PddlWorkspace(1e-3);
const insertedFiles: FileInfo[] = [];
// get notified about new/updated files
pddlWorkspace.on(PddlWorkspace.INSERTED, (file: FileInfo) => {
console.log(`Inserted: '${file.name}' from ${file.fileUri}.`);
})
pddlWorkspace.on(PddlWorkspace.UPDATED, (file: FileInfo) => {
console.log(`Updated: '${file.name}' from ${file.fileUri}.`);
})
const pddlDomainText = `(define (domain domain_name) )`;
const pddlProblemText = `(define (problem p1) (:domain domain_name))`;
// WHEN
const domainInfo = await pddlWorkspace.upsertFile(
URI.parse('file:///folder1/domain.pddl'),
PddlLanguage.PDDL,
1, // content version
pddlDomainText,
new SimpleDocumentPositionResolver(pddlDomainText));
const problemInfo = await pddlWorkspace.upsertFile(
URI.parse('file:///folder1/problem.pddl'),
PddlLanguage.PDDL,
1, // content version
pddlProblemText,
new SimpleDocumentPositionResolver(pddlProblemText));
const correspondingDomain = pddlWorkspace.getDomainFileFor(problemInfo as ProblemInfo);
// now do something like `solve(correspondingDomain, problemInfo)`
Extending PDDL Workspace with custom syntaxes and functionality
Creators of non-standard PDDL syntaxes, parsers, planning enginens can inject
their extensions to the PddlWorkspace
. Here is how (full working code is in CustomPddlParserExtension.ts
):
class CustomPddlFile extends FileInfo {
getLanguage(): PddlLanguage {
return PddlLanguage.PDDL;
}
}
class CustomParser extends PddlFileParser<CustomPddlFile> {
async tryParse(fileUri: URI, fileVersion: number, fileText: string, syntaxTree: PddlSyntaxTree, positionResolver: DocumentPositionResolver): Promise<CustomPddlFile | undefined> {
if ('(:custom-pddl') {
return new CustomPddlFile(fileUri, fileVersion, 'custom', syntaxTree, positionResolver);
}
}
}
class CustomExtension implements PddlWorkspaceExtension {
getPddlParsers(): PddlFileParser<FileInfo>[] | undefined {
return [new CustomParser()];
}
}
const pddlWorkspace = new PddlWorkspace(1e-3);
pddlWorkspace.addExtension(new CustomExtension());
const pddlText = `(:custom-pddl)`;
// WHEN
const parsedFile = await pddlWorkspace.upsertFile(URI.parse('file:///test'), PddlLanguage.PDDL, 1, pddlText, new SimpleDocumentPositionResolver(pddlText));
Extending PDDL VS Code Extension with custom planner configuration providers
The pddl-workspace
package is the external API of the PDDL VS Code extension.
To make it convenient for your users to configure and use your planner in VS Code,
implement the PlannerProvider
interface (see full working code in CustomPlannerProvider.ts
):
export const plannerKind = new planner.PlannerKind("my-planning-service");
export class SolveServicePlannerProvider implements planner.PlannerProvider {
get kind(): planner.PlannerKind {
return plannerKind;
}
getNewPlannerLabel(): string {
return "$(cloud-upload) Input a planning service URL...";
}
async configurePlanner(previousConfiguration?: planner.PlannerConfiguration): Promise<planner.PlannerConfiguration | undefined> {
const existingValue = previousConfiguration?.url ?? "http://solver.planning.domains/solve";
const previouslyUsedUri = URI.parse(existingValue);
console.log(`Previously, you configured ${previouslyUsedUri.toString()}, what do you want to change it to?`);
// let's pretend the user entered 'http://solver.planning.domains/solve'
const newPlannerUrl = 'http://solver.planning.domains/solve';
return this.createPlannerConfiguration(newPlannerUrl);
}
createPlannerConfiguration(newPlannerUrl: string): planner.PlannerConfiguration {
return {
kind: this.kind.kind,
url: newPlannerUrl,
title: newPlannerUrl,
canConfigure: true
};
}
}
/**
* Example custom Planner Provider extension.
*/
export class CustomPlannerProviderExtension implements PddlWorkspaceExtension {
getPlannerProvider(): PlannerProvider[] | undefined {
return [new SolveServicePlannerProvider()];
}
}
Starting from version 3.5.0, the PlannerProvider
may optionally also implement custom creation of the Planner
. Here is an example for composing java -jar xyz.jar
command-line:
createPlanner(configuration: planner.PlannerConfiguration, , plannerInvocationOptions: planner.PlannerRunConfiguration): planner.Planner {
return new PlannerExecutable(`java -jar ${configuration.path}`, plannerInvocationOptions.options, configuration.syntax, plannerInvocationOptions.workingDirectory);
}
Compiling and contributing
Install node.js 18.16.