Specification of the Process Specification Language (PSL)

Version: 0.98

by:

Krishna N. Jha

ACT, Boeing Corp., Philadelphia, PA

for NIST

Aug. 17, 98

# PSL Syntax

## Notational Convention

We present the PSL syntax in extended BNF format, marked up for easier
readability. (The exact, unadulterated syntax in the BNF format is
provided in the appendix.) We follow the following notational guidelines
in the syntax specification:

1.  The reserved words (e.g. **And**) , operators (e.g. **+** ) and
    other key-symbols (e.g. **:** ) are highlighted with **Bold**
    formatting.

2.  The terminals begin with uppercase letters, non-terminals begin with
    lowercase letters.

3.  In extended BNF, the following notational convention is used:

-   \[ X \] denotes an optional X i.e. 0 or 1 occurrence of X ;

-   X\* or {X}\* denotes optionally multiple X i.e. 0 or more
    occurrences of X ;

-   X+ or {X}+ denotes potentially multiple X i.e. 1 or more occurrences
    of X ;

1.  A list (e.g. *var1, var2, var3* ) of elements represented by
    (syntax-)symbol X is represented as: *List*\^X. This is a shorthand
    for the following high-level extra-BNF rule:

    *List*\^X : *List*\^X **,** X

    \| X

    \|

    ;

2.  A set (e.g. *\[var1, var2, var3\]* ) of elements represented by
    (syntax-)symbol X is represented as: *Set*\^X. This is a shorthand
    for the following high-level extra-BNF rule:

    *Set*\^X : **\[** *List*\^X **\]**

    ;

3.  To improve the readability of the syntax-rules, we often delete the
    ending **;** of a syntax-rule-specification if such an action
    introduces no ambiguity in the reading of the rule.

## The Syntax

psl : global\*

\| class\*

;

global : **Annotation:** *Set*\^ itemValuePair**;**

> \| **Ontology:** *Set*\^ itemValuePair **;**

;

class: **Class** className \[ **:** className **(** *List***\^**arg
**)** \]

> **Annotation:** *Set*\^ itemValuePair**;**
>
> **Ontology:** *Set*\^ itemValuePair **;**
>
> **Parameters** **:** *List*\^varDefinition **;**
>
> \[ **Variables:** *List*\^varDefinition **;** \]
>
> { attribute **;** }\*
>
> **EndClass**

className : Symbol

attribName : Symbol

attribute : attribName **:** valuesAttribute

\| attribName **:** conditionAttribute

\| attribName **:** processStepsAttribute

valuesAttribute : **Values** **:** \[ guardCondition \] **:**
*List***\^**value

conditionAttribute : **Condition** **:** \[ guardCondition \] **:**
condition

processStepsAttribute : **ProcessSteps** **:** \[ guardCondition \]
**:** processStepList

guardCondition : condition

;

itemValuePair: itemName **:** value

itemName : Symbol

label : Symbol

processStepList: processStepList **,** processStep

\| processStepList **\|** processStep

\| processStep

processStep : **(** processStepList **)**

\| basicStep \[**:** label \]

basicStep : **If** **(** condition **:** thenProcessStepList \[ **:**
elseProcessStepList \] **)**

\| **While** **(** condition **:** processStepList **)**

\| predicateName **(** *List***\^**arg **)**

\| value \[ **=** value \]

thenProcessStepList : processStepList

elseProcessStepList : processStepList

varDefinition : baseVarDefinition \[ **=** value \]

baseVarDefinition : varName **:** className **(** *List***\^**arg **)**
\[ **\[** expr **\]** \]

\| varName **:** baseType

baseType : **Integer**

\| **Real**

\| **Boolean**

\| **Symbol**

condition : logical_expr

;

arg : \[ varName **:** \] value

value : expr

\| valueSet

valueSet : **\[** *List***\^**value **\]**

varSet : **\[** *List*\^varName **\]**

;

expr : expr **+** expr

\| expr **-** expr

\| expr **\*** expr

\| expr **/** expr

\| **-** expr

\| **(** expr **)**

\| baseExpr

baseExpr : baseLhsValue

\| baseLhsValue **\[** *List*\^expr **\]**

\| predicateName **(** *List*\^arg **)**

\| number

baseLhsValue: varName /\* e.g. acctgDept \*/

\| VarAttribName /\* e.g. acctgDept.DeptNumber \*/

constant : number

\| String

number : Integer

\| Real

varName : Symbol

;

logical_expr : logical_expr **And** logical_expr

\| logical_expr **Or** logical_expr

\| **Not** logical_expr

\| **(** logical_expr **)**

\| comparison

\| expr

\| **True**

\| **False**

comparison : expr **==** expr

\| expr **\>=** expr

\| expr **\>** expr

\| expr **\<=** expr

\| expr **\<** expr

\| expr **=/=** expr

predicateName: Symbol

;

## The Lexicon

The various components of the PSL lexicon are shown below.

### Reserved Words

**And**

**Annotation**

**Condition**

**Class**

**EndClass**

**If**

**False**

**Integer**

**Not**

**Ontology**

**Or**

**Parameters**

**ProcessSteps**

**Real**

**Symbol**

**True**

**Values**

**Variables**

**While**

### Symbolic Operators

**=**

**+**

**-**

**\***

