W3C home > Mailing lists > Public > www-ws@w3.org > October 2003

Re: Data-flow redux

From: Drew McDermott <drew.mcdermott@yale.edu>
Date: Fri, 10 Oct 2003 22:24:54 -0400 (EDT)
Message-Id: <200310110224.h9B2Osw28557@pantheon-po01.its.yale.edu>
To: www-ws@w3.org


   [Massimo Paolucci]

   During the last DAML-S teleconference we decided to drop the use of
   sameAs and we adopted the idea that data-flow is controlled by a link
   from one parameter to the next one.

   Here is how it plays out:

It's good, but dataflows are not properties of parameters; they are
properties of parameters of particular (tagged) steps, which we can
call ParameterSpecs:

<owl:Class rdf:ID="ParameterSpec">
</owl:Class>

<rdf:Property rdf:ID="psParam">
   <rdfs:domain rdf:resource="#ParameterSpec"/>
   <rdfs:range rdf:resource="#Parameter"/>
</rdf:Property>

<rdf:Property rdf:ID="i-or-o">
   <rdfs:domain rdf:resource="#ParameterSpec"/>
   <rdfs:range>
      <owl:oneOf rdf:parseType="Collection">
          <owl:Thing rdf:ID="inputP"/>
	  <owl:Thing rdf:ID="outputP"/>
      </owl:oneOf>
   </rdfs:range>
</rdf:Property>
   
<rdf:Property rdf:ID="psStep">
   <rdfs:domain rdf:resource="#ParameterSpec"/>
   <rdfs:range rdf:resource="#StepTag"/>
</rdf:Property>

The class StepTag referred to here is defined thus:

<owl:Class rdf:ID="StepTag">
</owl:Class>

<rdf:Property rdf:ID="tagName">
   <rdfs:domain rdf:resource="StepTag"/>
   <rdfs:range rdf:resource="&xsd;string"/>
</rdf:Property>

The next draft of the surface syntax will spell all this out,
coherently I hope.

Anyway, I would change every occurrence of Parameter to ParameterSpec
(marked with a **):

   <!-- This class represents a data-flow link from one parameter to 
   another -->
   <owl:Class rdf:ID="DataFlow"/>


   <!-- ................................... Source -->

   <owl:ObjectProperty rdf:ID="source">
     <comment>
       This property links a data flow link to a parameter (the writer)
       This property is defined functional to guarantee that there is
       only one sorce of information for each data-flow link
     </comment>
     <rdf:type rdf:resource="&owl;#FunctionalProperty"/>
     <rdfs:domain rdf:resource="#DataFlow"/>
     <rdfs:range rdf:resource="#ParameterSpec"/>    <<--- **
   </owl:ObjectProperty> 




   <owl:ObjectProperty rdf:ID="sourceOf">
     <comment>
      Inverse relation used to relate a parameter with all the data-flow
      it writes into.
     </comment>
     <owl:inverseOf rdf:resource="#source"/>
   </owl:ObjectProperty>

   <!-- ................................... Destination -->

   <owl:ObjectProperty rdf:ID="destination">
     <comment>
       This property links a data flow link to a parameter (the reader).
       For the time being, this property is defined functional to guarantee 
   that there is
       only one recepient of the information for each data-flow link.
       This constraints forces us to add one data link for each parameter
       pair that are connected, which is not too bad.  An alternative
       could be to relax the functional constraint and allow the data to
       be "sprayed" to many parameters.  There is no difference between
       the two models other than personal preference.

Even if you make 'destination' functional, you can't rule out multiple
flows without ruling out multiple dataflow objects attached to a given
ParameterSpec, which is tricky.

You're right, though, that allowing multiple sources and destination
would give you "fan in" and "fan out" in a nice way.  How would we
indicate that in the surface syntax?  Maybe   s => <d1, d2> ?  
     </comment>
     <rdfs:domain rdf:resource="#DataFlow"/>
     <rdfs:range rdf:resource="#ParameterSpec"/>   <<--- **
   </owl:ObjectProperty>


   <owl:ObjectProperty rdf:ID="destinationOf">
     <owl:inverseOf rdf:resource="#destination"/>
     <comment>
      Inverse relation used to relate a parameter with all the data-flow
      it reads from.  The property is functional to impose that there is
      only one source of information.
     </comment>
     <rdf:type rdf:resource="&owl;#FunctionalProperty"/>
   </owl:ObjectProperty>


   During the teleconference we noted that there are at least three types
   of data-flow: 

       output-input: the output of a process feeds into the input of another
       output-output: as when the output of a process is returned to some
		      parent process
       input-input: as when the input of a process is propagated to some
		    substeps

   also it was suggested a fourth type:

       input-output: I did not really understand this, but I my
		     recollection si that it means the relation between
		     input/output within a process


   The four types of classes are defined below.  The names can be easily
   changed, just suggest what you want.

I like the names, but we have to subclass ParameterSpec, yielding
InputSpec and OutputSpec, which would replaced Input and Output:

<owl:Class rdf:ID="InputSpec">
   <rdfs:subClassOf rdf:resource="#ParameterSpec"/>
   <rdfs:subClassOf>
       <owl:Restriction>
          <owl:onProperty rdf:resource="#i-or-o"/>
	  <owl:hasValue rdf:resource="inputP"/>
       </owl:Restriction>
   </rdfs:subClassOf>
</owl:Class>

