Ejemplo n.º 1
0
        private static void AddComponentAndEdgesBoth(Graph graph, WorkflowComponent component, ReversalMode mode)
        {
            graph.AddVertex(CS(component.Id));
            var reversable = component as IReversableWorkflow;

            foreach (Data data in reversable.ReversedInputs)
            {
                if (mode == ReversalMode.GroupNonReversibleOnly && !(data is DoubleData))
                {
                    graph.AddEdge(data.Id, CS(component.Id));
                    graph.AddEdge(CS(component.Id), data.Id);
                }
                else if (mode == ReversalMode.GroupBoth)
                {
                    graph.AddEdge(data.Id, CS(component.Id));
                    graph.AddEdge(CS(component.Id), data.Id);
                }
            }
            foreach (Data data in reversable.ReversedOutputs)
            {
                if (mode == ReversalMode.GroupNonReversibleOnly && !(data is DoubleData))
                {
                    graph.AddEdge(CS(component.Id), data.Id);
                    graph.AddEdge(data.Id, CS(component.Id));
                }
                else if (mode == ReversalMode.GroupBoth)
                {
                    graph.AddEdge(data.Id, CS(component.Id));
                    graph.AddEdge(CS(component.Id), data.Id);
                }
            }
        }
Ejemplo n.º 2
0
        private static List <WorkflowComponent> ClusterReversedModel(string name, List <Data> allData, List <WorkflowComponent> matchedComponents, List <WorkflowComponent> reversedComponents, ReversalMode mode, List <WorkflowComponent> components)
        {
            //// Identify Reversed Components
            //foreach (var component in matchedComponents)
            //	if (component is IReversableWorkflow reversable && reversable.ReversedInputs.Count > 0)
            //		reversedComponents.Add(component);

            // 3.1. Graph only with reversed links of non-reversible variables only, both forward and backward (can be thought as undirected)
            var reversedLinksGraph = new Graph();

            foreach (Data data in reversedComponents.GetAllData())
            {
                reversedLinksGraph.AddVertex(data.Id);
            }
            foreach (WorkflowComponent component in reversedComponents)
            {
                AddComponentAndEdgesBoth(reversedLinksGraph, component, mode);
            }

            // 3.2. Forward graph - To trace forward dependencies
            var forwardGraph = new Graph();

            foreach (Data data in allData)
            {
                forwardGraph.AddVertex(data.Id);
            }
            foreach (WorkflowComponent component in matchedComponents)
            {
                AddComponentAndEdgesForward(forwardGraph, component);
            }

            //forwardGraph = GraphBuilder.FromTwoSets(matchedComponents, allData, name1: c => CS(c.Id), from1to2: c => c.ModelDataOutputs, to1from2: c => c.ModelDataInputs);

            // 3.3. Reversed graph - To trace backward dependencies
            var reversedGraph = new Graph();

            foreach (Data data in allData)
            {
                reversedGraph.AddVertex(data.Id);
            }
            foreach (WorkflowComponent component in matchedComponents)
            {
                AddComponentAndEdgesBackWard(reversedGraph, component);
            }

            // 3.4 Group reversed components
            var visitedComponents      = new HashSet <string>();
            var reversedComponentsHash = new HashSet <string>(reversedComponents.Select(c => CS(c.Id)));
            var componentsHash         = new HashSet <string>(matchedComponents.Select(c => CS(c.Id)));
            var componentsUnderStudy   = new Stack <string>();
            var groups = new List <HashSet <string> >();
            HashSet <string> groupForwardHash  = null;           // Used to reduce unnecesary visits, if node is visited for one component in the group it shouldn't be visited more
            HashSet <string> groupBackwardHash = null;           // Used to reduce unnecesary visits, if node is visited for one component in the group it shouldn't be visited more

            foreach (WorkflowComponent component in reversedComponents)
            {
                // 3.4.1. If the component has not been studied start studie and prepare a gropup for the component
                if (!visitedComponents.Contains(CS(component.Id)))
                {
                    groups.Add(new HashSet <string>());
                    groupForwardHash  = new HashSet <string>();
                    groupBackwardHash = new HashSet <string>();
                    componentsUnderStudy.Push(CS(component.Id));
                }

                while (componentsUnderStudy.Count > 0)
                {
                    // 3.4.2. Get the component under study to investigate its dependencies
                    string componentUnderStudy = componentsUnderStudy.Pop();

                    if (visitedComponents.Contains(componentUnderStudy))
                    {
                        continue;
                    }

                    // 3.4.3. Group with adajacent reversed components
                    HashSet <string> adjacent = reversedLinksGraph.DepthFirstSearch(componentUnderStudy);
                    foreach (string adj in adjacent)
                    {
                        visitedComponents.Add(adj);
                    }

                    // If there is more than one component joint by non-reversible variables
                    if (adjacent.Where(a => reversedComponentsHash.Contains(a)).Count() > 1)
                    {
                        // 3.4.4. Extend with others dependencies
                        HashSet <string> affectedForward  = forwardGraph.DepthFirstSearch(adjacent, groupForwardHash);
                        HashSet <string> affectedBackward = reversedGraph.DepthFirstSearch(adjacent, groupBackwardHash);
                        affectedForward.IntersectWith(affectedBackward);
                        adjacent.UnionWith(affectedForward);
                    }

                    // 3.4.5. If dependencies include a new reversed model push to the stack to be studied
                    foreach (string adj in adjacent)
                    {
                        // If a component is a reversed component and hasn't been added yet
                        if (!visitedComponents.Contains(adj) && reversedComponentsHash.Contains(adj))
                        {
                            componentsUnderStudy.Push(adj);
                        }
                        else
                        {
                            visitedComponents.Add(adj);
                        }

                        // Add to the group of dependent model from the first reversed model under study
                        if (componentsHash.Contains(adj))
                        {
                            groups.Last().Add(adj);
                        }
                    }
                }
            }

            // 3.5 Create Globally Reversed Workflows for each group
            var globalReversedComponents = new List <WorkflowComponent>();
            var componentsDict           = matchedComponents.ToDictionary(c => CS(c.Id));

            foreach (HashSet <string> group in groups)
            {
                if (group.Count > 1)
                {
                    var         groupComponents = group.Select(c => componentsDict[c]).ToList();             // new List<WorkflowComponent>();
                    List <Data> groupData       = groupComponents.GetAllData();
                    var(groupInputs, groupOutputs, _) = groupComponents.GetInputsOutputsStatus(groupData);

                    GlobalReversalMode globalMode = (mode == ReversalMode.GroupNonReversibleOnly)
                                                ? GlobalReversalMode.ReverseModelsWhenReversibleVariables
                                                : GlobalReversalMode.NoReversedModels;
                    string   globalName     = WorkflowGlobal.GetGlobalWorkflowName(name, components, groupComponents);
                    Workflow globalWorkflow = ScheduleWorkflowGlobal(globalName, "", groupInputs, groupOutputs, groupComponents, globalMode);

                    globalReversedComponents.Add(globalWorkflow);
                }
                else
                {
                    // If the group consists of one component only, it is already a reversed model and does not have any unfeasible reversal
                    globalReversedComponents.Add(componentsDict[group.First()]);
                }
            }

            // 3.6. Add the rest of components
            globalReversedComponents.AddRange(matchedComponents.Where(c => !visitedComponents.Contains(CS(c.Id))));

            return(globalReversedComponents);
        }