**/**

**==**

**=/=**

**\<**

**\>**

**\<=**

**\>=**

**:**

**;**

**,**

**\|**

**.**

**(**

**)**

**\[**

**\]**

### Variable Names

The variable names (including the class-names) begin with an alphabetic
character, followed by any number of alphanumeric or underscore (i.e. \_
) characters.

### Numbers

A number may be an integer (e.g. 123) or a real (e.g. 12.54) number.

### String

A string is a sequence of characters enclosed within matching
single-quotes (i.e. **'** ) or double-quotes (i.e. **"** ). A string may
not contain a quote. A string may span over multiple lines.

### Predicate Names

The predicate names, similar to the variable names, begin with an
alphabetic character, followed by any number of alphanumeric or
underscore (i.e. \_ ) characters.

### VarAttribName: Accessing Object Attribute

An attribute (e.g. Attrib) of an object (e.g. Obj) is referenced using
the dot (i.e. **.** ) operator (e.g. Obj**.**Attrib) . Within a class,
one refers to its own attributes simply by name e.g. within a class with
attribute Attrib, one can refer to the attribute as Attrib. (Note that
this implies that the variable-names and the attribute-names must be
different from each other i.e. the same name-space contains the
variable-names and the attribute-names.)

# PSL Semantics

## Global attributes

A PSL file may contain two kinds of global attributes: **Annotation**,
and **Ontology**.

An **Annotation** attribute provides an informal documentation for the
PSL file. An item in an item-value-pair is a user-defined name e.g.
Description, or Author. An example of annotation is : *\[Description: "A
PSL-file for drilling processes."\].*

An **Ontology** attribute specifies the default ontology for all the
classes in the PSL file which do not specify an ontology themselves. If
a class itself specifies an ontology, the class-specified ontology
augments the default ontology for that class if there are no conflicts.
If there are conflicts between the two ontologies, the class-specified
ontology supersedes the default ontology for that class.

## Classes and Objects

A class represents a related set of attributes of type: **Values**,
**Condition**, and **ProcessSteps**. A small number of attributes are
predefined in the language, others can be defined by the users.

### The Types of Class Attributes

The different types of user-definable attributes in a class are:

1.  **Values** attribute: This attribute takes a list of values
    (including only one value) as its attribute-value. On being accessed
    through the use of the dot operator on the object (e.g.
    Object**.**attribName), when the attribute is valid (i.e. the
    associated guard-condition is true), it unifies with the set
    (including a single value) of the associated values.

    For example, assuming an object *Obj* has an unguarded **Values**
    attribute: *Coordinate* containing a list of values: *X, Y, Z*, the
    expression *Obj.Coordinate* unifies with the set of the values of X,
    Y, and Z from the object Obj e.g. *\[2.5, 4, 3.6 \]* . (In case a
    single value is associated with the **Values** attribute, a single
    value (rather than a set of one element) is unified with.)

2.  **Condition** attribute: This attribute takes a conditional
    expression as its attribute-value. On being accessed through the use
    of the dot operator on the object (e.g. Object**.**attribName), when
    the attribute is valid (i.e. the associated guard-condition is
    true), it unifies with the truth-conditional value (i.e. *True*, or
    *False*) of the associated expression.

    For example, assuming an object *Obj* has an unguarded **Condition**
    attribute *isEqual* with the value: (*X == Y*), invoking
    *Obj**.**isEqual* unifies with the truth-conditionality of the
    conditional expression (X==Y) from the object Obj.

3.  **ProcessSteps** attribute: This attribute takes a list of a
    potential mixture of sequential and parallel process-steps as its
    attribute-value. A guard-condition associated with the
    **ProcessSteps** attribute represents the condition which must be
    true before the first process-step(s) may start. (A class may have a
    maximum of one **ProcessSteps** attribute which is not named after
    itself.) A process-step is represented either through a
    process-instantiation (described later) of a class or through a
    basic process-step. A process-step derived by instantiating a
    (generic) process represents an instance of the (generic) process.

The sequentiality of the process-steps is specified using the **,** and
**\|** operators. Sequential process-steps are specified using the **,**
operator. For example, *Task1 **,** Task2* specifies that *Task1* be
executed before *Task2*. Asynchronous process-steps are specified using
the **\|** operator. For example, *Task1 **\|** Task2* specifies that
*Task1* [and]{.underline} *Task2* may be executed asynchronously. (We
have no PSL-language-provided representation to specify that one of the
tasks: *Task1* [or]{.underline} *Task2* may be executed. We can simulate
that using ontology-provided predicates.)

### Predefined Attributes

The predefined attributes of a class include:

1.  **Annotation**: The value of this attribute is a set of item-value
    pairs describing the class in an informal manner (e.g. for
    documentation). An item in an item-value-pair is a user-defined name
    e.g. Description, or Author. An example of annotation is :
    *\[Description: "A class for the drilling-machines."\].*

2.  **Ontology**: The value of this attribute is a set of item-value
    pairs specifying the ontology needed to interpret the class
    correctly and completely. An item in an item-value-pair is a
    user-defined name e.g. *Version*.

3.  **Parameters**: This attribute contains the definitions of the
    arguments being passed to instantiate the class in order to create
    an object. When creating an instance of a class, one must supply the
    values for the required arguments (i.e. ones without default
    values), and, optionally, the values for the optional arguments
    (i.e. ones with default values). These parameters can be referenced
    inside the class. (The Parameters, in other words, specify the
    arguments to the class.)

    For example, a class may specify the following parameters:

    *distance: integer*, // required argument

    *gasPrice: real = 1.25*; // optional argument

    One can specify the arguments to the class by position (i.e. first
    argument maps to the first parameter, second argument maps to the
    second parameter, and so on), or by parameter-names i.e. using the
    parameter-name **:** argument pairs. All the arguments are passed by
    value only.

4.  **Variables**: This attribute contains the definitions of the
    various objects used in the class. (The Variables, in other words,
    specify the local variables of the class.)

    All the variables used in a class must be defined. A variable used
    in a class must have been defined either in the Variables or in the
    Parameters attribute.

### Objects from Classes

A user can instantiate a class by supplying its arguments using the
scheme: *ClassName*(*argsList*) to create an object from the class. For
example, to create an object of class *Department*, one could use the
expression: *Department*(*Number: "Act123", Name: "Accounting Dept*.").

In PSL, we provide for two kinds of instantiations of a class:
object-instantiation, and process-instantiation. An object-instantiation
occurs when a class is instantiated in **Variables** or **Parameters**
attribute. A process-instantiation occurs when a class is dynamically
instantiated outside of these two attributes e.g. in a **ProcessSteps**
attribute.

The object-instantiation of a class, in the **Variables** or
**Parameters** attribute, entails the following instantiation-steps in
the given sequence:

1.  The class-parameters are mapped with the supplied arguments. If
    arguments are supplied by position, they are mapped by position. If
    the arguments are supplied by name, they are mapped by matching the
    parameter-names.

2.  Its parent class, if any, is instantiated with the specified
    arguments.

3.  The argument-validity-check attribute (i.e. a **Condition**
    attribute named after the class itself) is evaluated for
    truth-conditionality. If the attribute evaluates to true, further
    steps in the instantiation are carried out. Otherwise, if the
    attribute evaluates to false, no further steps in the instantiation
    are carried out, and an appropriately initialized
    *Instantiation-Error-Object* (to be defined in ontology) is
    returned.

4.  The constructor attribute (i.e. a **ProcessSteps** attribute named
    after the class itself), if any, is checked for its associated
    guard-conditions (if any). If the guard-condition of the constructor
    attribute evaluates to true, the associated process-steps are
    evaluated (satisfying the specified steps-ordering) and the next
    instantiation-step is taken only after the evaluation of all the
    process-steps is completed successfully. Otherwise (i.e. the
    guard-condition evaluates to false, or the evaluation of
    process-steps completes unsuccessfully), no further steps in the
    instantiation are carried out, and an appropriately initialized
    *Instantiation-Error-Object* (to be defined in ontology) is
    returned.

5.  An instantiated copy of the class, semantically speaking, is
    provided.

The process-instantiation of a class, outside of the **Variables** or
**Parameters** attribute (e.g. in a **ProcessSteps** attribute), entails
the following instantiation-steps in the given sequence:

1.  The class is object-instantiated as specified above.

2.  The non-constructor **ProcessSteps** attribute (i.e. the
    **ProcessSteps** attributes named not after the class-name itself),
    if any, is checked for its guard-conditions. If the guard-condition
    for a **ProcessSteps** attribute evaluates to true, its associated
    process-steps are ready for evaluation (satisfying the specified
    steps-ordering).

3.  After all the process-steps have been evaluated successfully, it
    evaluates the values from the output attribute (i.e. a **Values**
    attribute named after the class). The values from the output
    attribute are provided as the result of the process-instantiation.

### Specially Named Attributes of the Class

A class may contain attributes named after its class-name. Such
attributes are special in the sense that they are used during
object-instantiation.

1.  A **Condition** attribute named after the class:
    *argument-validity-check* attribute: The conditional expression
    associated with such an attribute is evaluated during
    object-instantiation, and the instantiation proceeds if the
    expression evaluates to true.

2.  A **ProcessSteps** attribute named after the class: *constructor*
    attribute: The process-steps associated with such an attribute are
    evaluated during object-instantiation.

3.  A **Values** attribute named after the class: *output* attribute:
    The values associated with such an attribute are returned at the end
    of a class's evaluation of all its process-steps.

### User-Defined Attributes

A user may define various kinds of attributes in a class. Each attribute
is associated with a condition called the guard-condition. A
user-defined attribute is *valid* only when the associated
guard-condition is true. (When no guard-condition is specified, it is
assumed to be trivially true.) The value(s) returned from an attribute
are valid only when the attribute is valid. The status (e.g. *valid*,
*invalid*) of an attribute (e.g. X) can be determined through the object
*status*(Attribute) (e.g. *status*(X)).

### The Parent Class

A class may optionally specify a parent-class. The class inherits the
user-defined attributes from its parent-class. The attributes of the
class are a union of the inherited attributes and the local attributes.
In case of a conflicting attribute (i.e. the parent class and the local
class both have an attribute with the same name within a section), the
local attribute overrides the parent attribute.

### No Assignment in PSL

No assignments can be carried out using PSL constructs i.e. variables in
PSL may not be reassigned after their first initialization. When an
entity is not modified after its first initialization, we can use the
equality operator (i.e. = ) inside the **ProcessSteps** attribute to
model assignment-like behavior. For example, to specify that the result
of a drilling operation is a hole (say, Hole_1), we can use: DrillOp() =
Hole_1. (Or, equivalently, Hole_1= DrillOp(). ) We can then use Hole_1
in subsequent operations without modifying it e.g. we can specify the
screwing of a bolt (say, Bolt_1) into the hole as: ScrewBolt(Bolt_1,
Hole_1).

What we cannot specify, without resorting to extra-logical operators
(which the ontology, if it so chooses, may provide), is the modification
of a variable using assignment. For example, we [cannot]{.underline}
specify that the result of drilling operation on a part (say, Part_1) is
the part with a hole as: DrillOp(Part_1) = Part_1. This is because the
part is different after the drilling operation (i.e. the part has a new
hole in it) and, as such, is really a different part and must be modeled
as such. Thus, a correct representation for the current example may use
two parts of the same basic type to model the part before drilling and
after drilling. Assuming Part is declared as an array of two element, a
correct specification for this operation may be: DrillOp(Part\[1\]) =
Part\[2\] .

# Sample Examples in PSL

## Example 1: PIF to PSL Representation

We present a PSL representation for the example process encoded in PIF
in the PIF specification document: *PIF: The Process Interchange Format
v.1.2* (dated: Dec. 8, 1997). (You can download a MS-Word formatted
version of this document from:
**ftp://splicer2.cba.hawaii.edu/jl/pif/pif1-2.doc** .)

The PIF-representation for the example process is presented on pp.38-46
of the PIF specification document. Please review the PIF specification
document for the PIF-representation of the example process.

### Brief Overview of the Example Process

A brief overview of the example process, [borrowed from the PIF
specification document]{.underline}, is presented here for convenience.

The example design project is composed of five activities and a design
team with four designers. The precedence network of the activities and
the task responsibilities of the Agents are illustrated below:

![](media/image1.emf)

### PSL Representation of the Example Process: Version 1.

In version 1 of the PSL representation for the example process, a simple
representation is presented[. (We assume that the italicized predicates
and operators are provided by the underlying ontology]{.underline}.)

**Class** PSL_Example_1_V1

**Annotation:** \[Descriprion: "PSL Representation for the example in
PIF-specification, version 1" \]**;**

**Ontology:** \[ Name: Gruninger, Version: 0.5 \] **;**

**Parameters:**

architectName: String = "Robert Callahan"**,**

electricalEngineerName: String = "Cristina Marconi"**,**

mechanicalEngineerName: String = "Gary Fassbinder"**,**

projectManagerName: String = "Ann Rollins"**;**

**Variables:**

architect_1: *Architect*(architectName),

electrical_engineer_1: *ElectricalEngineer*(electricalEngineerName,

> \["Electrical Skill", "Mechanical Skill"\]),

mechanical_engineer_1: *MechanicalEngineer*(mechanicalEngineerName),

project_manager_1: *ProjectManager*(projectManagerName,

> \["Electrical Skill", "Mechanical Skill", "Management Skill"\]);

ResourceNeeded: **Condition**: *overTime*(PSL_Example_1_V1):

*isAvailable*(architect_1) **And**

*isAvailable*(electrical_engineer_1) **And**

*isAvailable*(mechanical_engineer_1) **And**

*isAvailable*(project_manager_1) ;

Steps: **ProcessSteps**: ResourceNeeded :

*Architecture_Design_1*(architect_1) **:** Step1,

*Electrical_Design_2*(electrical_engineer_1) \|

**if** (*status*(delayed, Step1, Step1.end)**:** // status of Step1at
Step1.end

*Mechanical_Design_4*(mechanical_engineer_1) // then

**:** *Mechanical_Design_3*(mechanical_engineer_1) ), // else

*Design_Review_5*(\[project_manager_1, architect_1,

> electrical_engineer_1, mechanical_engineer_1\])

**;**

**EndClass**

### PSL Representation of the Example Process: Version 2

We present a slightly more detailed and accurate model of the example
process in version 2. ([We assume that the italicized predicates and
operators are provided by the underlying ontology]{.underline}.)

**Class** PSL_Example_1_V2

**Annotation:** "PSL Representation for the example in
PIF_specification, version 2" **;**

**Ontology:** \[ Name: Gruninger, Version: 0.5 \] **;**

**Parameters:**

Architect_1: *Personnel*= *Personnel*("Robert Callahan", "Architectue
Skill")**,**

ElectEngr_1: *Personnel*= *Personnel*("Cristina Marconi",

> \["Electrical Skill", "Mechanical Skill"\])**,**

MechEngr_1: *Personnel*= *Personnel*("Gary Fassbinder", "Mechanical
Skill"),

ProjectMgr: *Personnel*= *Personnel*("Ann Rollins",

> \["Electrical Skill", "Mechanical Skill", "Management Skill"\])**;**

**Variables:**

ElectDesign: *ElectricalDesign*()\[3\],

MechDesign: *MechanicalDesign*()\[3\],

isElectDesignRevwd: *Boolean*,

isMechDesignRevwd: *Boolean*;

ParamsCheck: **Condition: :**

> *hasSkill*(Architect_1, "Architecture Skill") **And**
>
> *hasSkill*(ElectEngr_1, \["Electrical Skill", "Mechanical Skill"\])
> **And**
>
> *hasSkill*(MechEngr_1, "Mechanical Skill") **And**
>
> *hasSkill*(ProjectMgr, \["Electrical Skill", "Mechanical Skill",
> "Management Skill"\])**;**

PSL_Example_1_V2**:** **Values :** *atEndTime*(Steps)**:** // output

isElectDesignRevwd,

isMechDesignRevwd;

ResourceNeeded**:** **Condition : :**

*availableOverTime*(Architect, Step1) **And**

*availableOverTime*(Architect, ReviewStep) **And**

*availableOverTime*(ElectEngr_1, ElectStep) **And**

*availableOverTime*(ElectEngr_1, ReviewStep) **And**

(*availableOverTime*(MechEngr_1, Mech3Step) **Or**

> *availableOverTime*(MechEngr_1, Mech4Step) ) **And**

*availableOverTime*(MechEngr_1, ReviewStep) **And**

*availableOverTime*(ProjectMgr, PSL_Example_1_V2) **;**

Steps: **ProcessSteps:** ResourceNeeded **:**

*Architecture_Design_1*(Architect) = \[ElectDesign\[1\],
MechDesign\[1\]\] **:** Step1,

*Electrical_Design_2*(ElectEngr_1, ElectDesign\[1\]) **=**
ElectDesign\[2\] **:** ElectStep \|

**if** (*status*(delayed, Step1, Step1.end)**:** // status of Step1 at
Step1.end

(*Mechanical_Design_4*(MechEngr_1, MechDesign\[1\]) **=**
MechDesign\[2\]

> **:** Mech4Step )**:**

*Mechanical_Design_3*(MechEngr_1, MechDesign\[1\]) = MechDesign\[2\]

> **:** Mech3Step ),

*Design_Review_5*(\[ProjectMgr, Architect, ElectEngr_1, MechEngr_1\],

> \[ElectDesign\[2\], MechDesign\[2\]\]) =
>
> \[ElectDesign\[3\], MechDesign\[3\]\] **:** ReviewStep,

isElectricalDesignReviewed = True,

isMechanicalDesignReviewed = True,

**;**

**EndClass**

## Example 2: PIF to PSL Representation

For the second example of PIF-to-PSL representation, we choose Steve
Polyak's Supply Chain Process specification represented in PIF. (You can
fetch his Supply Chain Process specification (in PIF) and the associated
PSV from:
**http://www.dai.ed.ac.uk/students/stevep/pif/supply/supply.pif**

and **http://www.dai.ed.ac.uk/students/stevep/pif/supply/supply.psv**
respectively.)

### Brief Overview of the Example Process

The objects and the processes and the temporal relationships between the
processes from the example process are illustrated below. (*The
illustrations are my attempt at capturing Steve Polyak's intentions from
the PIF coded example process. As such, the illustrations may be
incomplete and/or incorrect. Your help to complete/correct them is
welcome*.)

#### Object-Classes in the Example Process

The object-class-hierarchy of high-level object-classes (which include
agents, and timepoints) in the example is represented below.

![](media/image2.emf){width="5.999305555555556in"
height="4.291666666666667in"}

#### Process-Classes in the Example Process

The process-class-hierarchy (of high-level process-classes) from the
example is presented below.

![](media/image3.emf)

#### Process-Flow for the Example Process

The process-flow for the example process is illustrated below.

![](media/image4.emf){width="5.996527777777778in"
height="4.333333333333333in"}

### PSL Representation of the Example Process

([We assume that the italicized predicates and operators are provided by
the underlying ontology]{.underline}.)

**Class** Handle_Customer_Order_V1 // called *Replenish_Inventory*
process in the PIF example

**Annotation:** "PSL Representation (V. 1) for the Handle_Customer_Order
(Replenish_Inventory ?) process in the example." **;**

**Ontology:** \[ Name: Gruninger, Version: 0.5 \] **;**

**Parameters:**

Product_1: *Product*(),

Customer_1: *Customer*(),

Retailer_1: Retailer_V1(),

Distributor_1: *Distributor*();

**Variables:**

RetailSalesOrder_1: *RetailSalesOrder*()\[2\],

Employee_1: *Employee*(Company**:** Retailer_1);

NeededResources **:** **Condition :**
*overTime*(Handle_Customer_Order_V1):

*isAvailable*(Employee_1);

Steps**:** **ProcessSteps :** NeededResources **:**

*Receive_Order*(Employee_1, Product_1, Customer_1) **=**
RetailSalesOrder_1\[1\],

*Gather_Order_Details*(Employee_1, RetailSalesOrder_1\[1\])**=**
RetailSalesOrder_1\[2\],

*Check_Order_Details*(Employee_1, RetailSalesOrder_1\[2\]),

**if** (*Detect_Condition*(Employee_1, RetailSalesOrder_1\[2\],
Retailer_1**.**Inventory)**:**

> Replenish_Inventory_V1(Employee_1, RetailSalesOrder_1\[2\],
> Distributor_1)
>
> )

**;**

**EndClass**

**Class** Retailer_V1

**Annotation:** "PSL Representation (V. 1) for the Retailer." **;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

Number: *String* = "r001",

Name: *String* = "Retailing Company",

Address: *String* = "1 Retailer Street",

Departments: *List*(*Department*),

Inventory-1: *Inventory()*,

LoadingDocks: *List*(*LoadingDock*);

Inventory: **Values :** **:**

Inventory-1;

**EndClass**

**Class** Replenish_Inventory_V1 // called *Send_Order* in the PIF
example

**Annotation:** "PSL Representation (V. 1) for the Replenish_Inventory
(Send_Order ?) process in the example." **;**

**Ontology:** (Name: Gruninger, Version: 0.5) **;**

**Parameters:**

Initiator: *Employee*(),

RetailSalesOrder: *RetailSalesOrder*(),

Distributor_1: *Distributor*();

**Variables:**

PL_1: *PurchaseLedger*(),

AccountingDept_1: AccountingDept_V1(PL_1),

ProductReplenishmentOrder_1: *ProductReplenishmentOrder*(),

Employee_1: *Employee*(Company: Initiator**.**Company);

NeededResources**:** **Condition :** *overTime*(Replenish_Inventory_V1)
**:**

*isAvailable*(Employee_1);

Steps**:** **ProcessSteps :** NeededResources **:**

*Send_Order*(Employee_1, RetailSalesOrder_1, Distributor_1)**=**
ProductReplenishmentOrder_1 \|

*Request_Prepare_Payment*(Employee_1, RetailSalesOrder_1,
AccountingDept_1) **=**

> PaymentRequest_1,

Take_Delivery_V1(ProductReplenishmentOrder_1) **=** Product_1,

> *Request_Release_Payment*(Employee_1, PaymentRequest_1,
> AccountingDept_1)

**;**

**EndClass**

**Class** AccountingDept_V1 **:** *Department*(*"Accounting"*)

**Annotation:** "PSL Representation (V. 1) for the Accounting Dept."
**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

Number: *String* = "r001",

PurchaseLedger: *PurchaseLedger*;

**EndClass**

**Class** Take_Delivery_V1

**Annotation:** "PSL Representation (V. 1) for the Take_Delivery process
in the example." **;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

ProductReplenishmentOrder: *ProductReplenishmentOrder*(),

Employee_1: *Employee*(Company: ProductReplenishmentOrder**.**Company),

Product_1: *Product()*;

NeededResources**:** **Condition :** *overTime*(Take_Delivery_V1)**:**

*isAvailable*(Employee_1);

Take_Delivery_V1**:** **Values:**
*atTime*(Take_Delivery_V1**.**end)**:** // output

Product_1;

Steps**:** **ProcessSteps :** NeededResources **:**

*Receive_Product*(Employee_1, ProductReplenishmentOrder) **=**
Product_1,

*Verify_Delivery*(Employee_1, Product_1, ProductReplenishmentOrder),

*Update_Inventory*(Employee_1, Product_1)

**;**

**EndClass**

## Example 3: CAMILE Pilot Scenario (Idef3 to PSL)

Example 3 represents the Make GT350 process as described in
Manufacturing Process Interoperability Scenario, (dated: April 22, 1998)
by Steve Polyak, AIAI, University of Edinburgh. An overview of the
example (i.e. Make GT350) in IDEF3 notation is shown in Figure 19, in
section 6. The example is elaborated further in the section.

([We assume that the italicized predicates and operators are provided by
the underlying ontology]{.underline}.)

**Class** MakeGT350

**Annotation:** \[Description: "Represents the Make GT350
Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

Assembler_1: *Assembler*();

**Variables:**

Interior_1: *Interior*(),

Drive_1: *EngineDrive*(),

Trim_1: *Trim*(),

Engine_1: *Engine*(),

Chassis_1: *Chassis*();

NeededResources**:** **Condition :** *overTime*(MakeGT350)**:**

*isAvailable*(Assembler_1);

MakeGT350**:** **Values:** *atEnd*(MakeGT350**.**Steps)**:** // output

GT350_1;

Steps**:** **ProcessSteps :** NeededResources **:**

(Make_Interior() = Interior_1 \|

Make_Drive() = Drive_1 \|

Make_Trim() = Trim_1 \|

Make_Engine() = Engine_1 \|

Make_Chassis() = Chassis_1),

> FinallyAssembleGT350(Interior_1, Drive_1, Trim_1, Engine_1, Chassis_1,
>
> Assembler_1) = GT350_1

**;**

**EndClass**

**Class** Make_Interior

**Annotation:** \[Description: "The Make-Interior subprocess of the
GT350 Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Variables:**

Interior_1: *Interior*(),

Cockpit_1: *Cockpit*(),

Seat_1: *Seat*(),

GearShift_1: *GearShift*(),

AssemblyBench_1: *AssemblyBench*(A002).

NeededResources**:** **Condition :** *overTime*(Make_Interior)**:**

*isPurchased*(Cockpit_1) **And** *isAvailable*(Cockpit_1) **And**

*isPurchased*(Seat_1) **And** *isAvailable*(Seat_1) **And**

*isAvailable*(AssemblyBench_1);

TimeToProduce**:** **Values: :**

3; // 3 minutes per kit

Make_Interior **:** **Values:** *atTime*(Make_Interior**.**end)**:**

Interior_1;

Steps**:** **ProcessSteps :** NeededResources **:**

*ProduceGearShift*() = GearShift_1,

*AssembleInterior*(Cockpit_1, Seat_1, GearShift_1) = Interior_1

**;**

**EndClass**

**Class** Make_Drive

**Annotation:** \[Description: "The Make-Drive subprocess of the GT350
Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Variables:**

Drive_1: *EngineDrive*(),

Motor_1: *Motor*(),

Electronics_1: *Electronics*(),

AssemblyBench_1: *AssemblyBench(*A002*)*,

AssemblyBench_2: *AssemblyBench(*A003*)*;

NeededResources**:** **Condition :** *overTime*(Make_Drive)**:**

*isPurchased*(Motor_1) **And** *isAvailable*(Motor_1) **And**

(*isAvailable*(AssemblyBench_1) Or *isAvailable*(AssemblyBench_2));

TimeToProduce**:** **Values: :**

12; // 12 minutes per piece

Make_Drive **:** **Values:** *atTime*(Make_Drive**.**end)**:**

Drive_1;

Steps**:** **ProcessSteps :** NeededResources **:**

*MakeElectronics*() = Electronics_1,

*AssembleDrive*(Motor_1, Electronics_1) = Drive_1

**;**

**EndClass**

**Class** Make_Trim

**Annotation:** \[Description: "The Make-Trim subprocess of the GT350
Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Variables:**

Trim_1: *Trim*(),

Options_1: *TrimOptions*(),

Stand_1: *Stand*(),

Wheel_1: *Wheel*(),

IdPlate_1: *IdPlate*(),

Decal_1: *Decal*(),

AssemblyBench_1: *AssemblyBench*(A002),

AssemblyBench_2: *AssemblyBench*(A005);

NeededResources**:** **Condition :** *overTime*(Make_Trim)**:**

*isPurchased*(Decal_1) **And** *isAvailable*(Decal_1) **And**

(*isAvailable*(AssemblyBench_1) Or *isAvailable*(AssemblyBench_2));

TimeToProduce**:** **Values: :**

20; // 20 minutes per piece

Make_Trim **:** **Values:** *atTime*(Make_Trim**.**end)**:**

Trim_1;

Steps**:** **ProcessSteps :** NeededResources **:**

*(MakeTrimOptions*() = Options_1 \|

*MakeStand*() = Stand_1 \|

*MakeWheels*() = Wheel_1 \|

*MakeIdPlate*() = IdPlate_1),

*AssembleTrim*(Options_1, Stand_1, Wheel_1, IdPlate_1, Decal_1) = Trim_1

**;**

**EndClass**

**Class** Make_Engine

**Annotation:** \[Description: "The Make-Engine subprocess of the GT350
Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Variables:**

Engine_1: *Engine*(),

Block_1: *EngineBlock*(),

Harness_1: *Harness*(),

Wires_1: *Wire*(),

PartNum_1: *PartNumber*(), // this should really be a parameter

AssemblyBench_1: *AssemblyBench*(A004);

NeededResources**:** **Condition :** *overTime*(Make_Engine)**:**

*isAvailable*(AssemblyBench_1);

TimeToProduce**:** **Values: :**

5; // 5 minutes per piece

Make_Engine **:** **Values:** *atTime*(Make_Engine**.**end)**:**

Engine_1;

Steps**:** **ProcessSteps :** NeededResources **:**

(MakeEngineBlock() = Block_1 \|

*MakeHarness*() = Harness_1 \|

*MakeWires*() = Wires_1),

*AssembleEngine*(Block_1, Harness_1, Wires_1) = Engine_1

**;**

**EndClass**

**Class** MakeEngineBlock

**Annotation:** \[Description: "The Make-Engine-Block subprocess of the
Make-Engine Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

PartNum_1: *PartNumber*();

**Variables:**

Block_1: *EngineBlock*(),

MoldedPart_1: *MoldedPart*();

MakeEngineBlock **:** **Values:** *atTime*(MakeEngineBlock**.**end)**:**

Block_1;

Steps**:** **ProcessSteps :** **:**

ProduceMoldedMetalItem(PartNum_1) = MoldedPart_1,

*MachineBlock*(MoldedPart_1) = Block_1

**;**

**EndClass**

**Class** Make_Chassis

**Annotation:** \[Description: "The Make-Chassis subprocess of the GT350
Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Variables:**

Chassis_1: *Chassis*(),

Unibody_1: *Unibody*(),

Frame_1: *Frame*(),

AssemblyBench_1: *AssemblyBench*(A002);

NeededResources**:** **Condition :** *overTime*(Make_Chassis)**:**

*isAvailable*(AssemblyBench_1);

TimeToProduce**:** **Values: :**

50; // 50 minutes per piece

Make_Chassis **:** **Values:** *atTime*(Make_Chassis**.**end)**:**

Chassis_1;

Steps**:** **ProcessSteps :** NeededResources **:**

*(MakeUnibody*() = Unibody_1 \|

*MakeFrame*() = Frame_1),

*AssembleChassis*(Unibody_1, Frame_1) = Chassis_1

**;**

**EndClass**

**Class** FinallyAssembleGT350

**Annotation:** \[Description: "The final assembly subprocess of the
GT350 Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

Interior_1: *Interior*(),

Drive_1: *EngineDrive*(),

Trim_1: *Trim*(),

Engine_1: *Engine*(),

Chassis_1: *Chassis*(),

Assembler_1: *Assembler*();

**Variables:**

AssembledGT350_1: *AssembledGT350*()\[2\];

FinallyAssembleGT350 **:** **Values:**
*atTime*(FinallyAssembleGT350**.**end)**:**

AssembledGT350_1\[1\];

Steps**:** **ProcessSteps :** **:**

*FinallyAssemble*(Interior_1, Drive_1, Trim_1, Engine_1, Chassis_1,
Assembler_1) =

> AssembledGT350_1\[1\],

*Engrave*(AssembledGT350_1\[1\]) = AssembledGT350_1\[2\]

**;**

**EndClass**

### Example 3a: Produce Mold Metal Item from CAMILE Scenario

Example 3a represents the Produce Mold Metal Item process as described
in Manufacturing Process Interoperability Scenario, (dated: April 22,
1998) by Steve Polyak, AIAI, University of Edinburgh. An overview of the
example (i.e. Produce Mold Metal Item) in IDEF3 notation is shown in
Figure 1, in section 5.1.

([We assume that the italicized predicates and operators are provided by
the underlying ontology]{.underline}.)

**Class** Foundry

**Annotation:** \[Description: "A description of the Foundry class for
the CAMILE process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

isWithinOperatingHours**:** **Condition : :**

*isCurTimeInRange*(CurrentTime, \["8:00", "24:00"\]),

*isCurDayInRange*(CurrentTime, \["Monday", "Friday"\]);

MaxOvertime**:** **Values: :**

2; // Max overtime allowed

PreventiveMaintenance**:** **ProcessSteps** **:**
*isDueforPM*(StartTime) **:**

*DoPreventiveMaintenance*()**;**

**EndClass**

**Class** ProduceMoldedMetalItem**:** Foundry()

**Annotation:** \[Description: "The Produce-Molded-Metal-Item subprocess
of the CAMILE Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

PartNum_1: *PartNumber*();

**Variables:**

MoldedPart_1: *MoldedPart(*PartNum_1),

Mold_1: *MoldingItem*("F004")\[2\], // the so-called Mold (noun)

Metal_1: *Metal*(),

MoltenMetal_1: *MoltenMetal*(),

MetalAnalysis_1: *MetalAnalysisReport*(),

Furnace_1: *Furnace*()\[2\],

Operator_1: *Operator*();

NeededResources**:** **Condition :**
*overTime*(ProduceMoldedMetalItem)**:**

*isAvailable*(Furnace_1) **And**

*isAvailable*(Operator_1) **And**

*isAvailable*(Mold_1);

ProduceMoldedMetalItem **:** **Values:**
*atTime*(ProduceMoldedMetalItem**.**end)**:**

MoldedPart_1;

Steps**:** **ProcessSteps :** NeededResources **And**
isWithinOperatingHours **:**

**if** (*isNewPart*(PartNum_1)**:**

*ChangeMoldingItem*() = Mold_1\[1\]),

*SelectAFurnace*() = Furnace_1\[1\],

*SetupFurnace*(Furnace_1\[1\]) = Furnace_1\[2\],

*(Melt*(Furnace_1\[2\], Metal_1, Operator_1) = MoltenMetal_1 \|

*AnalyzeMetal*(Furnace_1\[2\], Metal_1, Operator_1) = MetalAnalysis_1),

Mold(Mold_1\[1\], MoltenMetal_1, Operator_1) = MoldedPart_1,

*Wait*(24),

*ClearCavities*(Mold_1\[1\], Operator_1) = Mold_1\[2\]

**;**

**EndClass**

**Class** Mold**:** Foundry()

**Annotation:** \[Description: "The Mold subprocess of the
Produce-Molded-Metal-Item Process"\]**;**

**Ontology:** \[Name: Gruninger, Version: 0.5\] **;**

**Parameters:**

Mold_1: *MoldingItem*(),

MoltenMetal_1: *MoltenMetal*(),

MoldingOperator_1: *Operator*();

**Variables:**

MoldedBatch_1: *MoldedPart*(),

MoldedLot_1: *MoldedPart*(),

Racks_1: *MoldingRack*(Quantity: 2)\[2\],

Operators_x: *Operator*(Quantity: 2);

NeededResources**:** **Condition :** *overTime*(Mold)**:**

*isAvailable*(Racks_1\[1\]) **And**

*isAvailable*(Operators_x);

Mold**:** **Values:** *atTime*(Mold**.**end)**:**

MoldedPart_1;

Steps**:** **ProcessSteps :** NeededResources **:**

**while** (*isBatchIncomplete*()**:**

> *SetupRacks*(Racks_1\[1\], Mold_1, Operators_x) = Racks_1\[2\],
>
> *PourMetal*(MoltenMetal_1, Racks_1\[2\], MoldingOperator_1) =
> MoldedLot_1,
>
> *AddToSet*(MoldedBatch_1, MoldedLot_1) = MoldedBatch_1

)

**;**

**EndClass**

# Appendix

## PSL Syntax in BNF

%{

/\*

\* PSL-spec.y : Syntactic specification for PSL. (Process it using
bison)

\*

\* Version: 0.98 Date: Aug. 17, 98

\*

\* Developed by: Krishna N. Jha, Boeing Corp., in contract for NIST

\*/

