/// <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); }
private static List <int> ModelsInSCCFromIMM(IncidenceMatrix IM) { var modelsInSCC = new List <int>(); for (int r = 0; r < IM.RowCount; r++) { if (FindValueInArray(IM.Row(r).ToArray(), ANY)) { modelsInSCC.Add(r); } } return(modelsInSCC); }
/// <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)); }
/// <summary> /// This function identifies the Modified models (from imMatrixi and imMatrif) in the modelObjects, then creates a 'modified model subprocess' for each modified model, /// and therafter combines it with other models in the modelObjects and return it in a object array /// </summary> /// <param name="IMi"></param> /// <param name="IMf"></param> /// <param name="components"></param> /// <param name="data"></param> /// <param name="clusters"></param> /// <param name="name"></param> /// <returns></returns> private static WorkflowComponent[] CreateReversedModels(IncidenceMatrix IMi, IncidenceMatrix IMf, List <WorkflowComponent> components, List <Data> data, List <Cluster> clusters, string name) { var processedComponents = new WorkflowComponent[IMf.RowCount]; for (int r = 0; r < IMi.RowCount; r++) { WorkflowComponent component = components[r]; Vector <double> row = IMi.Row(r); if (!IMf.Row(r).CompareAssigned(row)) { List <int> inputIndices = row.FindLocations(IN); List <int> outputIndices = row.FindLocations(OUT); var inputs = inputIndices.Select(i => data[i]).ToList(); var outputs = outputIndices.Select(i => data[i]).ToList(); if (component is Model model) { processedComponents[r] = model.Reverse(inputs, outputs); } else if (component is Workflow workflow) { var opts = new NewtonOptions() { MaxIterations = 20, DerivativeStep = new double[] { 0.01 } }; var solver = new NewtonSolver(opts); processedComponents[r] = new WorkflowGlobal($"{name}#GlobalWorkflow#{workflow.Name}", "", inputs, outputs, workflow.Components, workflow.Components, new List <ISolver>() { solver }); } } else { processedComponents[r] = components[r]; } } return(processedComponents); }
/// <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; } } }
public static bool IsModelUnassigned(this IncidenceMatrix IM, int model) => IM.Row(model).FindValue(ANY) > 0;
public static int NOutputs(this IncidenceMatrix IM, int model) => IM.Row(model).FindValue(OUT);
public static int NInputs(this IncidenceMatrix IM, int model) => IM.Row(model).FindValue(IN);
public static int NVariables(this IncidenceMatrix IM, int model) => IM.Row(model).FindValue(ANY);
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); }