pddl-workspace
Version:
111 lines • 4.51 kB
JavaScript
/* --------------------------------------------------------------------------------------------
* Copyright (c) Jan Dolejsi. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.SearchStateToPlan = void 0;
const __1 = require("..");
const utils_1 = require("../utils");
/** Extracts `Plan` from a `SearchState`. */
class SearchStateToPlan {
constructor(domain, problem, epsilon = 1e-3) {
this.domain = domain;
this.problem = problem;
this.epsilon = epsilon;
}
convert(state) {
var _a;
const totalPlan = state.getTotalPlan();
// all happenings except for ENDs
const planStepBuilders = totalPlan
.filter(happening => happening.kind !== __1.HappeningType.END)
.map(happening => PlanStepBuilder.fromStart(happening));
// now associate all ends with the corresponding starts
totalPlan
.filter(happening => happening.kind === __1.HappeningType.END)
.forEach(endHappening => SearchStateToPlan.associate(endHappening, planStepBuilders));
const planSteps = planStepBuilders.map(step => step.toPlanStep(state.earliestTime, this.epsilon));
const helpfulActions = (_a = state.helpfulActions) !== null && _a !== void 0 ? _a : [];
return new __1.Plan(planSteps, this.domain, this.problem, state.earliestTime, helpfulActions);
}
static associate(endHappening, planSteps) {
const correspondingStart = planSteps.find(step => step.correspondsToEnd(endHappening) && !step.hasEnd());
if (!correspondingStart) {
throw new Error("Cannot find start corresponding to: " + endHappening.actionName);
}
correspondingStart.setEnd(endHappening);
}
}
exports.SearchStateToPlan = SearchStateToPlan;
/** Helps pairing corresponding start and end happenings. */
class PlanStepBuilder {
constructor(start) {
this.start = start;
}
static fromStart(happening) {
return new PlanStepBuilder(happening);
}
/**
* Sets corresponding end happening.
* @param endHappening corresponding end happening
*/
setEnd(endHappening) {
this.end = endHappening;
}
hasEnd() {
return !!this.end;
}
/**
* Checks whether the given endHappening corresponds to this start.
* @param endHappening end happening to test
*/
correspondsToEnd(endHappening) {
const matchingName = (0, utils_1.equalsCaseInsensitive)(this.start.actionName, endHappening.actionName);
if (!matchingName) {
return false;
}
if (endHappening.shotCounter === -1) {
return this.end === undefined;
}
else {
return this.start.shotCounter === endHappening.shotCounter;
}
}
getIterations() {
var _a, _b;
return Math.max(this.start.iterations, (_b = (_a = this.end) === null || _a === void 0 ? void 0 : _a.iterations) !== null && _b !== void 0 ? _b : 1);
}
toPlanStep(stateTime, epsilon) {
const isDurative = this.start.kind === __1.HappeningType.START;
let duration = epsilon;
if (isDurative) {
if (this.end) {
duration = this.end.earliestTime - this.start.earliestTime;
}
else {
// the end was not set yet (perhaps this was a dead end state and there was no relaxed plan at all)
duration = stateTime - this.start.earliestTime + stateTime * .1;
}
}
const commitment = this.getCommitment(isDurative);
return new __1.PlanStep(this.start.earliestTime, this.start.actionName, isDurative, duration, -1, commitment, this.getIterations());
}
getCommitment(isDurative) {
if (this.end && !this.end.isRelaxed) {
return __1.PlanStepCommitment.Committed;
}
else if (!this.start.isRelaxed) {
if (isDurative) {
return __1.PlanStepCommitment.EndsInRelaxedPlan;
}
else {
return __1.PlanStepCommitment.Committed;
}
}
else {
return __1.PlanStepCommitment.StartsInRelaxedPlan;
}
}
}
//# sourceMappingURL=SearchStateToPlan.js.map