/// <summary> /// Given the Model Objects, data objects and the vector(vIndep) in which '1' represent an independent variables , this function creates /// a subprocess after performing the computational proces modelling /// </summary> /// <param name="name"></param> /// <param name="components"></param> /// <param name="dataObjects"></param> /// <param name="independent"></param> /// <returns></returns> public static Workflow ScheduleWorkflow(string name, string description, List <Data> inputs, List <Data> outputs, List <WorkflowComponent> components) { explorationWatch.Restart(); List <Data> data = components.GetAllData(inputs, out int[] independent); // Incidence matrices for the workfow IncidenceMatrix IMf = LibishMatrixCalculators.GetIncidenceMatrix(components, data); IncidenceMatrix IMi = VariableFlowModelling(IMf, independent); // Model-based DSM DesignStructureMatrix DSM = IMMtoDSM(IMi); // Locates SCCs List <Cluster> clusters = Decompose(DSM); // SCC-based incidence matrix IncidenceMatrix IMU = CreateUpMatrix(IMi, clusters); // SCC-based DSM DesignStructureMatrix DSMU = IMMtoDSM(IMU); // Orders the models, so there is only feed-forward List <int> order = SequenceDsm(DSMU); // Creates the workflows for the reversed models WorkflowComponent[] processedComponents = CreateReversedModels(IMi, IMf, components, data, clusters, name); // Creates the workflows for the SCCs (default order) List <WorkflowComponent> clusteredComponents = CreateSCCs(processedComponents, clusters, data, name); // Applies the order (vDsmArr) to the models List <WorkflowComponent> scheduledComponents = Schedule(clusteredComponents, order); // Enables dependency analysis var dependencyAnalysis = new MatrixBasedDependencyAnalysis(processedComponents); return(new Workflow(name, description, inputs, outputs, components, scheduledComponents) { DependencyAnalysis = dependencyAnalysis }); }
/// <summary> /// This function reads through the dsm vDsmt identifies the identical rows (these are sccs ) and pass back this information(in an object array format) to the calling function /// </summary> /// <param name="DSM"></param> /// <returns></returns> private static List <Cluster> GatherClusters(DesignStructureMatrix DSM) { //gathers the clusters var clusterPresent = new List <int>(); var clusters = new List <Cluster>(DSM.RowCount); for (int c = 0; c < DSM.ColumnCount; c++) { var clusterlist = new Cluster(); if (!clusterPresent.Contains(c)) { clusterPresent.Add(c); clusterlist.Add(c); for (int r = 0; r < DSM.RowCount; r++) { if (c == r) { continue; } if (DSM.Row(c).Equals(DSM.Row(r))) { clusterlist.Add(r); clusterPresent.Add(r); } } clusters.Add(clusterlist); clusterlist = null; } } return(clusters); }
public static void CopyDefaultInputs(this DesignStructureMatrix IM, DesignStructureMatrix IMf, Cluster models) { for (int r = 0; r < IMf.RowCount; r++) { if (models.Contains(r)) { IM.SetRow(r, IMf.Row(r)); } } }
/// <summary> /// Identifies SCC in DSM (read chapter 3.2.2 in reference [2]), this information is passed back in the object array vClus. /// </summary> /// <param name="DSM"></param> /// <returns></returns> private static List <Cluster> Decompose(DesignStructureMatrix DSM) { DesignStructureMatrix DSMt = DesignStructureMatrix.Build.Dense(DSM.ColumnCount, DSM.ColumnCount); DesignStructureMatrix DSMmul = DesignStructureMatrix.Build.DenseIdentity(DSM.ColumnCount, DSM.ColumnCount); for (int c = 0; c < DSM.ColumnCount; c++) { DSMmul = DSM * DSMmul; DSMmul.ReplaceGreaterthanWith(1, 1); DSMt = DSMt + DSMmul; } DSMt = DSMt.PointwiseMultiply(DSMt.Transpose()); DSMt.ReplaceGreaterthanWith(1, 1); return(GatherClusters(DSMt)); }
/// <summary> /// Converts an incidence matrix to design structure matrix. /// </summary> /// <param name="IM"></param> /// <returns></returns> public static DesignStructureMatrix IncidenceMatrixToDesignStructureMatrix(IncidenceMatrix IM) { DesignStructureMatrix DSM = IncidenceMatrix.Build.DenseIdentity(IM.RowCount, IM.RowCount); List <(int i, int j)> locRowCol = IM.FindLocations(LibishScheduler.OUT); foreach ((int row, int col) in locRowCol) { List <int> inputLocaltions = IM.Column(col).FindLocations(LibishScheduler.IN); if (inputLocaltions != null) { foreach (int i in inputLocaltions) { DSM[row, i] = LibishScheduler.ANY; } } } return(DSM); }
/// <summary> /// Identifies the sequence for the Dsm for which its contents become all feed forward. /// The method is described in detail in reference [2] chapter 3.2.3.2. /// </summary> /// <param name="DSM"></param> /// <returns></returns> private static List <int> SequenceDsm(DesignStructureMatrix DSM) { int[] sequencedDSM = new int[DSM.ColumnCount]; DesignStructureMatrix E0 = DesignStructureMatrix.Build.Dense(DSM.ColumnCount, 1, 1); int nLoc = 0; while (nLoc < DSM.ColumnCount) { DesignStructureMatrix PE0 = DSM * E0; List <int> locations = PE0.Column(0).FindLocations(1); for (int l = 0; l < locations.Count; l++) { sequencedDSM[nLoc] = locations[l]; nLoc++; } E0 = PE0; E0.ReplaceLessthanWith(2, 0); E0.ReplaceGreaterthanWith(1, 1); } return(sequencedDSM.ToList()); }
/// <summary> /// This funnction returns all possible workflows in an incidence matrix format, given the foundation matrix /// as well as the vIndep vector which represent the independent variables. /// This function is the top level function which performs the incidence matrix method. /// </summary> /// <param name="IMf"></param> /// <param name="independent"></param> /// <returns></returns> private static IncidenceMatrix[] AllWorkflows(IncidenceMatrix IMf, int[] independent) { IncidenceMatrix IMi = IncidenceMatrix.Build.DenseOfMatrix(IMf); // Number of outputs per row (affect model r) IMi.ReplaceAlltoOne(); // valrf & valcf in [1] double[] Noutvalr = new double[IMf.RowCount]; for (int model = 0; model < IMf.RowCount; model++) { int NOutputs = IMf.NOutputs(model); int NVariables = IMi.NVariables(model); // Number of variables affecting model r int NInputs = (NVariables - NOutputs); Noutvalr[model] = ValRow(NOutputs, NInputs); } double[] Noutvalc = new double[IMf.ColumnCount]; for (int c = 0; c < IMf.ColumnCount; c++) { int NModels = IMi.Column(c).FindValue(ANY); // Number of models related to variable c int NInputs = (NModels - 1); Noutvalc[c] = ValColumn(NInputs); } // Assign user defined inputs/outputs for (int variable = 0; variable < IMi.ColumnCount; variable++) { if (independent[variable] == MARKED_IN) { IMi.SetInput(variable); // Asign variable as input in IMi } else if (independent[variable] == MARKED_OUT) { IMi.SetOutput(variable, IMf); } } List <int> notAssigned = FindNotAssignedModels(IMi, IMf); if (notAssigned.Count == 0) { return(new IncidenceMatrix[1] { IMf }); } IncidenceMatrixFirstStep(IMi, Noutvalr, Noutvalc, true); FillAsInput(IMi, Noutvalr, Noutvalc); IncidenceMatrixFirstStep(IMi, Noutvalr, Noutvalc, true); //////////////////////// List <int> reversed = FindReversedModels(IMi, IMf); bool reversedModelsInSCC = false; List <int> modelsInScc = ModelsInSCCFromIMM(IMi); foreach (int model in modelsInScc) { if (FindValueInArray(reversed, model)) // if ith model is in SCC and reversed then break { reversedModelsInSCC = true; break; } } if (!reversedModelsInSCC) //i.e. no models in SCC are modified/reversed { if (IMi.FindLocations(ANY).Count != 0) { // copy default SCC inputs and outputs to new incidence matrix, imMatrixi IMi.CopyDefaultInputs(IMf, modelsInScc); } return(new IncidenceMatrix[1] { IMi }); } else { // When clicking 'edit' then get incidence before it has been modified or if creating new object, then get default incidence DesignStructureMatrix DSM = IMMtoDSM(IMf); modelsInScc.Clear(); List <Cluster> clusters = Decompose(DSM); foreach (Cluster cluster in clusters) { if (cluster.Count > 1) { modelsInScc.AddRange(cluster); } } reversedModelsInSCC = false; foreach (int model in modelsInScc) { // foreach model in SCC is any model... if (FindValueInArray(reversed, model)) // if ith model is in SCC and reversed then break { reversedModelsInSCC = true; break; } } if (!reversedModelsInSCC) //i.e. copy existing SCC configurations { IMi.CopyDefaultInputs(IMf, modelsInScc); } } //////////////////// if (IMi.FindLocations(ANY).Count > 0) { return(IncidenceExplore(IMi, IMf, Noutvalr, Noutvalc)); //incmset=uniqueincmset(incmset);Unque object has to be added here.... } else { return(new IncidenceMatrix[1] { IMi }); } throw new ArgumentException(NoIMsFoundErrorMessage); }