<owl:Class rdf:ID="OutputSpec">
   <rdfs:subClassOf rdf:resource="#ParameterSpec"/>
   <rdfs:subClassOf>
       <owl:Restriction>
          <owl:onProperty rdf:resource="#i-or-o"/>
	  <owl:hasValue rdf:resource="outputP"/>
       </owl:Restriction>
   </rdfs:subClassOf>
</owl:Class>

Again, I've marked where the changes go:

   <owl:Class rdf:ID="ResultFlow">
     <comment>
       ResultFlow implements the output/input pattern flowing from an
       output to an input.
     </comment>
     <rdfs:label>resultFlow</rdfs:label>
     <rdfs:subClassOf rdf:resource="DataFlow"/>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#source"/>
       <owl:allValuesFrom rdf:resource="#OutputSpec"/>  <<--- **
     </owl:Restriction>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#destination"/>
       <owl:allValuesFrom rdf:resource="#InputSpec"/>   <<--- **
     </owl:Restriction>
   </owl:Class>
   .

   <owl:Class rdf:ID="ReturnFlow">
     <comment>
       ReturnFlow implements the output/output pattern flowing
       (typically) from the output of a process to the output of a parent
       process.  Loosely speaking, this is similar to a return statement
       in programming languages. 
     </comment>
     <rdfs:label>resultFlow</rdfs:label>
     <rdfs:subClassOf rdf:resource="DataFlow"/>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#source"/>
       <owl:allValuesFrom rdf:resource="#OutputSpec"/>   <<--- **
     </owl:Restriction>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#destination"/>
       <owl:allValuesFrom rdf:resource="#InputSpec"/>   <<--- **
     </owl:Restriction>
   </owl:Class>
   .

   <owl:Class rdf:ID="ArgumentFlow">
     <comment>
       ArgumentFlow implements the input/input pattern flowing
       (typically) from the input of a process to the input of a child
       process.  Loosely speaking, this is similar to argument passing
       between the declaration of a function and the steps of the
       function.
     </comment>
     <rdfs:label>resultFlow</rdfs:label>
     <rdfs:subClassOf rdf:resource="DataFlow"/>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#source"/>
       <owl:allValuesFrom rdf:resource="#InputSpec"/>   <<--- **
     </owl:Restriction>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#destination"/>
       <owl:allValuesFrom rdf:resource="#InputSpec"/>    <<--- **
     </owl:Restriction>
   </owl:Class>

   .

   <owl:Class rdf:ID="ValueFlow">
     <comment>
       ValueFlow implements the input/output pattern flowing
       (typically) from the input of a process to an output. 
     </comment>
     <rdfs:label>resultFlow</rdfs:label>
     <rdfs:subClassOf rdf:resource="DataFlow"/>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#source"/>
       <owl:allValuesFrom rdf:resource="#InputSpec"/>    <<--- **
     </owl:Restriction>
     <owl:Restriction>
       <owl:onProperty rdf:resource="#destination"/>
       <owl:allValuesFrom rdf:resource="#OutputSpec"/>    <<--- **
     </owl:Restriction>
   </owl:Class>

   The main problem of this approach is that there is no way to impose a
   relation between the values of the source parameter and the values of
   the target parameter.  For example, it could still be possible that
   the link connects an output parameter "Ticket" with an input parameter
   "Appointment".    I do not know how we can avoid it.

I don't think it can be avoided; it's another special-purpose module
of the OWL-S syntax/type checker.

   --------------------------------------------------------------------
   After thought

   Upon writing this document, I realized that there may be an even
   simpler solution by providing just a property writeTo that connects
   outputs to input and readsFrom that connects input to outputs (this
   model is of course assuming the output/input pattern).

   Basically we do not need the DataFlow class anymore, but just the
   following two properties:

   <owl:ObjectProperty rdf:ID="writeTo">
     <rdfs:domain rdf:resource="#Output"/>
     <rdfs:range rdf:resource="#Input"/>
   </owl:ObjectProperty>

   <owl:ObjectProperty rdf:ID="readFrom">
     <rdfs:label>readFrom</rdfs:label>
     <rdf:type rdf:resource="&owl;#FunctionalProperty"/>
     <rdfs:domain rdf:resource="#Input"/>
     <rdfs:range rdf:resource="#Output"/>
   </owl:ObjectProperty>

   Similarly we could define properties such as argumentTo/From and
   returnedTo/From.

This has the same problem as above: the flows are properties of
ParameterSpecs, not Parameters.

With that change, there's nothing wrong with this alternative, except
that it's asymmetrical.  In some cases, that might be clearer.

At a few places above, you imply that flows can have "fan out" but not
"fan in."  But there are places where that's exactly what we need.
Reverting to the surface syntax:

   (Sequence
      (If-Then-Else
         :ifCondition C
	 :then (tag tfoo (Atomic A :results (a)))
	 :else (tag foof (Atomic B :results (b))))
      (Atomic C (arg <= (a(^ tfoo)))
		(arg <= (b(^ foof)))))

(The "^" is an uparrow, meaning "output" param.)  Although the 'arg'
input to C (declared in the definition of C) is set just once, on any
given execution of the sequence it will be set by either the true
branch or the false branch of the conditional.

                                             -- Drew

-- 
                                   -- Drew McDermott
                                      Yale Computer Science Department
Received on Friday, 10 October 2003 22:24:57 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 3 July 2007 12:25:44 GMT