#include \<stdio.h\>

%}

%token Symbol String Integer Real

%token IntegerType RealType BooleanType SymbolType

%token Class EndClass If While True False

%token Values Condition ProcessSteps

%token Annotation Ontology Parameters Variables

%token VarAttribName

%token GE LE EQ NEQ

%right \'=\'

%left And Or

%left Not

%left \'+\' \'-\'

%left \'\*\' \'/\'

%%

psl : globals

\| classes

;

globals : globals global

\| global

;

classes : classes class

\| class

;

global : annotation

\| ontology

;

class : Class className inheritFromClass annotations ontology params
variables

> attributes EndClass

;

className: Symbol

;

inheritFromClass: \':\' className \'(\' argList \')\'

\| /\* empty \*/

;

annotations: annotations annotation

\| /\* empty \*/

;

annotation: Annotation \':\' String \';\'

;

ontology: Ontology \':\' \'\[\' itemValuePairList \'\]\'

;

params : Parameters \':\' varDefinitionList \';\'

;

variables: Variables \':\' varDefinitionList \';\'

\| /\* empty \*/

;

attributes: attributes attribute

\| /\* empty \*/

;

attribute: attribName \':\' valuesAttribute \';\'

\| attribName \':\' conditionAttribute \';\'

\| attribName \':\' processStepsAttribute \';\'

