protected void RunScenario(string title, string input) { RunScenario(title, () => { var lines = input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var map = lines.SelectMany((i, y) => i.Select((ii, x) => new { x, y, v = ii })) .ToDictionary(i => (i.x, i.y), i => i.v); void Dump() { var nmx = map.Keys.Min(i => i.Item1); var nmy = map.Keys.Min(i => i.Item2); var mx = map.Keys.Max(i => i.Item1); var my = map.Keys.Max(i => i.Item2); for (var y = nmx; y <= my; y++) { for (var x = nmy; x <= mx; x++) { var value = (map.TryGetValue((x, y), out var v) ? v : ' '); Console.Write(value); } Console.WriteLine(); } Console.WriteLine(); } //Dump(); var startP = map.Single(i => i.Value == '@').Key; var start = new MapNode(startP.x, startP.y, 0, map, new HashSet <char>(), map.Values.Count(i => char.IsLower(i))); var solution = new RealSolver().Evaluate <MapNode, (int, int, string), int>(start); Console.WriteLine(solution.CurrentCost); });
public void When_OrderAndFactoring2_Expect_Reference() { var solver = new RealSolver(5); solver.GetMatrixElement(1, 1).Value = 1.0; solver.GetMatrixElement(2, 1).Value = 0.0; solver.GetMatrixElement(2, 2).Value = 1.0; solver.GetMatrixElement(2, 5).Value = 0.0; solver.GetMatrixElement(3, 3).Value = 1.0; solver.GetMatrixElement(3, 4).Value = 1e-4; solver.GetMatrixElement(3, 5).Value = -1e-4; solver.GetMatrixElement(4, 4).Value = 1.0; solver.GetMatrixElement(5, 1).Value = 5.38e-23; solver.GetMatrixElement(5, 4).Value = -1e-4; solver.GetMatrixElement(5, 5).Value = 1e-4; solver.OrderAndFactor(); AssertInternal(solver, 1, 1, 1.0); AssertInternal(solver, 2, 1, 0.0); AssertInternal(solver, 2, 2, 1.0); AssertInternal(solver, 2, 5, 0.0); AssertInternal(solver, 3, 3, 1.0); AssertInternal(solver, 3, 4, 1e-4); AssertInternal(solver, 3, 5, -1e-4); AssertInternal(solver, 4, 4, 1.0); AssertInternal(solver, 5, 1, 5.38e-23); AssertInternal(solver, 5, 4, -1e-4); AssertInternal(solver, 5, 5, 10000); }
protected void RunScenario(string title, string input) { RunScenario(title, () => { var lines = input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var parsed = lines.Select(i => i.Split(' ')).ToList(); var cities = parsed.SelectMany(i => new[] { i[0], i[2] }).Distinct().ToList(); var edges = new Dictionary <string, Dictionary <string, int> >(); void Add(string city1, string city2, int distance) { if (!edges.ContainsKey(city1)) { edges.Add(city1, new Dictionary <string, int>()); } edges[city1][city2] = distance; } foreach (var p in parsed) { Add(p[0], p[2], int.Parse(p[4])); Add(p[2], p[0], int.Parse(p[4])); } var root = new GraphNode(null, new HashSet <string>(), cities, edges, 0); var solution = new RealSolver().Evaluate <GraphNode, string, int>(root); Console.WriteLine(solution.Description); }); }
public void When_OrderAndFactoring_Expect_Reference() { var solver = new RealSolver(); solver.GetMatrixElement(1, 1).Value = 0.0001; solver.GetMatrixElement(1, 4).Value = -0.0001; solver.GetMatrixElement(1, 5).Value = 0.0; solver.GetMatrixElement(2, 1).Value = 0.0; solver.GetMatrixElement(2, 2).Value = 1.0; solver.GetMatrixElement(2, 5).Value = 0.0; solver.GetMatrixElement(3, 1).Value = -0.0001; solver.GetMatrixElement(3, 3).Value = 1.0; solver.GetMatrixElement(3, 4).Value = 0.0001; solver.GetMatrixElement(4, 4).Value = 1.0; solver.GetMatrixElement(5, 5).Value = 1.0; // Order and factor solver.OrderAndFactor(); // Compare Assert.AreEqual(solver.GetMatrixElement(1, 1).Value, 1.0e4); Assert.AreEqual(solver.GetMatrixElement(1, 4).Value, -0.0001); Assert.AreEqual(solver.GetMatrixElement(1, 5).Value, 0.0); Assert.AreEqual(solver.GetMatrixElement(2, 1).Value, 0.0); Assert.AreEqual(solver.GetMatrixElement(2, 2).Value, 1.0); Assert.AreEqual(solver.GetMatrixElement(2, 5).Value, 0.0); Assert.AreEqual(solver.GetMatrixElement(3, 1).Value, -0.0001); Assert.AreEqual(solver.GetMatrixElement(3, 3).Value, 1.0); Assert.AreEqual(solver.GetMatrixElement(3, 4).Value, 0.0001); Assert.AreEqual(solver.GetMatrixElement(4, 4).Value, 1.0); Assert.AreEqual(solver.GetMatrixElement(5, 5).Value, 1.0); }
public void When_Preorder_Expect_Reference() { var solver = new RealSolver(5); solver.GetMatrixElement(1, 1).Value = 1e-4; solver.GetMatrixElement(1, 2).Value = 0.0; solver.GetMatrixElement(1, 3).Value = -1e-4; solver.GetMatrixElement(2, 1).Value = 0.0; solver.GetMatrixElement(2, 2).Value = 0.0; solver.GetMatrixElement(2, 5).Value = 1.0; solver.GetMatrixElement(3, 1).Value = -1e-4; solver.GetMatrixElement(3, 3).Value = 1e-4; solver.GetMatrixElement(3, 4).Value = 1.0; solver.GetMatrixElement(4, 3).Value = 1.0; solver.GetMatrixElement(5, 2).Value = 1.0; SpiceSharp.Simulations.ModifiedNodalAnalysisHelper.PreorderModifiedNodalAnalysis(solver, Math.Abs); AssertInternal(solver, 1, 1, 1e-4); AssertInternal(solver, 1, 4, -1e-4); AssertInternal(solver, 1, 5, 0.0); AssertInternal(solver, 2, 1, 0.0); AssertInternal(solver, 2, 2, 1.0); AssertInternal(solver, 2, 5, 0.0); AssertInternal(solver, 3, 1, -1e-4); AssertInternal(solver, 3, 3, 1.0); AssertInternal(solver, 3, 4, 1e-4); AssertInternal(solver, 4, 4, 1.0); AssertInternal(solver, 5, 5, 1.0); }
protected void RunScenario(string title, string input) { RunScenario(title, () => { var lines = input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var reactions = lines.Select(i => { var parts = i .Split(new[] { '=', '>' }, StringSplitOptions.RemoveEmptyEntries) .Select(ii => ii.Trim()) .Select(ii => ii.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(iii => iii.Split(' ', StringSplitOptions.RemoveEmptyEntries)) //.Select(iii => { Console.WriteLine(iii[0]); Console.WriteLine(iii[1]); return iii; }) .ToDictionary(iii => iii[1], iii => long.Parse(iii[0])) ) .ToList(); return(parts[0], parts[1]); }).ToList(); if (reactions.Any(ii => ii.Item2.Count != 1)) { throw new NotImplementedException(); } var start = new ChemNode(new Dictionary <string, long>(), reactions, new Estimator(reactions), new Dictionary <string, long>()); var solution = new RealSolver().Evaluate <ChemNode, string, long>(start); Console.WriteLine($"{solution.Description} - {solution.Ore}"); });
/// <summary> /// Find a voltage driver that closes a voltage drive loop. /// </summary> /// <returns> /// The component that closes the loop. /// </returns> private Component FindVoltageDriveLoop() { // Remove the ground node and make a map for reducing the matrix complexity var index = 1; var map = new Dictionary <int, int> { { 0, 0 } }; foreach (var vd in _voltageDriven) { if (vd.Node1 != 0) { if (!map.ContainsKey(vd.Node1)) { map.Add(vd.Node1, index++); } } if (vd.Node2 != 0) { if (!map.ContainsKey(vd.Node2)) { map.Add(vd.Node2, index++); } } } // Determine the rank of the matrix var solver = new RealSolver(Math.Max(_voltageDriven.Count, map.Count)); for (var i = 0; i < _voltageDriven.Count; i++) { var pins = _voltageDriven[i]; solver.GetMatrixElement(i + 1, map[pins.Node1]).Value += 1.0; solver.GetMatrixElement(i + 1, map[pins.Node2]).Value += 1.0; } try { // Try refactoring the matrix solver.OrderAndFactor(); } catch (SingularException exception) { /* * If the rank of the matrix is lower than the number of driven nodes, then * the matrix is not solvable for those nodes. This means that there are * voltage sources driving nodes in such a way that they cannot be solved. */ if (exception.Index <= _voltageDriven.Count) { var indices = new LinearSystemIndices(exception.Index); solver.InternalToExternal(indices); return(_voltageDriven[indices.Row - 1].Source); } } return(null); }
/// <summary> /// Read a .MTX file /// </summary> /// <param name="filename">Filename</param> /// <returns></returns> protected Solver <double> ReadMtxFile(string filename) { Solver <double> result; using (StreamReader sr = new StreamReader(filename)) { // The first line is a comment sr.ReadLine(); // The second line tells us the dimensions string line = sr.ReadLine() ?? throw new Exception("Invalid Mtx file"); var match = Regex.Match(line, @"^(?<rows>\d+)\s+(?<columns>\d+)\s+(\d+)"); int size = int.Parse(match.Groups["rows"].Value); if (int.Parse(match.Groups["columns"].Value) != size) { throw new Exception("Matrix is not square"); } result = new RealSolver(size); // All subsequent lines are of the format [row] [column] [value] while (!sr.EndOfStream) { // Read the next line line = sr.ReadLine(); if (line == null) { break; } match = Regex.Match(line, @"^(?<row>\d+)\s+(?<column>\d+)\s+(?<value>.*)\s*$"); if (!match.Success) { throw new Exception("Could not recognize file"); } int row = int.Parse(match.Groups["row"].Value); int column = int.Parse(match.Groups["column"].Value); double value = double.Parse(match.Groups["value"].Value, System.Globalization.CultureInfo.InvariantCulture); // Set the value in the matrix result.GetMatrixElement(row, column).Value = value; } } return(result); }
/// <summary> /// Reads a matrix file generated by Spice 3f5. /// </summary> /// <param name="matFilename">The matrix filename.</param> /// <param name="vecFilename">The vector filename.</param> /// <returns></returns> protected Solver <double> ReadSpice3f5File(string matFilename, string vecFilename) { var solver = new RealSolver(); // Read the spice file string line; using (var reader = new StreamReader(matFilename)) { // The file is organized using (row) (column) (value) (imag value) while (!reader.EndOfStream && (line = reader.ReadLine()) != null) { if (line == "first") { continue; } var match = Regex.Match(line, @"^(?<size>\d+)\s+(complex|real)$"); // Try to read an element match = Regex.Match(line, @"^(?<row>\d+)\s+(?<col>\d+)\s+(?<value>[^\s]+)(\s+[^\s]+)?$"); if (match.Success) { int row = int.Parse(match.Groups["row"].Value); int col = int.Parse(match.Groups["col"].Value); var value = double.Parse(match.Groups["value"].Value, CultureInfo.InvariantCulture); solver.GetMatrixElement(row, col).Value = value; } } } // Read the vector file using (var reader = new StreamReader(vecFilename)) { var index = 1; while (!reader.EndOfStream && (line = reader.ReadLine()) != null) { var value = double.Parse(line, CultureInfo.InvariantCulture); solver.GetRhsElement(index).Value = value; index++; } } return(solver); }
public void When_Factoring_Expect_Reference() { double[][] matrixElements = { new[] { 1.0, 1.0, 1.0 }, new[] { 2.0, 3.0, 5.0 }, new[] { 4.0, 6.0, 8.0 } }; double[][] expected = { new[] { 1.0, 1.0, 1.0 }, new[] { 2.0, 1.0, 3.0 }, new[] { 4.0, 2.0, -0.5 } }; // Create matrix var solver = new RealSolver(); for (var r = 0; r < matrixElements.Length; r++) { for (var c = 0; c < matrixElements[r].Length; c++) { solver.GetMatrixElement(r + 1, c + 1).Value = matrixElements[r][c]; } } // Factor solver.Factor(); // compare for (var r = 0; r < matrixElements.Length; r++) { for (var c = 0; c < matrixElements[r].Length; c++) { Assert.AreEqual(expected[r][c], solver.GetMatrixElement(r + 1, c + 1).Value, 1e-12); } } }
public void When_QuickDiagonalPivoting_Expect_NoException() { // Build the solver with only the quick diagonal pivoting var solver = new RealSolver(); var strategy = (Markowitz <double>)solver.Strategy; strategy.Strategies.Clear(); strategy.Strategies.Add(new MarkowitzQuickDiagonal <double>()); // Build the matrix that should be solvable using only the singleton pivoting strategy double[][] matrix = { new[] { 1, 0.5, 0, 0 }, new[] { -0.5, 5, 4, 0 }, new[] { 0, 3, 2, 0.1 }, new[] { 0, 0, -0.01, 3 } }; double[] rhs = { 0, 0, 0, 0 }; for (var r = 0; r < matrix.Length; r++) { for (var c = 0; c < matrix[r].Length; c++) { if (!matrix[r][c].Equals(0.0)) { solver.GetMatrixElement(r + 1, c + 1).Value = matrix[r][c]; } } if (!rhs[r].Equals(0.0)) { solver.GetRhsElement(r + 1).Value = rhs[r]; } } // This should run without throwing an exception solver.OrderAndFactor(); }
protected void RunScenario(string title, string input) { RunScenario(title, () => { var tiles = input.Replace("\r\n", "\n").Split("\n\n"); var tileData = new Dictionary <int, char[][]>(); foreach (var tile in tiles) { var lines = tile.Split("\n"); var tileId = int.Parse(lines[0].Substring(5, 4)); var data = lines.Skip(1).Select(i => i.ToArray()).ToArray(); tileData.Add(tileId, data); } var patterns = tileData.ToDictionary(i => i.Key, i => GenerateEdgePatterns(i.Value)); var corners = new List <int>(); var partners = new Dictionary <int, int[]>(); foreach (var tile1 in tileData.Keys) { //foreach (var dir1 in Enumerable.Range(0, 16)) { var p1 = patterns[tile1][0]; var matches = new List <int>(); foreach (var tile2 in tileData.Keys) { if (tile1 == tile2) { continue; } foreach (var dir2 in Enumerable.Range(0, 16)) { var p2 = patterns[tile2][dir2]; if (p1[0] == p2[2] || p1[1] == p2[3] || p1[2] == p2[0] || p1[3] == p2[1]) { matches.Add(tile2); break; } } } if (matches.Count <= 2) { Console.WriteLine( $"{tile1} only has {matches.Count} partners: {string.Join(",", matches)}"); corners.Add(tile1); } else { Console.WriteLine($" {tile1} has {matches.Count} partners"); } partners[tile1] = matches.ToArray(); } } //return; var h = (int)Math.Sqrt(tileData.Count); var w = h; var solution = new RealSolver().Evaluate <MapNode, string, int>(new MapNode(corners.ToArray(), partners, patterns, (short)h, new List <(int, short)>())); Console.WriteLine($"Solution: {solution}"); var placed = solution._placed; var parts = new[] { placed[0], placed[w - 1], placed[(h - 1) * w - 1], placed[h * w - 1], }.Select(i => (long)i.Item1).ToList(); for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { Console.Write(placed[y * w + x].Item1); Console.Write(" "); } Console.WriteLine(); } Console.WriteLine(); parts.ForEach(i => Console.WriteLine(i)); Console.WriteLine(parts.Aggregate(1L, (a, b) => a * b)); var tileSize = tileData.First().Value.Length; var map = Enumerable.Range(0, (tileSize - 2) * w).Select(y => Enumerable.Range(0, (tileSize - 2) * w).Select(x => ' ').ToArray()).ToArray(); for (var i = 0; i < placed.Count; i++) { var sx = (i % w) * (tileSize - 2) - 1; var sy = (i / w) * (tileSize - 2) - 1; var tile = placed[i]; //var originalImage = GetMapImage(tileData[tile.Item1], 0); var tileMapImage = GetMapImage(tileData[tile.Item1], tile.Item2); //Write($"Original {tile.Item1}", originalImage); //Write($"Rotated {tile.Item1} to {tile.Item2}", tileMapImage); for (var y = 1; y < tileSize - 1; y++) { var ty = sy + y; for (var x = 1; x < tileSize - 1; x++) { var tx = sx + x; //var tmap = map[ty][tx]; var smap = tileMapImage[y][x]; //if (tmap != ' ' && tmap != smap) //{ // Console.WriteLine($"Mismatch - '{tmap}' != '{smap}' @ {i} -> {x},{y} / {tx},{ty}"); // map[ty][tx] = 'X'; //} //else //{ map[ty][tx] = smap; //} } } } Write("map", map); //map = RemoveBorder(map); //Write("border free map", map); var count = FindMaxMonsters(map); //var map12 = GetMapImage(map, 7); //Write("map12", map12); //var count = FindMonsters(map12); // 9 // 144 // 0 = current // 1 = rotate 90 counterclockwise // 2 = rotate 180 // 3 = rotate 270 // 4 = h flip // 8 = v flip // 16 orientations total // need to store top/bottom/left/right pattern for each // tiles are 10x10 Console.WriteLine(count); });
protected void RunScenario(string title, string input) { RunScenario(title, () => { var tiles = input.Replace("\r\n", "\n").Split("\n\n"); var tileData = new Dictionary <int, char[][]>(); foreach (var tile in tiles) { var lines = tile.Split("\n"); var tileId = int.Parse(lines[0].Substring(5, 4)); var data = lines.Skip(1).Select(i => i.ToArray()).ToArray(); tileData.Add(tileId, data); } var patterns = tileData.ToDictionary(i => i.Key, i => GenerateEdgePatterns(i.Value)); var only2 = new List <int>(); foreach (var tile1 in tileData.Keys) { //foreach (var dir1 in Enumerable.Range(0, 16)) { var p1 = patterns[tile1][0]; var matches = new List <int>(); foreach (var tile2 in tileData.Keys) { if (tile1 == tile2) { continue; } foreach (var dir2 in Enumerable.Range(0, 16)) { var p2 = patterns[tile2][dir2]; if (p1[0] == p2[2] || p1[1] == p2[3] || p1[2] == p2[0] || p1[3] == p2[1]) { matches.Add(tile2); break; } } } if (matches.Count <= 2) { Console.WriteLine( $"{tile1} only has {matches.Count} partners: {string.Join(",", matches)}"); only2.Add(tile1); } else { //Console.WriteLine($" {tile1} has {matches.Count} partners"); } } } Console.WriteLine(only2.Aggregate(1L, (a, b) => a * b)); return; var h = (int)Math.Sqrt(tileData.Count); var w = h; var solution = new RealSolver().Evaluate <MapNode, string, int>(new MapNode(patterns, (short)h, new List <(int, short)>())); Console.WriteLine($"Solution: {solution}"); var placed = solution._placed; var parts = new[] { placed[0], placed[w - 1], placed[(h - 1) * w - 1], placed[h * w - 1], }.Select(i => (long)i.Item1).ToList(); for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { Console.Write(placed[y * w + x].Item1); Console.Write(" "); } Console.WriteLine(); } Console.WriteLine(); parts.ForEach(i => Console.WriteLine(i)); Console.WriteLine(parts.Aggregate(1L, (a, b) => a * b)); // 9 // 144 // 0 = current // 1 = rotate 90 counterclockwise // 2 = rotate 180 // 3 = rotate 270 // 4 = h flip // 8 = v flip // 16 orientations total // need to store top/bottom/left/right pattern for each // tiles are 10x10 Console.WriteLine(tileData.Count); });
protected void RunScenario(string title, string input) { RunScenario(title, () => { var lines = input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var map = lines.SelectMany((i, y) => i.Select((ii, x) => new { x, y, v = ii })) .ToDictionary(i => (i.x, i.y), i => i.v); var importantPoints = map.Where(i => i.Value != '#' && i.Value != '.') .Select(i => i.Key) .ToList(); int?getDistance((int, int)p1, (int, int)p2) { var start = new SimpleMapNode(p1.Item1, p1.Item2, p2, 0, map); var solution = new RealSolver().Evaluate <SimpleMapNode, (int, int), int>(start); return(solution?.CurrentCost); } var edges = importantPoints.ToDictionary(p1 => p1, p1 => { return(importantPoints .Where(p2 => p1 != p2) .Select(p2 => new { p1, p2, d = getDistance(p1, p2) }) .Where(i => i.d.HasValue) .ToDictionary(i => i.p2, i => i.d.Value)); }); void Dump() { var nmx = map.Keys.Min(i => i.Item1); var nmy = map.Keys.Min(i => i.Item2); var mx = map.Keys.Max(i => i.Item1); var my = map.Keys.Max(i => i.Item2); for (var y = nmx; y <= my; y++) { for (var x = nmy; x <= mx; x++) { var value = (map.TryGetValue((x, y), out var v) ? v : ' '); Console.Write(value); } Console.WriteLine(); } Console.WriteLine(); } //Dump(); var worstCostYet = 0; var startP = map.Where(i => i.Value == '@').Select(i => i.Key).ToList(); var startX = startP.Select(i => i.x).ToArray(); var startY = startP.Select(i => i.y).ToArray(); var start = new MapNode(startX, startY, 0, map, new HashSet <char>(), map.Where(i => char.IsLower(i.Value)).ToDictionary(i => i.Value, i => i.Key), edges); var solution = new RealSolver().Evaluate <MapNode, string, int>(new [] { start }, null, (n) => { if (worstCostYet < n.CurrentCost) { worstCostYet = n.CurrentCost; Console.WriteLine($"Evaluating node with cost {n.CurrentCost} -> {n.EstimatedCost} ({n.KeysLeft} keys left)"); } }); //var solution = new ParallelSolver(8).Evaluate(start, start.Key); Console.WriteLine(solution.CurrentCost); });