Declarative workflow system supporting side-effects6424948Abstract An object-focused workflow system for processing a received object in accordance with a declarative workflow specification. The specification includes modules and attributes, where module execution results in the evaluation of attributes, and may include the initiation of a side-effect action performed by an external component. Whether modules are to be executed for a particular received object is determined by associated enabling conditions. Attributes may be evaluated in accordance with computation rules and a combining policy, where the computation rules specify how values are to be contributed to an attribute, and the combining policy indicates how those contributed values are combined in order to assign a value to the attribute. Tasks in the workflow system may be executed eagerly in order to improve the performance of the workflow system. The eager evaluation of tasks includes the determination of whether such tasks are eligible for eager evaluation, and whether the tasks are unneeded or necessary for the processing of the received event. Workflows which satisfy described design properties allow for improved algorithms for the determination of the whether tasks are eligible, eager, and/or necessary. A graphical user interface is provided for displaying a representation of the evaluation status of the modules and attributes during workflow execution. Claims We claim: Description FIELD OF THE INVENTION
.theta. Type
.orgate. (Union) {T}
@ (concat) [T]
or Boolean
and Boolean
+ integer
- integer
* integer
sup atom
The .orgate. collector computes the (bag) union of two bags (double are not eliminated). The @ collector does the concatenation of two lists (@([1, . . . , a.sub.n ], [b.sub.1, . . . , b.sub.k ])=[1, . . . , a.sub.n, b.sub.1, . . . , b.sub.n ]). In practice, the user can define new collectors either (i) by providing built-in collectors associated with built-in atom types, or (ii) by constructing new collectors using the CPL language. Indeed, the CPL language permits the user to declare any binary function to be used as a collector. Constructed operators will now be defined. A constructed operator is an operator which is equivalent to a sequence of CPL statements. A constructed operator can always be defined using basic operators. Constructed operators are used in CPL as a short-hand to represent sequences of CPL statements that are frequently used in CPL programs. Select operator: The select operator is an operator that is a parameterized by a boolean CPL function. It applies on lists or bags. The typing rules for select are: ##EQU12## where t.sub.1 is any CPL type. select(cd)(S.sub.1) returns a subset R of elements of S.sub.1. An element e.sub.1 of S.sub.1 is in R if cd(e.sub.1)=true. The select(cd) operator (on bags) is equivalent to the following sequence of CPL statements: ##EQU13## The select(cd) operator (on lists) is equivalent to the following sequence of CPL statements: ##EQU14## Join operator: The join operator is binary operator that is a parameterized by a boolean CPL function. The typing rules for join are: ##EQU15## where t.sub.1 and t.sub.2 are any CPL type. join (cd) (S.sub.1, S.sub.2) returns a set R of tuples of the form <f_a:t.sub.1, s_a:t.sub.2 >. A tuple <e.sub.1, e.sub.2 > is in R if e.sub.1 is in S.sub.1, e.sub.2 is in S.sub.2 and cd(e.sub.1, e.sub.2)=true. Join (cd) is equivalent to the following sequence of CPL statements: ##EQU16## Trans operator The trans operator is a binary operator that is parameterized by CPL function. The typing rules for trans are: ##EQU17## trans (f) is equivalent to the following sequence of CPL statements: ##EQU18## Enum operator The enum operator associates each element of a list with its position in the list. The typing rule for trans is: ##EQU19## It is defined as follows: ##EQU20## The enum operator is equivalent to the following sequence of CPL statements: ##EQU21## Dot operator The dot operator is a binary operator that combines two lists by associating elements with same position. The typing rule for dot is: ##EQU22## It is defined as follows: ##EQU23## The dot operator is equivalent to the following sequence of CPL statements: ##EQU24## Group operator The group operator is a parameterized operator. The typing rules for group are: ##EQU25## where t' is an atom type. Group takes as input a bag (resp, a list) and produces as output a bag of tuples of the form (h.sub.i,S.sub.i) i.epsilon.1 . . . n such that .A-inverted.i,j.epsilon.1 . . . n, (h.sub.i.noteq.h.sub.j)or(i=j) and, Each member s.sub.i of S.sub.i contains the projection on the second attribute of all the tuples in S whose first attribute is equal to h.sub.i. The Group Operator is equivalent to the following sequence of CPL statements: ##EQU26## Sort operator: The sort operator is a parameterized operator. The typing rules for sort are: ##EQU27## where .alpha. is a CS mapping that describes an order relation over values of type T. More precisely, .alpha. is a CS mapping that takes as input two values of type T and returns a boolean value. .alpha. returns the value True if the first argument is greater than the second argument and False otherwise. .alpha. describes a non-strict order relation if it verifies the properties (1) (2) and (3) described below. a describes a strict order relation if it verifies the properties (1) and (4). (1) if (.alpha.(x,y) and (.alpha.(y,z) then .alpha.(x,z) (2) .alpha.(x,x)=True (3) not(.alpha.(x,y)) or (not(.alpha.(y,x)) or (y=x)) (4) not(.alpha.(x,y)) or (not(.alpha.(y,x)) The sort operator performs as follows: sort(.alpha.)(S) sorts the value of S in an increasing order according to .alpha.. Let us note that the result is not deterministic since (i) the order relation .alpha. is applied on a bag and (ii) a may define a partial order. The sort operator is equivalent to the following sequence of CPL statements: ##EQU28## The foregoing was a formal definition of the CPL language. Examples of how the language is used to implement combining policy will be given below in connection with the ongoing example. Returning now to the description of the example application and FIG. 2, module 260 is specified in terms of computation rules and a combining policy, and is shown textually in FIG. 11. The computation rules are specified in line 25-39 of the DL specification. As defined in lines 21-22, the output attribute WRAP_UP is a set of tuples containing an attribute name and a value of the attribute. In effect, this attribute contains various attribute names and associated values for archival purposes. The first three rules (lines 26-31) are of the form "if true", so that they will always be True, and the values specified in those rules will always contribute to the attribute WRAP_UP. The computation rule on lines 32-35 will only contribute to the attribute WRAP_UP if the attribute WEB_DESTINATIONS is not empty. Similarly, the computation rule on lines 36-39 will only contribute to the attribute WRAP_UP if the value of CUST_REC.CARD_COLOR is "gold". The combining policy (wrap-up-cp) is specified in lines 40-41 and indicates that the contribution of all true rules are to be used. It is assumed that this combining policy is a predefined CPL function which is available for use by system designers. The CPL program defining this function is as follows: wrap_up_cp: :=x - > select(value) (x) It is also noted that the Calculate_Wrap_Up module 260 has a side-effect, as specified in line 42. The side-effect of this module is to use the WRAP_UP attribute to write into an archive. This archive may be, for example, an external database which stores operational information for the system. Returning now to FIG. 2, module 220 will be described in further detail. As described above in conjunction with FIG. 5, module 220 contains 8 sub-modules 504, 508, 512, 516, 520, 524, 528, 532. Modules 504, 508, and 512 are modules which perform database retrievals in order to assign values to attributes. The DL specification for the Get_Recent_Contacts_For_This_Customer module 504 is shown in FIG. 12. Based on the input attribute ACCOUNT_NUMBER, the module will perform a database query as specified in lines 13-16 in order to evaluate and assign a value to the output attribute RECENT_CONTACTS. The DL specification for the Get_Recent_Purchases_For_This_Customer module 508 is shown in FIG. 13. Based on the input attribute ACCOUNT_NUMBER, the module will perform a database query as specified in lines 10-13 in order to evaluate and assign a value to the output attribute RECENT_PURCHASES. The DL specification for the Get_Account_History_For_This_Customer module 512 is shown in FIG. 14. Based on the input attribute ACCOUNT_NUMBER, the module will perform a database query as specified in lines 14-17 in order to evaluate and assign a value to the output attribute ACCOUNT_HISTORY. Returning now to FIG. 5, the Calculate_Frustration_Score module 516 is represented as a hexagon, which indicates that the module is a decision module and that the processing of the module is specified in terms of computation rules and a combining policy. The DL specification for this module is shown in FIG. 15. The computation rules are shown in part in lines 7-19. There would likely be additional computation rules, but such rules are not shown because they are not necessary for an understanding of the relevant portions of FIG. 15. The input attribute to this module is RECENT_CONTACTS, which is a list as defined in FIG. 12, lines 4-10. Thus, the computation rule specified in lines 8-13 of FIG. 15 specifies that if the attribute RECENT_CONTACTS is defined for list element [1] (i.e., there is at least one recent contact specified in the RECENT_CONTACTS attribute), then the expression in lines 10-13 is evaluated and the result is contributed to the FRUSTRATION_SCORE attribute. Similarly, the computation rule specified in lines 14-19 of FIG. 15 specifies that if the attribute RECENT_CONTACTS is defined for list element [2] (i.e., there are at least two recent contacts specified in the RECENT_CONTACTS attribute), then the expression in lines 16-19 is evaluated and the result is contributed to the FRUSTRATION_SCORE attribute. Additional computation rules would likely be included in an actual implementation, but are not shown here. It is noted that in this example, any or all of the computation rules may evaluate to True, in which case the attribute FRUSTRATION_SCORE gets contributions from each of the true rules. The combining policy for the Calculate_Frustration_Score module 516 is a CPL function, frustration-score-cp, as specified in lines 21-24 and indicates that the contributions of the true rules will be added together and rounded up to the next integer, up to a maximum of 10. The result is assigned to the attribute FRUSTRATION_SCORE. The CPL program defining this function is as follows: Calculate_Frustration_Score ( sum_true : :=x -> collect (select(value), 0, +) min_of : :=x, v -> if x>v then v else x Frustration_score_cp : :=cont_vals -> min_of (round_up (sum_true (cont_vals,1)), 10) The Calculate_Net_Profit_Score module 520 (FIG. 5) is represented as a hexagon, which indicates that this module is a decision module and that the processing of the module is specified using computation rules and a combining policy. The DL specification for this module is shown in FIG. 16. The computation rules are shown in lines 10-32. The input attributes to this module are RECENT_CONTACTS, RECENT_PURCHASES, ACCOUNT_HISTORY, and CUST_REC. The computation rules specified in lines 10-32 specify the contributions to the attribute NET_PROFIT_SCORE based on the input attributes. The combining policy specified in lines 33-35 is a CPL function, net-profit-score-cp, and indicates that the contributions of the true rules will be added together. The resulting sum is assigned to the attribute Net_Profit_Score. The CPL program defining this function is as follows: Net_Profit_Score_cp : :=cont_vals -> sum_true (cont_vals) The Calculate_Late_Payment_Score module 524 (FIG. 5) is specified using computation rules and a combining policy and the DL specification for this module is shown in FIG. 17. The computation rules specified in lines 7-19 specify the contributions to the LATE _PAYMENT_SCORE attribute based on the input attribute. The combining policy as specified in lines 20-22 is a CPL function, late-payment-score-cp, and indicates, that the contribution of a true rule will be assigned to the attribute LATE_PAYMENT_SCORE, or if there is no rule evaluating to a true value, then the LATE_PAYMENT_SCORE attribute will be assigned the default value of 0. It is noted that a constraint on this type of combining policy is that only one computation rule may evaluate to true. This constraint could be tested for during a pre-processing step to make sure that any possible evaluation will result in only one computation rule being true. The CPL program defining this function is as follows: choose_first : :=x,y -> x Late_Payment_Score_cp : :=cont_vals -> collect (0, choose_first) (select (value) (cont_vals)) The Calculate_Cust_Value module 528 (FIG. 5) is specified using computation rules and a combining policy and the DL specification for this module is shown in FIG. 18. The computation rules specified in lines 9-19 specify the contributions to the CUST_VALUE attribute based on the input attributes. The combining policy as specified in lines 20-23 is a CPL function, calculate-cust-val-cp, and indicates that the contributions of rules with a true condition are added and rounded up, with a maximum of 100. The result is assigned to the attribute CUST_VALUE. If no rule evaluates to a true valve, then the CUST_VALUE attribute is assigned the default value 0. The CPL program defining this function is as follows: Calculate_cust_Value_cp : :=cont_vals -> min _of (round_up (sum_true (cont_vals)), 100) The Calculate_Marketing_vs._Collections module 532 (FIG. 5) is specified using computation rules and a combining policy and the DL specification for this module is shown in FIG. 19. The computation rule specified in lines 8-16 specifies the contributions to the MARKETING_VS_COLLECTIONS attribute based on the input attributes. It is noted that in an actual implementation additional rules would likely be included. The combining policy as specified in lines 19-24 is a CPL function, marketing-vs-collection-cp, and indicates that the contribution of a true rule will be assigned to the attribute MARKETING_VS_COLLECTIONS, or if there is no rule evaluating to a true value, then the MARKETING_VS_COLLECTIONS attribute will be assigned the default value "marketing". In this module, it is assumed that all computation rules (not all shown) have the effect of contributing the value "collect", and so there is no inconsistency if more than one rule has a true condition. The CPL program defining this function is as follows: marketing_vs_collection_cp : :=cont_vals -> collect ("marketing",choose_first) (select (value) (cont_vals)) Returning now to FIG. 2, module 250 will be described in further detail. As described above in conjunction with FIG. 9, module 250 contains 6 sub-modules. The Ask_Reason_For_Call module 910 will be evaluated if the CUST_VALUE attribute has a value less than 7, as indicated by enabling condition 912. Module 910 is represented as a rectangle, which indicates that the module is a foreign module. Module 910 requires an IVR interaction and asks the caller the reason for calling. The reason is assigned to attribute IVR_CHOICE. The DL textual specification for module 910 is show in FIG. 20. The computation steps are set forth in lines 8-12, which indicate that the attribute IVR_CHOICE will be assigned the value "dom" or "intl" or the state of this attribute will be EXCEPTION with an exception value of 1, depending on the response to the IVR question. This module has a side-effect, as indicated in lines 14-15. The side effect is an IVR_dip, which will initiate an IVR question to the caller using the external IVR component 112 (FIG. 1). Module 920 is represented as a hexagon, which indicates that this module is a decision module and is specified using computation rules and a combining policy. The DL specification for module 920 is shown in FIG. 21. The computation rules specified in lines 12-30 specify the contributions to the BUSINESS_VALUE_OF_CALL attribute based on the input attributes. The combining policy as specified in lines 31-34 is a CPL function, business-value-of-call-cp, and indicates that the contribution of the rules with a true condition are added and rounded up with a default value of 0. The CPL program defining this function is as follows: Business_Value_of_Call_cp : :=cont_vals -> round_up (sum_true (cont_vals)) The DL specification for the Calculate_Send_Bonus_Check module 930 is shown in FIG. 22. This module is represented as a rectangle, which indicates that this is a foreign module. This module will only be evaluated if the enabling condition specified in lines 5-13 is True. In such case, the module performs the side-effect action of issuing a check to a customer as specified in lines 16-17. As shown in FIG. 9, all remaining sub-modules of the Routing_Decisions module 250 are represented as hexagons, which indicates that these modules are decision modules and are specified using computation rules and a combining policy. Turning now to the Calculate_Call_Priority module 940 module, the DL specification for this module is shown in FIG. 23. The computation rules specified in lines 8-20 specify the contributions to the CALL_PRIORITY attribute based on the input attributes. The combining policy as specified in lines 21-22 is a CPL function, call-priority-cp, and indicates that high value wins with a default value of 2. This means that the single highest contribution value for a true rule is the value that is assigned to the CALL_PRIORITY attribute. Thus, after all the computation rules are evaluated, there will be a collection of all the results, with the true rules contributing the value specified in the rule, and the false rules contributing .perp.. The combining policy will choose the highest value in the collection and assign that value to the output attribute CALL PRIORITY. If no rule has a true condition, then the value of 2 is assigned to CALL_PRIORITY. The CPL program defining this function is as follows: choose_sup : :=x,y -> if (x >=y) then x else y; Call_Priority_cp : :=cont_vals -> collect (2<choose_sup) (select (value) (cont_vals) The DL specification for the Calculate_Skill module 950 is shown in FIG. 24. The computation rules specified in lines 11-40 specify the contributions to the SKILL attribute based on the input attributes. The combining policy as specified in lines 41-45 is a CPL function, skill_cp, and indicates a weighted sum policy with ties being broken by the given ordering. Referring back to the computation rules, each true rule will contribute both a value and a weight to the SKILL attribute. For example, if the computation rule on lines 14-15 is evaluated to True, then the value high_tier with a weight of 40 is contributed to the SKILL attribute. After all the computation rules are evaluated, the sum of each of the weights for a particular value is computed, and the value that has the greatest weight is assigned to the SKILL attribute. If there is a tie between the weights of two different values, the value assigned to the SKILL attribute is determined by the ordering given by the combining policy. As an example, suppose the computation rule in line 28 and the computation rule in lines 32-35 are both evaluated to true. The computation rule in line 28 will contribute the value norm_tier_dom with a value of 30, and the computation rule in lines 32-35 will contribute the value norm_tier_dom with a value of 20. If these were the only two rules which contributed weights to the value norm_tier_dom, then the value norm-tier_dom would have a combined weight of 50 (30+20) when the combining policy was evaluated. If this combined weight of 50 for the value norm_tier_dom was the highest combined weight of any value, then the value norm_tier_dom would be assigned to the output attribute SKILL. The CPL program defining this function is as follows:
aggval : := X -> tupling ( hash:= x.hash; val :=
sum_true(x,vals,0))
complist : :=
[" collections" ," australia_promo" ," high_tier" ,
" low_tier_intl" ," low_tier_down" ]
ccomplist : := enum (complist)
compsel : := X -> x.f_a.val = x.s_a
poslist : := X -> (select(compsel) (factor(ccomplist,x) )#0.t_a.pos
compval : := X,y -> if (x,val > y.val) then x
else if y.val > x.val then y
elseif poslist(x) < poslist(y) then x else y
Skill_cp : := cont_vals -> collect(NULL, compval) (map (aggval)
(group (cont_vals) ) )
The DL specification for the Calculate_On_Queue_Promo module 960 is shown in FIG. 25. The computation rules specified in lines 8-13 specify the contributions to the ON_QUEUE_PROMO attribute based on the input attribute. The combining policy as specified in lines 14-15 is a CPL function, on-queue-promo-cp, and indicates first true wins with a default of 0. In accordance with this combining policy, the contribution of the true rule will be assigned to the attribute ON_QUEUE_PROMO. As described above, a constraint on this type of combining policy is that one and only one computation rule may evaluate to true. The CPL program defining this function is as follows: on_Queue_Promo_cp : :=cont_vals -> collect (NULL, choose_first) (select(value) (cont_vals)) Returning to FIG. 1, the above description described the DL specification 102. We now turn to a description of the decision engine 104 which will take the DL specification 102 and implement the specified workflow when an object (e.g., incoming call) is received at the workflow system 100. The following description will describe two embodiments of a decision engine 104. The first embodiment implements a straightforward execution of the workflow. The second embodiment implements an improved workflow execution which utilizes optimization strategies. The first embodiment of the decision engine 104 requires that a topological sort of the modules be created. In order to describe the topological sort, first the data and enabling flow diagram shown in FIG. 26 will be described. This diagram illustrates the data flow dependencies and the enabling flow dependencies of the workflow described above. Each of the modules (ovals) and enabling conditions (hexagons) are represented as nodes with solid line data flow edges representing data flow dependencies and broken line enabling flow edges representing enabling flow dependencies. Node 2601 represents the source attributes. A data flow edge from a module M to a module M' indicates that an output attribute of M is used as an input attribute of M'. An enabling flow edge from a module M to the enabling condition of a module M' indicates that the enabling condition of M' uses an output attribute from M. Also, there is an enabling flow edge from each enabling condition to the module that it qualifies. For example, there is a data flow edge 2602 from the identify_caller module 2604 to the info_about_customer module 2606 because the input attributes ACCOUNT_NUMBER and CUST_REC of the info_about_customer module 2606 are output attributes of the identify_caller module 2604. There is an enabling flow edge 2608 from the identify_caller module 2604 to the enabling condition 2610 of the info_about_customer module 2606 because the attribute ACCOUNT_NUMBER used in the enabling condition 2610 is an output attribute of the identify_caller module 2604. There is an enabling flow edge 2612 from enabling condition 2610 to the module 2606 which it qualifies. Thus, FIG. 26 shows the data flow and enabling flow dependencies for the routing_to_skill module 202 (FIG. 2). The data flow and enabling flow dependencies for lower level modules could similarly be shown using data and enabling flow diagrams. It is noted that the data and enabling flow diagrams of the modules are acyclic. That is, there is no module M for which there is a directed path in the graph composed of data flow and control flow edges that starts at M and ends at M. The first step of the decision engine 104 is to produce a topological sort of the modules in the workflow description. As is well known, a topological sort is an ordering of modules such that the ordering satisfies the following properties: If module M precedes module M' in the ordering then: there is no directed path in the graph composed of data flow edges and enabling flow edges that starts at M' and ends at M. Given the notation shown in FIG. 26, one topological sort for the modules shown in FIG. 26 is M.sub.1, M.sub.2, M.sub.3, M.sub.4, M.sub.5, M.sub.6. Topological sorts for lower level modules would be produced in a similar manner. After determining the topological sort, the modules may be executed such that a module is executed only after all preceding modules in the topological sort are completely finished executing and all attributes have been evaluated. Thus, given an ordering M.sub.1, M.sub.2, . . . M.sub.N, the modules are executed as follows: enabling condition of M.sub.1 is evaluated and if True, then module M.sub.1 is completely executed, if False, then module M.sub.1 is not executed; enabling condition of M.sub.2 is evaluated and if True, then module M.sub.2 is completely executed, if False, then module M.sub.2 is not executed; enabling condition of M.sub.N is evaluated and if True, then module M.sub.N is completely executed, if False, then module M.sub.N is not executed. The above steps describe how a determination is made as to whether a module will be executed. With respect to how a module is executed, it depends on the type of module. If the module is other than a decision module and therefore specified in terms other than computation rules and a combining policy, then the module is executed as specified in the module (e.g. C++ program, database dip, flowchart, declarative module, etc.), and the details of such execution will not be described in detail herein. If the module is a decision module specified in terms of computation rules and a combining policy, then the module is executed as follows: for each computation rule test the condition for True or False If False, produce .perp. and add to collection If True, then compute the value of the term on the right side of the rule and add to collection. (** at this point have a collection of values and/or .perp.**) apply combining policy program to the collection of values to produce the attribute value assign attribute value to the attribute; execute any side-effect, if any. The above described embodiment of the decision engine 104 executes the DL specification in a straightforward manner. That is, the various modules are executed sequentially in a topological order. However, the use of a more sophisticated execution technique can result in improved performance of the system. Such an execution technique will now be described. For clarity of exposition, the more sophisticated execution technique for executing declarative modules will be described in a simplified context, but one skilled in the art will be able to extend the description presented here so that it can be used on arbitrary declarative modules. In the simplified context, the focus is on a DL program that consists of a declarative module with one or more internal modules. It is further assumed that each internal module computes exactly one attribute, and may have a side-effect. It is further assumed that once enabled, internal modules will always produce a value and will never produce an exception value. Because each internal module produces only one attribute, a single state can be used for an attribute and the module that produces it. The states for attributes (modules) in this context are {UNINITIALIZED, VALUE, DISABLED}. Finally, suppose that module Mproduces attribute A. Because A is the only attribute produced by M, for convenience in exposition we refer to attribute A as a side-effect attribute if M is a side-effect module. Similarly, we refer to attribute A as a non-side-effect attribute if M is a non-side-effect module. When describing the more sophisticated execution technique, the term task is used to refer to an execution of a module during execution of an instance of the workflow. Thus, a task refers to the activity (actual or potential) of executing a module. As will be described below, in some cases a task will be identified but not carried out. For example, a module and input values for it may be identified as eligible for execution but subsequently be deemed unneeded for completing the workflow and thus not executed. A task is a side-effect task if the module underlying the task is a side-effect module. A task is a non-side-effect task if the module underlying the task is a non-side-effect module. A high level functional diagram of the decision engine 104 is shown in FIG. 28. The oval components represent data repositories and the rectangles represent software modules. The workflow schema 2810 represents the specification of how workflows are to be processed. For example, the workflow schema may be a DL specification as described above. Whenever a new object to be worked on is received (e.g. a new call enters a call center), a new instance of the workflow is created and stored in runtime workflow instances 2808. The execution engine 2812 works on a runtime workflow instance stored in 2808 in accordance with the workflow schema 2810 to execute the tasks in the workflow and to propagate the effects of the execution until the object has been fully processed. The execution engine 2812 works in a multi-thread fashion, so that it processes in parallel multiple workflow instances and multiple tasks within each instance. The task scheduler 2806 schedules the tasks that will be executed by the execution engine 2812. The task scheduler 2806 dynamically chooses the tasks to be executed from the candidate task pool 2802, which is maintained by the prequalifier 2804. The decision engine 104 executes tasks in an eager fashion, that is, the decision engine 104 will use available computing resources to execute tasks prior to fully determining whether such tasks are required for processing the workflow instance for a given object. Such speculative execution generally improves the performance of the system by reducing the response time (i.e., the time it takes to process inputs to the system) because computing resources will be fully utilized. Of course, by eager execution of tasks, certain tasks will be executed unnecessarily. However, the overall performance will be improved by eagerly executing certain tasks which, in fact, are needed to fully process the workflow instance. The presence of side-effect modules imposes an important restriction on the eager evaluation of tasks. In particular, in a workflow instance a side-effect module should not be executed eagerly unless it is known that the module would also be executed in accordance with the declarative meaning of the DL specification. This restriction is motivated by the assumption that the processing impact of executing a side-effect module is so significant that the possible benefit of eager execution of the module is outweighed by the desire to avoid execution that is not justified by the meaning of the DL specification. The prequalifier 2804 will determine three key properties of tasks which substantially improves the performance of the decision engine 104. Tasks which are eligible for eager evaluation are tasks which may be immediately evaluated, but which may or may not be required for complete processing of the workflow instance for a given object. It is noted that immediate execution of an eligible task will not violate the intended meaning of the DL specification. Tasks which are unneeded are tasks which are not needed for complete processing of the workflow instance for a given object. Tasks which are necessary are tasks which are known to be needed for complete processing of the workflow instance for a given object. By using these three characteristics of tasks, decision engine 104 can substantially improve its performance. Tasks which are eligible but unneeded may be deleted from the candidate task pool 2802, and tasks which are eligible and necessary may be given high priority because it is known that these tasks will be required for complete processing. Algorithms for determining whether tasks are eligible, unneeded, or necessary will be described below. Because of the complexity of the algorithms, the description will proceed in steps. First, an algorithm, identified as the basic algorithm, for determining whether tasks are eligible or unneeded will be described. Thereafter, an extension to the basic algorithm, identified as the extended algorithm, for further determining whether tasks are necessary will be described. In order to describe the algorithms, several definitions must be introduced. For purposes of this description, assume that a workflow schema S=(Att, Src, Tgt, Eff, Cnd, Mod) is fixed. This schema provides a mathematical formalism for describing DL specifications of declarative modules. The elements of the schema S are as follows: Att is a set of attributes; Src is the set of source attributes; Tgt is the set of target attributes; Eff is the set of side-effect modules; Cnd is the set of enabling conditions; and Mod is the set of modules. Recall that in the simplified context, each module produces as output a single non-source attribute. The algorithms described here focus on determining sets of attributes that are eligible, unneeded, or necessary. We also apply these terms to the modules associated with attributes, and to the tasks associated with those modules. For example, if attribute A is found to be eligible in the context of an execution of a workflow instance, then we also say that the module M that defines A is eligible in that context. Further, the task T of executing module M (whether this execution occurs or not) is said to be eligible in that context. In order to implement the basic algorithm, additional states (i.e., in addition to those described above) for attributes must be defined. The states used in the algorithm are: UNINITIALIZED ENABLED READY READY+ENABLED COMPUTED VALUE DISABLED. It is noted that the states EXCEPTION, and FAIL were defined above as attribute states, but are not used in conjunction with the simplified context for describing the execution algorithm. In the context of the execution of a workflow instance, the states for an attribute A are defined as follows. Initially, an attribute A will be in the state UNINITIALIZED. This indicates that the attribute A has not yet been considered in the execution. The state ENABLED indicates that it has been determined that A's enabling condition is, or will eventually be, True, but it is not yet determined whether A's input attributes are stable (i.e., the input attributes are in the state "value" or "disabled"), and the value for A has not yet been computed. The READY state indicates that the input attributes for A are stable, but no determination has been made as to whether A's enabling condition is true or false, and the value of A has not been computed. The state of READY+ENABLED indicates that the input attributes for A are stable and the enabling condition for A is true, but the value for A has not been computed. The state COMPUTED indicates that the value for A has been computed but it has not been determined whether the enabling condition for A is true or false. The state DISABLED indicates that the enabling condition for A is, or will eventually be, false. The state VALUE indicates that the value for A has been computed and the enabling condition for A is, or eventually will be, true. FIGS. 29 and 30 show the finite state automata (FSA) for this extended family of states. FIG. 29 shows the FSA for a non-side-effect attribute, and FIG. 30 shows the FSA for a side-effect attribute. The difference between the FSA for a non-side effect attribute (FIG. 29) and a side-effect attribute (FIG. 30) is that for side-effect attributes, the COMPUTED state is omitted. This is because, since the execution of modules computing side-effect attributes has significant impact on a system or user that is external to the workflow system, such modules should not be executed until it is known that their enabling conditions are, or eventually will be, true. For example, it would be undesirable to initiate an IVR side-effect which asks a caller to provide certain information if that information is not required for complete processing of the object. The states VALUE and DISABLED are represented in FIGS. 29 and 30 with double lines to indicate that they are terminal states for the attributes. If an attribute is in a terminal state then that attribute is considered stable. The notion of a snapshot will now be described. Snapshots are used to represent different stages in the execution of individual workflow instances. Let Att be a set of attributes with associated states. For each attribute A the type of A is denoted by .tau.(A). A snapshot for Att is a pair s=(.sigma.,.mu.) where 1. the state mapping .sigma. is a total function from Att into {UNINITIALIZED, ENABLED, READY, READY+ENABLED, COMPUTED, VALUE, DISABLED} 2. The value mapping .mu. is a partial function from Att into .orgate.{.tau.(A).vertline.A.epsilon.Att}, such that for each A, .mu.(A) is defined iff .sigma.(A)=VALUE or .sigma.(A)=COMPUTED. If .mu.(A) is defined then .mu.(A).epsilon..tau.(A). Thus, a snapshot is a data structure which stores the state (.sigma.) of each attribute, and if the state of an attribute is VALUE then the data structure also stores the value (.mu.) of the attribute. The snapshot contains relevant information at a particular point during workflow execution. As execution of the workflow progresses, the snapshot will change to reflect the new information determined during execution. One snapshot s' extends another snapshot s (specified as s<s') if for each attribute A: (a) if A has a value in s, then A has the same value in s'; and (b) the state of A in s'.gtoreq.the state of A in s; where .gtoreq. is relative to the FSAs of FIGS. 29 and 30. Thus, criteria (b) means that the state of A in s' is equal to, or at a higher level in the FSA than, the state of A in s. One snapshot s' strictly extends another snapshot s if for at least one attribute A, the state of A in s' is>the state of A in s. A snapshot s is complete if each attribute A in s is stable. That is, each attribute has a state of VALUE or DISABLED. For the purposes of describing the execution algorithm a particular formal definition for enabling conditions in DL specifications is now presented. One skilled in the art will be able to use the techniques described here in connection with DL specifications that use a different formalism for enabling conditions and/or enabling conditions that can test values and properties different than those tested by the enabling conditions presented here. A denotes attributes, term denotes terms, and pred denotes Boolean functions (such as comparison term .theta. term) on terms which do not refer to states of attributes. The syntax of conditions is given by the following: cond : :=pred(term, . . . ,term).vertline.VALUE(A).vertline.DISABLED(A).vertline.{character pullout}cond.vertline.cond {character pullout}cond.vertline.cond {character pullout}cond The truth value of conditions is given by the standard two-valued logic when the involved attributes are stable, except that pred(t.sub.1, . . . ,t.sub.k) is true if all attributes referred to by pred(t.sub.1, . . . ,t.sub.k) have state VALUE and pred(t.sub.1, . . . ,t.sub.k) is true in the standard sense, and it is false otherwise. Thus, when evaluating an expression, if one or more of the attributes is in the state DISABLED, then the truth value is false. Note that this logic does not always behave in the standard way (e.g. A>3{character pullout}A.ltoreq.3 is not a tautology). The truth value of a condition in a snapshot s where all attributes occurring in a condition .gamma. are stable, is denoted TruthVal(.gamma.,s). A complete snapshot is enabling-consistent if for each attribute A which is not a source attribute, the state of A is VALUE if and only if the truth value of the enabling condition of A relative to s is true. A second notion of consistency concerns the relationship between the values of the attributes and the modules that define them. To provide an interpretation for the behavior of modules we define an environment for schema S to be a mapping .epsilon. such that, for each module M in S.sub.1 if M has input attributes B.sub.1, . . . , B.sub.n and output attribute 1 then .epsilon. (M) is a total mapping from (T(B.sub.1).orgate..perp.) x . . . x (T(B.sub.n).orgate..perp.) to T (A). The use of a static environment in this formalism is a convenience for this description. In practice, DL workflows will operate in the context of a dynamic world, i.e., the environment associated with a given workflow instance may be the result of combining the behaviors of different modules at different points in time, rather than from a single point in time. A complete snapshot s is .epsilon.-consistent for environment .epsilon. if for each attribute A such that .sigma.(A)=VALUE, .mu.(A) is equal to the A-value computed by .epsilon. (M) (.mu.(B.sub.1), . . . , .mu.(B.sub.n)), where M is the module producing attribute A and has input attributes B.sub.1, . . . , B.sub.n. (Note that if B.sub.i does not have state VALUE in s for some i, then .mu.(B.sub.i)=.perp..) An environment .epsilon. is compatible with snapshot s if it agrees with all defined values of .mu. in s. For a snapshot s, s.vertline..sub.Src denotes the snapshot whose state and value functions agree with those of s on all source attributes, and such that all non-source attributes have state UNINITIALIZED. A snapshot s over S is permissible if (i) there exists an environment .epsilon. that is compatible with s, and (ii) for each environment .epsilon. compatible with s, if s' is a complete snapshot that extends s.vertline..sub.Src and is compatible with .epsilon., then s' extends s and the set of side-effect modules with state in {ENABLED, ENABLED+READY, VALUE} in s is a subset of the set of side-effect modules with state VALUE in s'. It is noted that the notion of permissible snapshot captures in an absolute sense the family of snapshots s such that all determinations in s concerning whether attributes are ENABLED or DISABLED and all side-effect actions that were executed in s are consistent with the declarative semantics associated with S. In practical situations (e.g., in situations where the condition language includes integers with addition and multiplication) the determination of whether a snapshot is permissible or not is undecidable, i.e., there is no algorithm that always terminates that determines whether, for a given DL schema S and snapshot s, whether s is permissible for S. Even when the condition language is restricted to permit atomic types with equality, deciding whether a snapshot is permissible is intractable. However, it is possible to develop sufficient conditions for permissible that are tractable, even if the condition language is quite rich. In the algorithm developed here, execution of workflow S begins with a snapshot such that all source attributes are stable and all other attributes are in state UNINITIALIZED. Then a sequence of permissible snapshots is constructed, each one a strict extension of the previous one. Execution halts when a terminal snapshot is reached. A non-source attribute A is absolute-enabled for permissible snapshot s if for each complete snapshot s' that extends s, A has state VALUE. A non-source attribute A is absolute-disabled for snapshot s if s is permissible and for each complete snapshot s' that extends s, A has state DISABLED. Given a permissible snapshot s over S then: A side-effect attribute A is absolute-eligible in s if A is absolute-enabled and each input attribute for A is stable. A non-side-effect attribute A is absolute-eligible in s if each input attribute for A is stable. A snapshot s=(.sigma.,.mu.) over S is terminal if s is permissible and .sigma.(A).epsilon. {VALUE,DISABLED} for each A.epsilon.Tgt. That is, a snapshot is terminal if it is permissible and all target attributes are stable. A snapshot s over S is minimal terminal if s is terminal and s is not a strict extension of another terminal snapshot for S. An attribute A is absolute-unneeded for permissible snapshot s over S if for each minimal terminal snapshot s'=(.sigma.',.mu.') that extends s, .sigma.'(A) {COMPUTED,VALUE}. As with the definition of permissible, the notions of absolute-eligible and absolute-unneeded define, in an absolute sense, all eligible attributes and all unneeded attributes, for a given permissible snapshot during execution of a workflow schema. However, the actual computation of all eligible or unneeded attributes is not possible in practical situations, e.g., if the condition language includes integers with addition and multiplication. Even if the condition language is limited to include only atomic types with equality, computing all eligible or unneeded attributes is intractable. Thus a subset of absolute-eligible and absolute-unneeded attributes is determined in order to improve the performance of a workflow execution. The basic and extended algorithms are used to determine which attributes to evaluate eagerly, that is, which attributes should be computed even though not all of the attributes occurring in their associated enabling conditions have become stable. Such an analysis involves partial computations of conditions, since the conditions may depend on attributes which have not yet been computed. In order to represent such partial computations, a three valued logic is used. The truth value for a given condition may be true, false, or unknown. Instead of considering each enabling condition as one indivisible three-valued logic formula, enabling conditions are represented by trees. This gives more precise knowledge as to which sub-formulas are true and which are false. Condition trees are used for this purpose. A condition tree of an enabling condition P is obtained from the parse tree (as well known in the art) of P by replacing each leaf node p of the form pred(t.sub.1, . . . , t.sub.k) with a tree T(p) defined as: the root node of T(p) is an AND operator node; pred(t.sub.1, . . . , t.sub.k) is a leaf node of T(p); and VALUE (A) is a leaf node of Tfp) if A occurs inpred(t.sub.1, . . . , t.sub.k). All the leaf nodes are directly connected to the root node. For example, consider the enabling condition: (NOT(F=3 AND G=4)) OR DISABLED (F). The condition tree for this enabling condition is shown in FIG. 31. Now, in order to determine which tasks may be computed eagerly, a dependency graph is defined which will take into account the dependencies between the enabling conditions and the attributes, and the dependencies between the attributes themselves. The dependency graph is defined as follows. Given a workflow schema S, the dependency graph of S, denoted D.sub.S, is a directed acyclic graph that is constructed as follows: each enabling condition in the workflow schema S is represented by its condition tree in D.sub.S ; each attribute in A is a node in D.sub.S ; there is an edge from the root node of each condition tree to the attribute node attached to the associated enabling condition in S; there is an edge from an attribute A to a predicate node p if and only if A occurs in p; there is an edge from an attribute A to an attribute B if and only if A is an input attribute of B. As an example, consider the workflow schema represented by the data and enabling flow diagram of FIG. 32. As described above in conjunction with the data and enabling flow diagram of FIG. 26, the data and enabling flow diagram of FIG. 32 illustrates the data flow dependencies (solid lines) and the enabling flow dependencies (broken lines) for a given workflow schema. Given the workflow schema represented in FIG. 32, the dependency graph for that workflow schema is shown in FIG. 33. In FIG. 33, all nodes belonging to an evaluation tree are condition nodes, with the remaining nodes being attribute nodes. The edges between attribute nodes are shown with broken lines and are data edges and the edges between condition nodes are shown with solid lines and are called condition edges. Finally, prior to describing the basic algorithm, the notion of an extended snapshot must be defined. An extended snapshot is a tuple s=(.sigma., .mu., .alpha., Hidden-att, Hidden-edge) where: (a) the state mapping .sigma. is a total function from Att into {UNINTIALIZED, ENABLED, READY, READY+ENABLED, COMPUTED, VALUE, DISABLED) (b) The value mapping .mu. is a partial function from Att into .orgate.{.tau.(A).vertline.A.epsilon.Att}, such that for each A, .mu.(A) is defined iff .sigma.(A)=VALUE. If .mu.(A) is defined then .mu.(A).epsilon..tau.(A) (c) a maps each condition node to T (true), F (false), or U (unknown) (d) Hidden-att is the set of attributes which have been hidden (the notion of a hidden attribute will be described below); and (e) Hidden-edge is the set of edges (both data edges and condition edges) which have been hidden (the notion of a hidden edge will be described below). The pseudo code for the basic algorithm for determining whether a task is eligible or unneeded is shown in FIGS. 34A-D. Generally, the algorithm starts at the beginning of the execution of a workflow instance and ends when the execution is completed. The prequalifier 2804 (FIG. 28) executes this algorithm for each workflow instance. The algorithm computes and incrementally maintains the states (in an array .sigma.[ ]) and the values (in the array .mu.[ ]) of the attributes defined in the workflow schema 2810. In order to carry out its computations, the algorithm uses the dependency graph D.sub.S. It incrementally computes a set of nodes called hidden-att such that the attribute nodes contained in the set hidden-att are stable or unneeded, and a set of edges called hidden-edge where edges contained in hidden-edge are edges which have been traversed by the algorithm, and do not have to be considered again by the algorithm. More generally, if an attribute or edge is "hidden", then the information embodied in that attribute or edge relevant to the algorithm has already been used during execution and possibly incorporated into the snapshot, and will not be needed in any subsequent step of the algorithm. The algorithm also maintains an array of three valued logic values (.alpha.[ ]) for condition nodes. The algorithm consists of two main phases. The first phase is an initialization phase which is executed once at the beginning of execution of a workflow instance. The second phase is the incremental phase which is executed each time a value of an attribute is computed by the execution engine 2812 and incorporated into the runtime workflow instances 2808. The incremental phase is also executed for the source attributes when the workflow instance is initially placed into workflow instances 2808. The pseudo-code for the basic algorithm shown in FIGS. 34A-D will now be described. Section 3402 of the algorithm is the definition of the global variables. Section 3404 is the definition of some of the notations used in the algorithm. The initialization phase 3406 is executed once at the beginning of execution of a workflow instance in order to initialize the required data structures. In section 3408, the states and values of the attribute nodes of the dependency graph are initialized such that the state of the source attribute nodes are initialized to a state of READY+ENABLED and all other attribute nodes are initialized to a state of UNINITIALIZED. The values (.mu.) of the attributes are set to null. In section 3410, the logic values (.alpha.[ ]) for condition nodes are initialized to unknown. In section 3412, the set of hidden edges and hidden attributes is set to null. This is the end of the initialization phase 3406. The remainder of the pseudo code defines the incremental phase. Each time a new value for an attribute is computed by the execution engine 2812 (FIG. 28), the increment function 3414 is called as part of the operation of the prequalifier 2804. The increment function is also called by the prequalifier 2804 at the beginning of processing a workflow instance, once for each source attribute. The increment function 3414 then calls the propagate_att_change function 3422 which in turns recursively calls the propagate_cond_change function 3450 in order to propagate changes along the dependency graph. Both the propagate_att_change function 3422 and the propagate_cond_change function 3450 call the recursively defined functions hide_edge 3474 and hide_node 3476. These functions will now be described in further detail. The increment function is shown in section 3414. As shown by the input section 3416, this function is called when a value .nu. has been computed for an attribute A in the dependency graph G. First, the value (.mu.) of the attribute is updated in step 3418. Next, in section 3420 the propagate_att_change function is called. If the current state of attribute A is READY, then the propagate_att_change function is called with parameters indicating that the state of A should be updated to COMPUTED. If the current state of attribute A is ENABLED+READY then the propagate_att_change function is called with parameters indicating that the state of A should be updated to VALUE. The increment function then ends. The propagate_att_change function is shown in section 3422. The input to this function, as shown in section 3424, is an attribute B and a state (.sigma.) for B. In section 3426 the state (.sigma.) for attribute B is updated. In section 3428, changes are propagated up the dependency graph as a result of the newly computed attribute as follows. If the state of the attribute B has changed to VALUE or COMPUTED, then in section 3430 an attempt is made to evaluate predicate nodes which use the value of B. Thus, for each condition node in which B occurs in the predicate (line 3432) and for which the edge in the dependency graph from B to the predicate is not currently hidden (line 3434), the edge is hidden (line 3436) and an attempt is made to evaluate the predicate using the new value of B. If the predicate can be evaluated, then the logic value (.alpha.) is updated to True or False and the change is propagated by calling the propagate_cond_change function (line 3438). The propagate_cond_change function will be described in further detail below. Thereafter, for each attribute node C which has B as an input attribute, if B has the state VALUE and the value for B is the last input attribute needed for C to go stable, then attribute C is promoted to the READY state by calling the propagate_att_change function (section 3440). If the state of attribute B is ENABLED, then in section 3442 for each condition node p of the form VAL(B) the state of p (.alpha.[p]) is set to TRUE, and for each condition node p of the form DIS(B) the state of p (.alpha.[p]) is set to FALSE, and the changes are propagated by calling the propagate_cond_change function. This processing takes place because when it is known that an attribute B is enabled, then the truth value of VAL(B) must be true, because the attribute will eventually be assigned some value. Similarly, the truth value of DIS(B) is known to be false. In a manner similar to that described above in conjunction with section 3442, if the state of attribute B is DISABLED, then in section 3444 for each condition node p of the form VAL(B) the state of p (.alpha.[p]) is set to FALSE, and for each condition node p of the form DIS(B) the state of p (.alpha.[p]) is set to TRUE, and the changes are propagated by calling the propagate_cond_change function. Thereafter, in a manner similar to step 3440, for each attribute node C which has B as an input attribute, if the value for B is the last input attribute needed for C to go stable, then attribute C is promoted to the READY state by calling the propagate_att_change function (section 3446). The last line 3448 of the propagate_att_change function indicates that if the state of B has become DISABLED or VALUE (i.e., attribute B has become stable), then the node is hidden. The propagate_cond_change pseudo-code is shown in section 3450. This is a recursive algorithm which propagates condition changes up the dependency graph. The input to this function is a condition node p in the dependency graph G. The node n is the parent of the node p (line 3452). If the edge from p.fwdarw.n is not hidden, then section 3454 is executed. Otherwise, the function ends. First, the edge from p.fwdarw.n is hidden (line 3456). If the parent of p (n) is an OR condition node section 3458 is executed. If the truth value of condition node p is true, then the truth value of the parent node n (.alpha.[n]) is set to true (because an OR condition is true if any of its components is true) and the change is further propagated up the dependency graph by recursively calling the propagate_cond_change function for node n (line 3460). If the truth value of condition node p is false and if there are no other non-hidden edges into the parent n, then the truth value of the parent node n (.alpha.[n]) is set to false (because if there are no more non-hidden edges then there are no more possibilities for a component of n to be true), and the change is further propagated up the dependency graph by recursively calling the propagate_cond_change function for node n (3462). If the parent of p (n) is an AND condition node section 3464 is executed. If the truth value of condition node p is false, then the truth value of the parent node n (.alpha.[n]) is set to false (because an AND condition is false if any of its components is false) and the change is further propagated up the dependency graph by recursively calling the propagate_cond_change function for node n (line 3466). If the truth value of condition node p is true and if there are no other non-hidden edges into the parent n, then the truth value of the parent node n (.alpha.[n]) is set to true (because if there are no more non-hidden edges then there are no more possibilities for a component of n to be false), and the change is further propagated up the dependency graph by recursively calling the propagate_cond_change function for node n (3468). If the parent of p (n) is a NOT condition node then the truth value of the parent node n (.alpha.[n]) is set to the inverse of the truth value of condition node p in 3470. If the parent of p (n) is an attribute node, then the enabling condition for node n can now be evaluated and section 3472 of the pseudo code is executed. If the truth value of condition node p is true, then the propagate_att_change function is called to update the state of node n to ENABLED. Otherwise, if the truth value of condition node p is false, then the propagate_att_change function is called to update the state of node n to DISABLED. The hide_edge function is shown in section 3474. The hide_edge function receives as input an edge (n,n') in g. The function will hide a node n if the received edge (n,n') is the last non-hidden edge emanating from n. The hide_node function is shown in section 3476. The hide_node function receives as input a node n in g. The function hides all edges into n. When the basic algorithm is finished executing, there is a new updated snapshot stored in the memory of the system. Because of properties of the algorithm, this snapshot is permissible. A determination as to which attributes are eligible is made as follows. A non-side effect attribute is eligible if its state (.sigma.) is READY or READY+ENABLED. A side effect attribute is eligible if its state (.sigma.) is READY+ENABLED. Recall that if an attribute A is determined to be eligible for execution then the task corresponding to execution of the module that defines A is also viewed as eligible for execution. Thus, since side-effect tasks have significant impact external to the workflow system, a side-effect task is eligible for eager evaluation only if the data is available for its evaluation and if it is known that its enabling condition will ultimately be true (i.e. the corresponding attribute is in state READY+ENABLED). Non-side-effect tasks, on the other hand, have no significant external impact, and a non-side-effect task may be considered as eligible for eager evaluation when its data inputs are available, whether or not it is known that its enabling condition will ultimately be true (i.e. the corresponding attribute is in state READY or READY+ENABLED). Further, a determination as to which attributes, and hence which tasks, are unneeded is made as follows. An attribute A is unneeded if the node for A in the dependency graph is hidden and the state of A is not COMPUTED or VALUE. The node of an attribute may become hidden if its value will not be used, directly or indirectly, in the evaluation of any target attribute. As a particular example, if the attribute is an input for some target attribute but partial evaluation of the enabling condition for the target attribute indicates that the enabling condition will take the value FALSE, and the attribute will not be used, directly or indirectly in the evaluation of any other target attribute, then the node of the attribute will become hidden. Recall that if attribute A is unneeded then the task corresponding to execution of the module producing A is also viewed as unneeded. At this point, the prequalifier 2804 (FIG. 28) identifies all tasks which are eligible and not unneeded as candidate tasks and provides these candidate tasks to the candidate task pool 2802. If a task which was previously identified as eligible is newly identified as unneeded, then the corresponding task is removed from the candidate task pool 2802. In determining that an attribute is ENABLED, READY+ENABLED, or DISABLED the algorithm may use a partial evaluation of the enabling condition of the attribute, i.e., an evaluation of all or part of the ultimate value of the enabling condition based on the states and/or values of some but not all of the attributes occurring in the enabling condition. It is noted that the running time of this algorithm for executing the workflow S on an input is linear in the number of edges in D.sub.S. Given the above description and the pseudo code in FIGS. 34A-34D, one skilled in the art could readily implement the algorithm. The basic algorithm will therefore update the snapshot when a new attribute value is computed and the updated snapshot allows a determination to be made as to whether a task is eligible and/or unneeded. As described above, another characteristic of tasks, namely necessary, is also used in order to improve the performance of the decision engine 104. If a task is known to be necessary to complete the workflow execution, then that task should be given high priority for evaluation. Pseudo code for the extended algorithm for determining whether a task is necessary is described below in conjunction with FIGS. 35A-35G. In order to describe the extended algorithm, several definitions must be introduced. Given an extended snapshot s=(.sigma.,.mu.,.alpha., Hidden--att, Hidden--edge), an attribute A is a relative source attribute if each in-edge of A is an element of Hidden--edge. A snapshot s=(.sigma.,.mu.,.alpha., Hidden--att, Hidden--edge) is eager if and only if: (a) For each relative source attribute A in S, .sigma.(A).epsilon.{VALUE, DISABLED, READY+ENABLED}; (b) For each non-relative source attribute A, .sigma.(A).gtoreq.ENABLED iff .alpha.(n)=T where n is the root node of the enabling condition of A; (c) For each non-relative source attribute A, .sigma.(A).gtoreq.DISABLED iff .alpha.(n)=F where n is the root node of the enabling condition of A; (d) For each non-relative source attribute A, .sigma.(A).gtoreq.READY iff for each input attribute B of A, .sigma.(B).epsilon.{VALUE,DISABLED}; (e) For each non-relative source attribute A, .sigma.(A).epsilon.{COMPUTED,VALUE}iff .mu.(A) is defined; (f) for each condition node n, .alpha.(n) is defined accordance with the basic algorithm (section 3450) based on the value of .sigma. and .mu.; (g) Hidden-node is defined in accordance with the basic algorithm (section 3474) based on the value of .sigma. and .mu.; (h) Hidden--edge is defined in accordance with the basic algorithm (section 3476) based on the value of .sigma. and .mu.. It is noted that the snapshots produced by the basic algorithm will satisfy the above criteria for an eager snapshot. There are four properties that are useful in determining necessary tasks: True-Necessary, False-Necessary, Value-Necessary, and Stable-Necessary. True-Necessary and False-Necessary properties give information about the necessary relationship between an attribute and a predicate. Intuitively, an Attribute A is True-Necessary for a condition node p if in order for .alpha.(p)=T (in later snapshots), the value of A must be known. More formally: Let D be a dependency graph, and let s=(.sigma.,.mu.,.alpha., Hidden--att, Hidden--edge), be an eager snapshot. An attribute A is True-Necessary for a condition node p, if the following is true: if for each eager snapshot s'=(.sigma.',.mu.',.alpha.', Hidden--att', Hidden--edge') such that s<s', and .alpha.'(p)=T, then .sigma.'(A) is in {VALUE, COMPUTED}. Intuitively, an Attribute A is False-Necessary for a condition node p if in | ||||||
