public static void PrintReordered(this ISparsePivotingSolver <double> solver) { solver.Precondition((matrix, rhs) => { var text = new string[solver.Size][]; var widths = new int[solver.Size + 1]; for (var i = 0; i < solver.Size; i++) { text[i] = new string[solver.Size + 1]; Element <double> elt; for (var j = 0; j < solver.Size; j++) { elt = matrix.FindElement(new MatrixLocation(i + 1, j + 1)); text[i][j] = elt == null ? "." : $"{elt.Value:G3}"; widths[j] = Math.Max(widths[j], text[i][j].Length); } elt = rhs.FindElement(i + 1); text[i][solver.Size] = elt == null ? "." : $"{elt.Value:G3}"; widths[solver.Size] = Math.Max(widths[solver.Size], text[i][solver.Size].Length); } // Write the string for (var i = 0; i < solver.Size; i++) { for (var j = 0; j < solver.Size; j++) { Console.Write(new string(' ', widths[j] - text[i][j].Length)); Console.Write(text[i][j]); Console.Write(" "); } Console.Write("| "); Console.WriteLine(text[i][solver.Size]); } }); }
/// <summary> /// Initializes a new instance of the <see cref="LocalSolverState{T,S}"/> class. /// </summary> /// <param name="name">The name of the subcircuit instance.</param> /// <param name="parent">The parent simulation state.</param> /// <param name="solver">The local solver.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="name"/>, <paramref name="parent"/> or <paramref name="solver"/> is <c>null</c>.</exception> protected LocalSolverState(string name, S parent, ISparsePivotingSolver <T> solver) : base(name, parent) { Solver = solver.ThrowIfNull(nameof(solver)); // We will keep our own map! We will use the parent's variable set though, to make sure our parent can find back // our solved variables. _map = new VariableMap(parent.Map[0]); }
/// <summary> /// Initializes a new instance of the <see cref="ComplexSimulationState"/> class. /// </summary> /// <param name="solver">The solver.</param> /// <param name="comparer">The comparer.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="solver"/> is <c>null</c>.</exception> public ComplexSimulationState(ISparsePivotingSolver <Complex> solver, IEqualityComparer <string> comparer) : base(comparer) { Solver = solver.ThrowIfNull(nameof(solver)); var gnd = new SolverVariable <Complex>(this, Constants.Ground, 0, Units.Volt); _map = new VariableMap(gnd); Add(Constants.Ground, gnd); }
/// <summary> /// Assert internal element /// </summary> /// <param name="solver"></param> /// <param name="row"></param> /// <param name="col"></param> /// <param name="expected"></param> void AssertInternal(ISparsePivotingSolver <double> solver, int row, int col, double expected) { var indices = new MatrixLocation(row, col); indices = solver.InternalToExternal(indices); var elt = solver.FindElement(indices); Assert.AreNotEqual(null, elt); Assert.AreEqual(expected, elt.Value); }
/// <summary> /// Build a new solver from scratch using the current constraints and variables. /// </summary> /// <returns>The solver.</returns> private void BuildSolver() { _solver = new SparseRealSolver(); _map.Clear(); // Build our total function bool hasResolved = true; var diffs = new Dictionary <Unknown, Function>(); while (hasResolved) { hasResolved = false; _lambdas.Clear(); var f = Minimize ?? 1.0; int index = 1; foreach (var c in _constraints.Keys) { if (c.IsFixed) { if (!c.Value.IsZero()) { Warn(this, new WarningEventArgs($"Could not {_constraints[c]}.")); } continue; } var lambda = new Unknown($"lambda{index++}", UnknownTypes.Scalar); f += lambda * c; _lambdas.Add(lambda); } // Differentiate the Lagrangian function if (LogInfo) { Console.WriteLine(f); } diffs.Clear(); f.Differentiate(null, diffs); // Handle unknowns that need to be minimized foreach (var m in _minimum) { if (m.Key.IsFixed) { if (m.Key.Value < m.Value) { Warn(this, new WarningEventArgs($"Minimum was violated for {m.Key}.")); } continue; } if (diffs.TryGetValue(m.Key, out var eq)) { diffs[m.Key] = eq - 0.01 / (m.Key - m.Value); } } // First try to precompute as many constraints as possible var done = new HashSet <Unknown>(); do { done.Clear(); foreach (var pair in diffs) { var c = pair.Value; // Skip the ones we already resolved if (c.Resolve(0.0)) { hasResolved = true; if (LogInfo) { Console.WriteLine($"Resolved {c}"); } // This has been fixed! done.Add(pair.Key); } else if (c.IsFixed && !c.Value.IsZero()) { if (_constraints.TryGetValue(c, out var description)) { Warn(this, new WarningEventArgs($"Could not {description}.")); } else { Warn(this, new WarningEventArgs($"Could not {c}.")); } // This has been fixed! done.Add(pair.Key); } } foreach (var key in done) { diffs.Remove(key); } }while (done.Count > 0); } // Setup the equations and solution _solution = new DenseVector <double>(_equations.Count); _oldSolution = new DenseVector <double>(_equations.Count); foreach (var eq in diffs) { var index = _map.Map(eq.Key); var rowEquation = eq.Value.CreateEquation(index, _map, _solver); _equations.Add(eq.Key, rowEquation); switch (eq.Key.Type) { case UnknownTypes.Scale: if (eq.Key.Value.IsZero()) { _solution[index] = 1.0; } else { _solution[index] = eq.Key.Value; } break; case UnknownTypes.Length: if (eq.Key.Value < 0) { _solution[index] = 0; } else { _solution[index] = eq.Key.Value; } break; case UnknownTypes.X: case UnknownTypes.Y: _solution[index] = Fix; break; default: _solution[index] = eq.Key.Value; break; } _oldSolution[index] = _solution[index]; if (LogInfo) { Console.WriteLine($"df/d{eq.Key} = {eq.Value}"); } } foreach (var m in _minimum) { var initial = m.Key.Value; if (m.Key.Value <= m.Value) { initial = m.Value + 1e-9; } if (_map.TryGet(m.Key, out var index)) { _solution[index] = initial; _oldSolution[index] = _solution[index]; } } }
/// <summary> /// Initializes a new instance of the <see cref="LocalSimulationState"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="parent">The parent.</param> /// <param name="solver">The solver.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="name"/>, <paramref name="parent"/> or <paramref name="solver"/> is <c>null</c>.</exception> public LocalSimulationState(string name, IComplexSimulationState parent, ISparsePivotingSolver <Complex> solver) : base(name, parent, solver) { }
/// <summary> /// Initializes a new instance of the <see cref="LocalSimulationState"/> class. /// </summary> /// <param name="name">The name of the subcircuit instance.</param> /// <param name="parent">The parent simulation state.</param> /// <param name="solver">The solver.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="name"/>, <paramref name="parent"/> or <paramref name="solver"/> is <c>null</c>.</exception> public LocalSimulationState(string name, IBiasingSimulationState parent, ISparsePivotingSolver <double> solver) : base(name, parent, solver) { }