;

attribName: Symbol

;

valuesAttribute: Values \':\' guardCondition \':\' valueList

;

conditionAttribute : Condition \':\' guardCondition \':\' condition

;

processStepsAttribute: ProcessSteps \':\' guardCondition \':\'
processStepList

;

guardCondition : condition

\|

;

valueList: valueList \',\' value

\| value

;

itemValuePairList: itemValuePairList \',\' itemValuePair

\| itemValuePair

;

itemValuePair : itemName \':\' value

;

itemName : Symbol

;

varDefinitionList: varDefinitionList \',\' varDefinition

\| varDefinition

;

processStepList : processStepList \',\' processStep

\| processStepList \'\|\' processStep

\| processStep

;

processStep: \'(\' processStepList \')\'

\| basicStep \':\' label

\| basicStep

;

label : Symbol

;

basicStep: If \'(\' condition \':\' thenProcessStepList \':\'
elseProcessStepList \')\'

\| If \'(\' condition \':\' thenProcessStepList \')\'

\| While \'(\' condition \':\' processStepList \')\'

\| value \'=\' value

\| value

;

thenProcessStepList : processStepList

;

elseProcessStepList : processStepList

;

varDefinition: baseVarDefinition

\| baseVarDefinition \'=\' value

;

baseVarDefinition: varName \':\' className \'(\' argList \')\' \'\[\'
expr \'\]\'