Ejemplo n.º 3
0
        public static Workflow ScheduleWorkflow(string name, string description, List <Data> inputs, List <Data> outputs, List <WorkflowComponent> components, ReversalMode mode)
        {
            // Redirect to right scheduler method
            if (mode == ReversalMode.Global)
            {
                return(ScheduleWorkflowGlobal(name, description, inputs, outputs, components, GlobalReversalMode.Global));
            }
            else if (mode == ReversalMode.Legacy)
            {
                return(LibishScheduler.ScheduleWorkflow(name, description, inputs, outputs, components));
            }

            List <WorkflowComponent> workflowComponents = components.GetAllComponents();
            var allData = inputs.Concat(outputs).ToList();

            // 0. Sanity checks, check array is not more than 1 output
            NonReversibleSanityCheck(workflowComponents);

            // 1. Find Model-Variable matching. Which variables are inputs, and wich are outputs for each model
            MatchingDictionary outputsDict = MatchModelsWithVariables(inputs, allData, workflowComponents);

            // 2. Determine which models are reversed, and create reversed Workflows (Model or Global) to cater for them
            ReverseComponents(name, outputsDict, workflowComponents, out List <WorkflowComponent> matchedComponents, out List <WorkflowComponent> reversedComponents);

            // 3. Cluster reversed components joint by non-reversible variables (e.g. arrays)
            List <WorkflowComponent> reversedClusteredComponents = ClusterReversedModel(name, allData, matchedComponents, reversedComponents, mode, components);

            // 4. Cluster Strongly Connected Components to get an acyclic graph
            List <WorkflowComponent> clusteredComponents = ClusterStronglyConnectedComponents(name, allData, reversedClusteredComponents);

            // 5. Schedule the acyclic graph to get the final order of the components
            List <WorkflowComponent> scheduledComponents = ScheduleAcyclic(allData, clusteredComponents);

            return(new Workflow(name, description, inputs, outputs, components, scheduledComponents, false, mode.ToString())
            {
                DependencyAnalysis = new GraphBasedDependencyAnalysis(matchedComponents)
            });
        }
Ejemplo n.º 4
0
        public static Workflow ScheduleWorkflow(string name, string description, List <Data> inputs, List <Data> outputs,
                                                List <WorkflowComponent> components, MatchingDictionary matching, ReversalMode mode)
        {
            if (mode == ReversalMode.Global || mode == ReversalMode.Legacy)
            {
                throw new ArgumentException($"Only reversals modes: '{ReversalMode.GroupNonReversibleOnly}' and '{ReversalMode.GroupBoth}' " +
                                            $"are valid to schedule a workflow from a matching", nameof(mode));
            }

            List <WorkflowComponent> workflowComponents = components.GetAllComponents();
            var allData = inputs.Concat(outputs).ToList();

            // 2. Determine which models are reversed, and create reversed Workflows (Model or Global) to cater for them
            ReverseComponents(name, matching, workflowComponents, out List <WorkflowComponent> matchedComponents, out List <WorkflowComponent> reversedComponents);

            // 3. Cluster reversed components joint by non-reversible variables (e.g. arrays)
            List <WorkflowComponent> reversedClusteredComponents = ClusterReversedModel(name, allData, matchedComponents, reversedComponents, mode, components);

            // 4. Cluster Strongly Connected Components to get an acyclic graph
            List <WorkflowComponent> clusteredComponents = ClusterStronglyConnectedComponents(name, allData, reversedClusteredComponents);

            // 5. Schedule the acyclic graph to get the final order of the components
            List <WorkflowComponent> scheduledComponents = ScheduleAcyclic(allData, clusteredComponents);

            return(new Workflow(name, description, inputs, outputs, components, scheduledComponents, false, mode.ToString())
            {
                DependencyAnalysis = new GraphBasedDependencyAnalysis(matchedComponents)
            });
        }