UNPKG

pddl-workspace

Version:
358 lines 21.3 kB
"use strict"; /* -------------------------------------------------------------------------------------------- * Copyright (c) Jan Dolejsi. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.JobSchedulingSyntaxInjector = void 0; const Compilations_1 = require("../Compilations"); const expression_1 = require("../expression"); const language_1 = require("../language"); const parser_1 = require("../parser"); const SyntaxInjector_1 = require("./SyntaxInjector"); /** Injects auto-generated code triggered by the :job-scheduling requirement/ontology. */ class JobSchedulingSyntaxInjector extends SyntaxInjector_1.BaseSyntaxInjector { process(domainInfo, positionResolver) { if (!domainInfo.getRequirements().includes(JobSchedulingSyntaxInjector.JOB_SCHEDULING)) { return; } this.replaceRequirement(domainInfo, positionResolver); this.injectTypes(domainInfo, positionResolver); this.injectPredicatesAndFunctions(domainInfo, positionResolver); if (!domainInfo.getActions().find(a => a.name === 'move')) { this.injectMoveAction(domainInfo, positionResolver); } } replaceRequirement(domainInfo, positionResolver) { const origRequirements = new Set(domainInfo.getRequirements()); const replacementRequirements = JobSchedulingSyntaxInjector.JOB_SCHEDULING_IMPLIED_REQS .filter(r => !origRequirements.has(r)) .join(' '); const requirementsNode = domainInfo.getRequirementsNode(); if (!requirementsNode) { return; } const jobSchedulingNode = requirementsNode.getChildren() .find(node => node.getToken().tokenText.toLowerCase() === ':job-scheduling'); if (!jobSchedulingNode) { return; } const replacement = new Compilations_1.CodeReplacement({ origCode: jobSchedulingNode.getToken().tokenText, newCode: replacementRequirements, documentation: { title: 'Implied requirements' }, offset: this.getOffset(jobSchedulingNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.OutsideStart }), reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, }); domainInfo.getCompilations().add(replacement); } injectPredicatesAndFunctions(domainInfo, positionResolver) { var _a, _b, _c, _d, _e, _f; const predicates = [ JobSchedulingSyntaxInjector.IS_AVAILABLE_PREDICATE, JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE, JobSchedulingSyntaxInjector.CONTAINS_PREDICATE, JobSchedulingSyntaxInjector.BUSY_PREDICATE ]; const functions = [ JobSchedulingSyntaxInjector.TRAVEL_TIME_FUNCTION, JobSchedulingSyntaxInjector.TIME_STEPS_PER_DAY_FUNCTION, JobSchedulingSyntaxInjector.TIME_STEP_IN_DAYS_FUNCTION, ]; const resourceTypes = new Set(domainInfo.getTypesInheritingFromPlusSelf(JobSchedulingSyntaxInjector.RESOURCE)); const locationTypes = new Set(domainInfo.getTypesInheritingFromPlusSelf(JobSchedulingSyntaxInjector.LOCATION)); const jobDecorations = ((_a = domainInfo.getJobs()) !== null && _a !== void 0 ? _a : []) .map(j => this.compileJob(j, locationTypes, resourceTypes, positionResolver)); jobDecorations.forEach(jd => { predicates.push(...jd.generatedPredicates); functions.push(...jd.generatedFunctions); }); // inject the accumulated predicates this.injectVariables(domainInfo.getPredicatesNode(), (_c = (_b = domainInfo.getConstantsNode()) !== null && _b !== void 0 ? _b : domainInfo.getTypesNode()) !== null && _c !== void 0 ? _c : domainInfo.getRequirementsNode(), positionResolver, predicates, 'Predicates', 'predicates', (i) => domainInfo.injectPredicates(i)); // inject the accumulated functions this.injectVariables(domainInfo.getFunctionsNode(), (_f = (_e = (_d = domainInfo.getPredicatesNode()) !== null && _d !== void 0 ? _d : domainInfo.getConstantsNode()) !== null && _e !== void 0 ? _e : domainInfo.getTypesNode()) !== null && _f !== void 0 ? _f : domainInfo.getRequirementsNode(), positionResolver, functions, 'Functions', 'functions', (i) => domainInfo.injectFunctions(i)); jobDecorations .flatMap(jd => jd.injections) .forEach(c => domainInfo.getCompilations().add(c)); } injectVariables(variablesNode, precedingNode, positionResolver, variables, docTitle, pddlPrefix, injectionMethod) { const doc = { title: this.createHoverTitle(docTitle) }; if (variablesNode) { injectionMethod(new Compilations_1.VariableDeclarationsInjection({ documentation: doc, offset: this.getOffset(variablesNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideEnd }), variables: variables, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING })); } else if (precedingNode) { injectionMethod(new Compilations_1.VariableDeclarationsInjection({ documentation: doc, offset: this.getOffset(precedingNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.OutsideEnd }), variables: variables, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, prefix: `(:${pddlPrefix} `, suffix: ')', })); } } injectTypes(domainInfo, positionResolver) { const types = domainInfo.getTypeInheritance(); types.addEdge(JobSchedulingSyntaxInjector.AVAILABLE, parser_1.PddlInheritanceParser.OBJECT); types.addEdge(JobSchedulingSyntaxInjector.LOCATION, JobSchedulingSyntaxInjector.AVAILABLE); types.addEdge(JobSchedulingSyntaxInjector.RESOURCE, JobSchedulingSyntaxInjector.AVAILABLE); const typesNode = domainInfo.getTypesNode(); const hover = this.createHoverTitle('Types'); const injectedCode = `${JobSchedulingSyntaxInjector.LOCATION} ${JobSchedulingSyntaxInjector.RESOURCE} - ${JobSchedulingSyntaxInjector.AVAILABLE}`; if (typesNode) { domainInfo.getCompilations().add(new Compilations_1.PddlCodeInjection({ documentation: { title: hover }, offset: this.getOffset(typesNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideStart }), code: injectedCode, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } else { const precedingNode = domainInfo.getRequirementsNode(); precedingNode && domainInfo.getCompilations().add(new Compilations_1.PddlCodeInjection({ documentation: { title: hover }, offset: this.getOffset(precedingNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.OutsideEnd }), code: `(:types ${injectedCode})`, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } } compileJob(job, locationTypes, resourceTypes, positionResolver) { var _a, _b, _c; const decoration = new JobDecoration(); const actionNode = job.actionNode; const parametersNode = job.parametersNode; if (!actionNode || !parametersNode) { return decoration; } // replace :job by :durative-action decoration.add(new Compilations_1.CodeReplacement({ origCode: actionNode.getToken().tokenText, newCode: ':durative-action ', offset: actionNode.getStart() + 1, documentation: { title: 'Job is a simplified durative action', codeblock: `:durative-action`, }, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING })); if (!job.duration) { const durationDef = ':duration ' + new expression_1.EqualityNode(new expression_1.DurationExpressionNode(), new expression_1.VariableNode(decoration.createDurationVariable(job, resourceTypes))).toPddlString(); decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset(parametersNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.OutsideEnd }), code: durationDef, documentation: { title: 'Suggested job duration definition', codeblock: durationDef }, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } const availabilityVariables = []; // the location shall be available const locationParameter = job.parameters.find(p => locationTypes.has(p.type)); if (locationParameter) { const locationIsAvailable = JobSchedulingSyntaxInjector.IS_AVAILABLE_PREDICATE.bind([locationParameter]); availabilityVariables.push(locationIsAvailable); } const resourcesAtLocation = []; // all resources shall be available and at the location job.parameters .filter(p => resourceTypes.has(p.type)) .forEach(p => { const resourceIsAvailable = JobSchedulingSyntaxInjector.IS_AVAILABLE_PREDICATE.bind([p]); availabilityVariables.push(resourceIsAvailable); if (locationParameter) { const resourceAtLocation = JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE.bind([p, locationParameter]); resourcesAtLocation.push(resourceAtLocation); } }); const conditions = [...availabilityVariables.map(v => (0, expression_1.overAll)((0, expression_1.expression)(v)))]; conditions.push(...resourcesAtLocation.map(p => (0, expression_1.overAll)((0, expression_1.expression)(p)))); const jobStarted = decoration.createActionPredicate(job, JobSchedulingSyntaxInjector.JOB_STARTED_SUFFIX, resourceTypes); const jobDone = decoration.createActionPredicate(job, JobSchedulingSyntaxInjector.JOB_DONE_SUFFIX, resourceTypes); conditions.push((0, expression_1.atStart)((0, expression_1.not)(jobStarted)), (0, expression_1.atStart)((0, expression_1.not)(jobDone))); const effects = []; effects.push((0, expression_1.atStart)((0, expression_1.expression)(jobStarted)), (0, expression_1.atEnd)((0, expression_1.expression)(jobDone))); availabilityVariables.forEach(e => { effects.push((0, expression_1.atStart)((0, expression_1.not)(e))); effects.push((0, expression_1.atEnd)((0, expression_1.expression)(e))); }); const conditionDocumentation = { title: 'Auto-generated conditions', codeblock: conditions.map(c => c.toPddlString()).join('\n'), }; if (job.condition) { const conjunction = job.condition.getFirstOpenBracket('and'); if (conjunction) { // inject into the :condition (and ...) conjunction decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset(conjunction, positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideEnd }), code: conditions.map(c => c.toPddlString()).join(' '), documentation: conditionDocumentation, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } else { // inject into :condition decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset(job.condition, positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideEnd }), code: (0, expression_1.and)(conditions).toPddlString(), documentation: conditionDocumentation, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } } else { // inject the :condition to the end of the action decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset((_a = job.duration) !== null && _a !== void 0 ? _a : parametersNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.OutsideEnd }), code: ':condition ' + (0, expression_1.and)(conditions).toPddlString(), documentation: conditionDocumentation, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } const effectDocumentation = { title: 'Auto-generated effect', codeblock: effects.map(e => e.toPddlString()).join('\n'), }; if (job.effect) { const conjunction = job.effect.getFirstOpenBracket('and'); if (conjunction) { // inject into the :effect (and ...) conjunction decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset(conjunction, positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideEnd }), code: effects.map(c => c.toPddlString()).join(' '), documentation: effectDocumentation, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } else { // inject into the :effect decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset(job.effect, positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideEnd }), code: (0, expression_1.and)(effects).toPddlString(), documentation: effectDocumentation, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } } else { // inject the :effect to the end of the action decoration.add(new Compilations_1.PddlCodeInjection({ offset: this.getOffset((_c = (_b = job.condition) !== null && _b !== void 0 ? _b : job.duration) !== null && _c !== void 0 ? _c : parametersNode, positionResolver, { position: SyntaxInjector_1.InjectionPosition.OutsideEnd }), code: ':effect ' + (0, expression_1.and)(effects).toPddlString(), documentation: effectDocumentation, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } return decoration; } injectMoveAction(domainInfo, positionResolver) { const resParam = new language_1.Parameter('res', JobSchedulingSyntaxInjector.RESOURCE); const fromParam = new language_1.Parameter('from', JobSchedulingSyntaxInjector.LOCATION); const toParam = new language_1.Parameter('to', JobSchedulingSyntaxInjector.LOCATION); const params = `(${resParam.toPddlString()} ${language_1.Parameter.createPddlString(fromParam, toParam)})`; const durationVar = JobSchedulingSyntaxInjector.TRAVEL_TIME_FUNCTION.bind([resParam, fromParam, toParam]); const duration = new expression_1.EqualityNode(new expression_1.DurationExpressionNode(), new expression_1.VariableNode(durationVar)).toPddlString(); const condition = (0, expression_1.and)([ (0, expression_1.atStart)((0, expression_1.not)(JobSchedulingSyntaxInjector.BUSY_PREDICATE.bind([resParam]))), (0, expression_1.atStart)((0, expression_1.expression)(JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE.bind([resParam, fromParam]))), ]).toPddlString(); const effect = (0, expression_1.and)([ (0, expression_1.atStart)((0, expression_1.not)(JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE.bind([resParam, fromParam]))), (0, expression_1.atStart)((0, expression_1.expression)(JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE.bind([resParam, toParam]))), ]).toPddlString(); const moveAction = `(:durative-action move :parameters ${params} :duration ${duration} :condition ${condition} :effect ${effect})`; domainInfo.getCompilations().add(new Compilations_1.CodeInjection({ offset: this.getOffset(domainInfo.syntaxTree.getDefineNode(), positionResolver, { position: SyntaxInjector_1.InjectionPosition.InsideEnd }), code: moveAction, documentation: { title: this.createHoverTitle('Resource move action') }, doesNotRequireWhitespaceSurrounding: true, reason: JobSchedulingSyntaxInjector.JOB_SCHEDULING, })); } createHoverTitle(generatedEntitiesName) { return generatedEntitiesName + " auto-generated because of the `" + JobSchedulingSyntaxInjector.JOB_SCHEDULING + "` requirement:"; } } exports.JobSchedulingSyntaxInjector = JobSchedulingSyntaxInjector; /* TYPES */ JobSchedulingSyntaxInjector.AVAILABLE = 'available'; JobSchedulingSyntaxInjector.RESOURCE = 'resource'; JobSchedulingSyntaxInjector.LOCATION = 'location'; /* PREDICATE NAMES */ JobSchedulingSyntaxInjector.IS_AVAILABLE_PREDICATE_NAME = 'is_available'; JobSchedulingSyntaxInjector.IS_AVAILABLE_PREDICATE = language_1.Variable.from(JobSchedulingSyntaxInjector.IS_AVAILABLE_PREDICATE_NAME, [ new language_1.Parameter('a', JobSchedulingSyntaxInjector.AVAILABLE) ]); JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE_NAME = 'located_at'; /** (located_at ?r - resource ?l - location) */ JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE = language_1.Variable.from(JobSchedulingSyntaxInjector.LOCATED_AT_PREDICATE_NAME, [ new language_1.Parameter('r', JobSchedulingSyntaxInjector.RESOURCE), new language_1.Parameter('l', JobSchedulingSyntaxInjector.LOCATION) ]); JobSchedulingSyntaxInjector.BUSY_PREDICATE_NAME = 'busy'; /** (busy ?r - resource) */ JobSchedulingSyntaxInjector.BUSY_PREDICATE = language_1.Variable.from(JobSchedulingSyntaxInjector.BUSY_PREDICATE_NAME, [ new language_1.Parameter('r', JobSchedulingSyntaxInjector.RESOURCE) ]); JobSchedulingSyntaxInjector.CONTAINS_PREDICATE_NAME = "contains"; /** (contains ?parent ?child - location) */ JobSchedulingSyntaxInjector.CONTAINS_PREDICATE = language_1.Variable.from(JobSchedulingSyntaxInjector.CONTAINS_PREDICATE_NAME, [ new language_1.Parameter('parent', JobSchedulingSyntaxInjector.LOCATION), new language_1.Parameter('child', JobSchedulingSyntaxInjector.LOCATION), ]); JobSchedulingSyntaxInjector.JOB_STARTED_SUFFIX = '_job_started'; JobSchedulingSyntaxInjector.JOB_DONE_SUFFIX = '_job_done'; /* FUNCTION NAMES */ JobSchedulingSyntaxInjector.JOB_DURATION_SUFFIX = '_job_duration'; JobSchedulingSyntaxInjector.TRAVEL_TIME = 'travel_time'; /** (travel_time ?r - resource ?from ?to - location) */ JobSchedulingSyntaxInjector.TRAVEL_TIME_FUNCTION = language_1.Variable.from(JobSchedulingSyntaxInjector.TRAVEL_TIME, [ new language_1.Parameter('r', JobSchedulingSyntaxInjector.RESOURCE), new language_1.Parameter('from', JobSchedulingSyntaxInjector.LOCATION), new language_1.Parameter('to', JobSchedulingSyntaxInjector.LOCATION) ]); JobSchedulingSyntaxInjector.TIME_STEPS_PER_DAY = 'time_steps_per_day'; JobSchedulingSyntaxInjector.TIME_STEP_IN_DAYS = 'time_step_in_days'; /** (time_steps_per_day) ; number of time steps per day */ JobSchedulingSyntaxInjector.TIME_STEPS_PER_DAY_FUNCTION = language_1.Variable.from(JobSchedulingSyntaxInjector.TIME_STEPS_PER_DAY, []); /** (time_step_in_days) ; time step length in [day] unit */ JobSchedulingSyntaxInjector.TIME_STEP_IN_DAYS_FUNCTION = language_1.Variable.from(JobSchedulingSyntaxInjector.TIME_STEP_IN_DAYS, []); JobSchedulingSyntaxInjector.JOB_SCHEDULING = ':job-scheduling'; /** PDDL Requirements that are implied by the :job-scheduling and therefore should be inserted in its place */ JobSchedulingSyntaxInjector.JOB_SCHEDULING_IMPLIED_REQS = [ ':strips', ':fluents', ':durative-actions', ':typing', ':negative-preconditions' ]; class JobDecoration { constructor() { this.injections = []; this.generatedPredicates = []; this.generatedFunctions = []; } add(injection) { this.injections.push(injection); } createDurationVariable(action, resourceTypes) { const suffix = JobSchedulingSyntaxInjector.JOB_DURATION_SUFFIX; return this.createActionFunction(action, suffix, resourceTypes); } createActionFunction(action, suffix, resourceTypes) { const newFunction = this.createActionVariable(action, suffix, resourceTypes); this.generatedFunctions.push(newFunction); return newFunction; } createActionPredicate(action, suffix, resourceTypes) { const newPredicate = this.createActionVariable(action, suffix, resourceTypes); this.generatedPredicates.push(newPredicate); return newPredicate; } createActionVariable(action, suffix, resourceTypes) { return language_1.Variable.from(action.name + suffix, action.parameters.filter(p => !resourceTypes.has(p.type))); } } //# sourceMappingURL=JobSchedulingSyntaxInjector.js.map