\| varName \':\' className \'(\' argList \')\'

\| varName \':\' baseType

;

baseType: IntegerType

\| RealType

\| BooleanType

\| SymbolType

;

condition: logical_expr

;

argList : auxArgList

\| /\* empty \*/

;

auxArgList: auxArgList \',\' arg

\| arg

;

arg : varValuePair

\| value

;

varValuePair: varName \':\' value

;

value : expr

\| valueSet

;

valueSet: \'\[\' valueList \'\]\'

;

exprList: exprList \',\' expr

\| expr

;

expr : expr \'+\' expr

\| expr \'-\' expr

\| expr \'\*\' expr

\| expr \'/\' expr

\| \'-\' expr %prec \'\*\'

\| \'(\' expr \')\'

\| baseExpr

;

baseExpr: baseLhsValue

\| baseLhsValue \'\[\' exprList \'\]\'

\| predicateName \'(\' argList \')\'

\| number

;

baseLhsValue: varName /\* e.g. acctgDept \*/

\| VarAttribName /\* e.g. acctgDept.DeptNumber \*/

;

constant: number

\| String

;

number : Integer

\| Real

;

varName : Symbol

;

logical_expr: logical_expr And logical_expr

\| logical_expr Or logical_expr

\| Not logical_expr

\| \'(\' logical_expr \')\'

\| comparison

\| expr

\| True

\| False

;

comparison: expr \"==\" expr

\| expr \"\>=\" expr

\| expr \'\>\' expr

\| expr \"\<=\" expr

\| expr \'\<\' expr

\| expr \"=/=\" expr

;

predicateName: Symbol

;

%%