/// <summary> /// This is the first step of incidence matrix method. This function performs the operation described in chapter3.2.1 in [1] /// </summary> /// <param name="IM"></param> /// <param name="Noutvalr"></param> /// <param name="Noutvalc"></param> /// <param name="Activat"></param> private static void IncidenceMatrixFirstStep(IncidenceMatrix IM, double[] Noutvalr, double[] Noutvalc, bool Activat) { IncidenceMatrix IMstart; do { IMstart = IncidenceMatrix.Build.DenseOfMatrix(IM); var locations = IM.FindLocations(ANY); foreach ((int row, int col) in locations) { double currentValr = IM.Row(row).MultiplyNonZeroVector(); double currentValc = IM.Column(col).MultiplyNonZeroVector(); // Coefficients in equations (1) to (4) in reference [1] double Cvalr = Noutvalr[row] / currentValr; double Cvalc = Noutvalc[col] / currentValc; //checking for rows double R2 = Log(Cvalr) / Log(IN); double R3 = Log(Cvalr) / Log(OUT); double C2 = Log(Cvalc) / Log(IN); double C3 = Log(Cvalc) / Log(OUT); if (IsInteger(R2) && !IsInteger(C3)) // D1 in Fig. 1 { IM[row, col] = IN; } else if (IsInteger(R3) && !IsInteger(C2)) // D2 in Fig. 1 { IM[row, col] = OUT; } else if (IsInteger(C2) && !IsInteger(R3)) // D3 in Fig. 1 { IM[row, col] = IN; } else if (IsInteger(C3) && !IsInteger(R2)) { if (!Activat && (IM.Column(col).FindAnyValue() > 1)) { IM[row, col] = OUT; } else if (Activat) { IM[row, col] = OUT; } } } } while (!IMstart.Equals(IM)); }
public static void SetOutput(this IncidenceMatrix IM, int variable, IncidenceMatrix IMf) { Cluster locs = IMf.Column(variable).FindLocations(OUT); if (locs.Count > 0) { int r = locs.First(); IM[r, variable] = OUT; // Asign variable as output of the firs model that has it as a default output } IM.MultiplyColumn(variable, IN); }
/// <summary> /// creates the new incidence matrix based on the SCCs. SCCs are clustered in the new DSM in a single row. /// </summary> /// <param name="IM"></param> /// <param name="clusters"></param> /// <returns></returns> private static IncidenceMatrix CreateUpMatrix(IncidenceMatrix IM, List <Cluster> clusters) { IncidenceMatrix imMatrixU = IncidenceMatrix.Build.Dense(clusters.Count, IM.ColumnCount); for (int r = 0; r < clusters.Count; r++) { Cluster cluster = clusters[r]; if (cluster.Count == 1) { imMatrixU.SetRow(r, IM.Row(cluster[0])); } else { IncidenceMatrix imMatrixT = IncidenceMatrix.Build.Dense(cluster.Count, IM.ColumnCount); int nvC = 0; foreach (int nRow in cluster) { imMatrixT.SetRow(nvC, IM.Row(nRow)); nvC++; } for (int c = 0; c < IM.ColumnCount; c++) { Vector <double> column = imMatrixT.Column(c); int Nin = column.FindValue(IN); int Nout = column.FindValue(OUT); if (Nin > 0 && Nout > 0) { imMatrixU[r, c] = OUT; } else if (Nout > 0) { imMatrixU[r, c] = OUT; } else if (Nin > 0) { imMatrixU[r, c] = IN; } else { imMatrixU[r, c] = NOTHING; } } } } return(imMatrixU); }
/// <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> /// This function adds additional varaibles as indpendent varaibles. This is done when the system is underdetermined and /// additional variables are required to solve it. /// </summary> /// <param name="IM"></param> /// <param name="Noutvalr"></param> /// <param name="Noutvalc"></param> private static void FillAsInput(IncidenceMatrix IM, double[] Noutvalr, double[] Noutvalc) { List <(int i, int j)> locations = IM.FindLocations(ANY); foreach ((int row, int col) in locations) { //% fills the ANYs with IN if IN has to be put in row and in column //% this make the variable in the column to be an input double currentValr = IM.Row(row).MultiplyNonZeroVector(); double currentValc = IM.Column(col).MultiplyNonZeroVector(); // Coefficients in equations (1) to (4) in reference [1] double Cvalr = Noutvalr[row] / currentValr; double Cvalc = Noutvalc[col] / currentValc; //checking for rows double R2 = Log(Cvalr) / Log(IN); double C3 = Log(Cvalc) / Log(OUT); if (IsInteger(R2) && IsInteger(C3)) // D1 in Fig. 1 { IM[row, col] = IN; } } }
private static List <IncidenceMatrix> IncidenceExploreRecurse(IncidenceMatrix IMi, IncidenceMatrix IMf, double[] Noutvalr, double[] Noutvalc, List <IncidenceMatrix> IMlist, double minNReversed) { var IMset = new List <IncidenceMatrix>(1000); List <int> notAssigned = FindNotAssignedModels(IMi, IMf); List <int> reversed = FindReversedModels(IMi, IMf); if (reversed.Count == 0) { reversed = new HashSet <int>(IMi.FindLocations(ANY).Select(l => l.i)).ToList(); } for (int rev = 0; rev < reversed.Count; rev++) { int r = reversed[rev]; Vector <double> row = IMi.Row(r); List <int> locations = row.FindLocations(ANY); double currentValr = row.MultiplyNonZeroVector(); double Cvalr = Noutvalr[r] / currentValr; for (int l = 0; l < locations.Count; l++) { int c = locations[l]; double currentValc = IMi.Column(c).MultiplyNonZeroVector(); double Cvalc = Noutvalc[c] / currentValc; double R2 = Log(Cvalr) / Log(IN); double C2 = Log(Cvalc) / Log(IN); if (!IsInteger(C2) && !IsInteger(R2)) { IncidenceMatrix IMg = IncidenceMatrix.Build.DenseOfMatrix(IMi); IMg[r, c] = OUT; IncidenceMatrixFirstStep(IMg, Noutvalr, Noutvalc, true); FillAsInput(IMg, Noutvalr, Noutvalc); if (IMg.FindLocations(ANY).Count == 0) { int NRevModels = FindNReversed(IMi, IMg); if (NRevModels < minNReversed) { IMlist.Clear(); IMlist.Add(IMg); minNReversed = NRevModels; } else if (NRevModels == minNReversed) { IMlist.Add(IMg); } else { // do nothing as inspected incidence already has more rev models than those stored. } if (IMlist.Count >= MaxWorkflowAlternatives || explorationWatch.ElapsedMilliseconds > MaxEllapsedTime) { return(IMlist); } } else { IncidenceExplore(IMg, IMf, Noutvalr, Noutvalc); } } } } if (IMlist.Count == 0) { throw new ArgumentException(NoIMsFoundErrorMessage); } return(IMlist); }
/// <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); }