/// <summary> /// Część 1. zadania - zaplanowanie produkcji telewizorów dla pojedynczego kontrahenta. /// </summary> /// <remarks> /// Do przeprowadzenia testów wyznaczających maksymalną produkcję i zysk wymagane jest jedynie zwrócenie obiektu <see cref="PlanData"/>. /// Testy weryfikujące plan wymagają przypisania tablicy z planem do parametru wyjściowego <see cref="weeklyPlan"/>. /// </remarks> /// <param name="production"> /// Tablica obiektów zawierających informacje o produkcji fabryki w kolejnych tygodniach. /// Wartości pola <see cref="PlanData.Quantity"/> oznaczają limit produkcji w danym tygodniu, /// a pola <see cref="PlanData.Value"/> - koszt produkcji jednej sztuki. /// </param> /// <param name="sales"> /// Tablica obiektów zawierających informacje o sprzedaży w kolejnych tygodniach. /// Wartości pola <see cref="PlanData.Quantity"/> oznaczają maksymalną sprzedaż w danym tygodniu, /// a pola <see cref="PlanData.Value"/> - cenę sprzedaży jednej sztuki. /// </param> /// <param name="storageInfo"> /// Obiekt zawierający informacje o magazynie. /// Wartość pola <see cref="PlanData.Quantity"/> oznacza pojemność magazynu, /// a pola <see cref="PlanData.Value"/> - koszt przechowania jednego telewizora w magazynie przez jeden tydzień. /// </param> /// <param name="weeklyPlan"> /// Parametr wyjściowy, przez który powinien zostać zwrócony szczegółowy plan sprzedaży. /// </param> /// <returns> /// Obiekt <see cref="PlanData"/> opisujący wyznaczony plan. /// W polu <see cref="PlanData.Quantity"/> powinna znaleźć się maksymalna liczba wyprodukowanych telewizorów, /// a w polu <see cref="PlanData.Value"/> - wyznaczony maksymalny zysk fabryki. /// </returns> public PlanData CreateSimplePlan(PlanData[] production, PlanData[] sales, PlanData storageInfo, out SimpleWeeklyPlan[] weeklyPlan) { weeklyPlan = null; if (!isOK(production, sales, storageInfo)) { throw new ArgumentException(); } int n = production.Length; weeklyPlan = new SimpleWeeklyPlan[n]; for (int i = 0; i < n; ++i) { weeklyPlan[i].UnitsProduced = 0; weeklyPlan[i].UnitsSold = 0; weeklyPlan[i].UnitsStored = 0; } int k = n + 2; int source = 0; int sink = n + 1; Graph g = new AdjacencyListsGraph <SimpleAdjacencyList>(true, k); Graph r = new AdjacencyListsGraph <SimpleAdjacencyList>(true, k); for (int j = 0; j < n - 1; ++j) { g.AddEdge(new Edge(source, j + 1, production[j].Quantity)); // dodawanie produkcji //produkcja+, sales-, magazynowanie- r.AddEdge(new Edge(source, j + 1, production[j].Value)); g.AddEdge(new Edge(j + 1, sink, sales[j].Quantity)); // dodawanie sprzedazy r.AddEdge(new Edge(j + 1, sink, -sales[j].Value)); g.AddEdge(new Edge(j + 1, j + 2, storageInfo.Quantity)); // dodawanie magazynu r.AddEdge(new Edge(j + 1, j + 2, storageInfo.Value)); } g.AddEdge(source, n, production[n - 1].Quantity); // ostatni tydzien produkcji r.AddEdge(source, n, production[n - 1].Value); g.AddEdge(n, sink, sales[n - 1].Quantity); // ostatni tydzien sprzedazy r.AddEdge(n, sink, -sales[n - 1].Value); (double value, double cost, Graph flow)ret = MinCostFlowGraphExtender.MinCostFlow(g, r, source, sink, false, MaxFlowGraphExtender.PushRelabelMaxFlow, null, false); int produced = 0; for (int i = 0; i < n; ++i) { produced += (int)ret.flow.GetEdgeWeight(source, i + 1); weeklyPlan[i].UnitsProduced = (int)ret.flow.GetEdgeWeight(source, i + 1); weeklyPlan[i].UnitsSold = (int)ret.flow.GetEdgeWeight(i + 1, sink); if (i != n - 1) { weeklyPlan[i].UnitsStored = (int)ret.flow.GetEdgeWeight(i + 1, i + 2); } else { weeklyPlan[i].UnitsStored = 0; } } return(new PlanData { Quantity = produced, Value = -ret.cost }); }
public static Graph webGraph() { int nOfCycles = rnd.Next(2, 15); int ringSize = rnd.Next(3, 1000 / nOfCycles); int verticesCount = nOfCycles * ringSize; Graph web = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); int i, j; for (j = 0; j < nOfCycles; j++) { for (i = 1; i < ringSize; i++) // 0:ringsize-1 denotes first cycle; ringsize:2*ringsize-1 is second cycle { web.AddEdge(new Edge(j * ringSize + i - 1, j * ringSize + i)); } } for (j = 0; j < nOfCycles; j++) // closing cycles { web.AddEdge(new Edge(j * ringSize, (j + 1) * ringSize - 1)); } for (j = 0; j < nOfCycles - 1; j++) // connecting cycles { for (i = 0; i < ringSize; i++) { web.AddEdge(new Edge(j * ringSize + i, (j + 1) * ringSize + i)); } } for (j = 0; j < nOfCycles - 1; j++) // connecting last vertices of cycles { web.AddEdge(new Edge((j + 1) * ringSize - 1, (j + 2) * ringSize - 1)); } return(changeVerticesNumeration(web)); }
/// <summary> /// Część 1. zadania - zaplanowanie produkcji telewizorów dla pojedynczego kontrahenta. /// </summary> /// <remarks> /// Do przeprowadzenia testów wyznaczających maksymalną produkcję i zysk wymagane jest jedynie zwrócenie obiektu <see cref="PlanData"/>. /// Testy weryfikujące plan wymagają przypisania tablicy z planem do parametru wyjściowego <see cref="weeklyPlan"/>. /// </remarks> /// <param name="production"> /// Tablica obiektów zawierających informacje o produkcji fabryki w kolejnych tygodniach. /// Wartości pola <see cref="PlanData.Quantity"/> oznaczają limit produkcji w danym tygodniu, /// a pola <see cref="PlanData.Value"/> - koszt produkcji jednej sztuki. /// </param> /// <param name="sales"> /// Tablica obiektów zawierających informacje o sprzedaży w kolejnych tygodniach. /// Wartości pola <see cref="PlanData.Quantity"/> oznaczają maksymalną sprzedaż w danym tygodniu, /// a pola <see cref="PlanData.Value"/> - cenę sprzedaży jednej sztuki. /// </param> /// <param name="storageInfo"> /// Obiekt zawierający informacje o magazynie. /// Wartość pola <see cref="PlanData.Quantity"/> oznacza pojemność magazynu, /// a pola <see cref="PlanData.Value"/> - koszt przechowania jednego telewizora w magazynie przez jeden tydzień. /// </param> /// <param name="weeklyPlan"> /// Parametr wyjściowy, przez który powinien zostać zwrócony szczegółowy plan sprzedaży. /// </param> /// <returns> /// Obiekt <see cref="PlanData"/> opisujący wyznaczony plan. /// W polu <see cref="PlanData.Quantity"/> powinna znaleźć się maksymalna liczba wyprodukowanych telewizorów, /// a w polu <see cref="PlanData.Value"/> - wyznaczony maksymalny zysk fabryki. /// </returns> public PlanData CreateSimplePlan(PlanData[] production, PlanData[] sales, PlanData storageInfo, out SimpleWeeklyPlan[] weeklyPlan) { int weeks = production.Length; if (weeks == 0 || storageInfo.Quantity < 0 || storageInfo.Value < 0 || weeks != sales.Length) { throw new ArgumentException(); } for (int i = 0; i < weeks; i++) { if (production[i].Quantity < 0 || production[i].Value < 0 || sales[i].Quantity < 0 || sales[i].Value < 0) { throw new ArgumentException(); } } Graph g = new AdjacencyListsGraph <HashTableAdjacencyList>(true, weeks + 2); Graph c = g.IsolatedVerticesGraph(); //n - source //n+1 - target for (int i = 0; i < weeks; i++) { g.AddEdge(weeks, i, production[i].Quantity); c.AddEdge(weeks, i, production[i].Value); g.AddEdge(i, weeks + 1, sales[i].Quantity); c.AddEdge(i, weeks + 1, -sales[i].Value); if (i < weeks - 1) { g.AddEdge(i, i + 1, storageInfo.Quantity); c.AddEdge(i, i + 1, storageInfo.Value); } } (double value, double cost, Graph flow) = g.MinCostFlow(c, weeks, weeks + 1, true, MaxFlowGraphExtender.FordFulkersonDinicMaxFlow, MaxFlowGraphExtender.MKMBlockingFlow); weeklyPlan = new SimpleWeeklyPlan[weeks]; for (int i = 0; i < weeks; i++) { weeklyPlan[i].UnitsProduced = (int)flow.GetEdgeWeight(weeks, i); weeklyPlan[i].UnitsSold = (int)flow.GetEdgeWeight(i, weeks + 1); if (i < weeks - 1) { weeklyPlan[i].UnitsStored = (int)flow.GetEdgeWeight(i, i + 1); } else { weeklyPlan[i].UnitsStored = 0; } } return(new PlanData { Quantity = (int)value, Value = -cost }); }
public static Graph cactus() { int verticesCount = rnd.Next(3, 1000); Graph cactus = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); int i = 0; int connectingNode = 0; while (i < verticesCount - 1) { int polygonsize = 1; if (rnd.Next(2) > 0) { cactus.AddEdge(connectingNode, ++i); } else { polygonsize = rnd.Next(1, 10); polygonsize = Math.Min(polygonsize, verticesCount - i - 1); cactus.AddEdge(connectingNode, ++i); for (int j = 1; j < polygonsize; j++) { cactus.AddEdge(i, ++i); } cactus.AddEdge(i, connectingNode); } if (rnd.Next(2) > 0) // chance for changing connecting node == 0.5 { connectingNode = i - rnd.Next(polygonsize); } } return(changeVerticesNumeration(cactus)); }
private void button1_Click(object sender, EventArgs e) { Random rand = new Random(); int x = 100; int y = 100; IGraph g = new AdjacencyListsGraph(false, x*y); for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { if (rand.Next(0, 3) != 3) g.AddEdge(i, j, rand.Next(1,3)); } } textBox1.Text = ""; Edge[] path; int s = 3, t = 24; g.DelEdge(s, t); Stopwatch sw = new Stopwatch(); sw.Start(); if (g.AStar(s, t, out path)) { foreach (var p in path) textBox1.Text += p.From + ","; textBox1.Text += t; } textBox2.Text = sw.Elapsed.Milliseconds.ToString(); }
public static Graph treeOfPolygons() { int verticesCount = rnd.Next(3, 1000); Graph poligonTree = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); List <Edge> freeEdges = new List <Edge>(); Edge e = new Edge(0, 1); poligonTree.Add(e); freeEdges.Add(e); int i = 1; while (i < verticesCount - 1) { int polygonsize = rnd.Next(3, 7); polygonsize = Math.Min(polygonsize, verticesCount - i - 1); if (polygonsize > 2) { poligonTree.AddEdge(e.To, ++i); freeEdges.Add(new Edge(e.To, i)); for (int j = 0; j < polygonsize - 1; j++) { poligonTree.AddEdge(i, ++i); freeEdges.Add(new Edge(i - 1, i)); } poligonTree.AddEdge(i, e.From); freeEdges.Add(new Edge(i, e.From)); } else { break; } e = freeEdges[rnd.Next(freeEdges.Count)]; freeEdges.Remove(e); } return(changeVerticesNumeration(poligonTree)); }
public static Graph twotree() { int verticesCount = rnd.Next(3, 1000); Graph twotree = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); twotree.AddEdge(new Edge(0, 1)); twotree.AddEdge(new Edge(1, 0)); twotree.AddEdge(new Edge(1, 2)); twotree.AddEdge(new Edge(2, 1)); twotree.AddEdge(new Edge(2, 0)); twotree.AddEdge(new Edge(0, 2)); for (int i = 3; i < verticesCount; i++) { int a = rnd.Next(i); List <Edge> neighbours = twotree.OutEdges(a).ToList(); int b = rnd.Next(neighbours.Count); if (neighbours[b].To == a) { b = neighbours[b].From; } else { b = neighbours[b].To; } twotree.AddEdge(i, a); twotree.AddEdge(i, b); } return(changeVerticesNumeration(twotree)); }
public static Graph necklace() { int k, l, r; // k - size of a bead; l - length of path; r - nb of beads k = rnd.Next(3, 7); l = rnd.Next(2, 7); r = rnd.Next(3, 15); int verticesCount = (k + l) * r; Graph necklace = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); int i = 0; int toPathStart = k / 2 - 1; for (int bead = 0; bead < r; bead++) { for (int j = 0; j < k; j++) { necklace.AddEdge(i, ++i); } necklace.AddEdge(i, i - k); // bead done necklace.AddEdge(i - toPathStart, ++i); if (bead == r - 1) { l--; } for (int j = 0; j < l - 1; j++) { necklace.AddEdge(i, ++i); // path done } } necklace.AddEdge(verticesCount - 1, 0); // for the last bead the last vertice connected with vertice 0 return(changeVerticesNumeration(necklace)); }
/// <summary> /// Sprawdza możliwość przejazdu między dzielnicami-wielokątami district1 i district2, /// tzn. istnieją para ulic, pomiędzy którymi jest przejazd /// oraz fragment jednej ulicy należy do obszaru jednej z dzielnic i fragment drugiej należy do obszaru drugiej dzielnicy /// </summary> /// <returns>Informacja czy istnieje przejazd między dzielnicami</returns> public bool CheckDistricts(Street[] streets, Point[] district1, Point[] district2, out List <int> path, out List <Point> intersections) { AdjacencyListsGraph <SimpleAdjacencyList> g = new AdjacencyListsGraph <SimpleAdjacencyList>(false, streets.Length + 2); path = new List <int>(); intersections = new List <Point>(); int s = streets.Length; int d1 = streets.Length + 1; int d2 = streets.Length; //Construct graph for (int i = 0; i < s; i++) { for (int j = 0; j < district1.Length; j++) { Street temp = new Street(district1[j], district1[(j + 1) % district1.Length]); if (CheckIntersection(temp, streets[i]) == 1) { g.AddEdge(i, d1); } } for (int j = 0; j < district2.Length; j++) { Street temp = new Street(district2[j], district2[(j + 1) % district2.Length]); if (CheckIntersection(temp, streets[i]) == 1) { g.AddEdge(i, d2); } } for (int j = i + 1; j < s; j++) { if (CheckIntersection(streets[i], streets[j]) == 1) { g.AddEdge(i, j); } } } PathsInfo[] d = new PathsInfo[s + 2]; g.DijkstraShortestPaths(d1, out d); if (double.IsNaN(d[d2].Dist)) { return(false); } Edge[] edges = PathsInfo.ConstructPath(d1, d2, d); for (int i = 0; i < edges.Length - 1; i++) { path.Add(edges[i].To); if (i > 0) { intersections.Add(GetIntersectionPoint(streets[edges[i].From], streets[edges[i].To])); } } return(true); }
public static void PrepareTests2() { int n; var rgg = new RandomGraphGenerator(); cliq_test2 = new Graph[3]; izo_test2 = new Graph[2, 2]; cliq_res2 = new int[] { 3, 3, 5 }; izo_res2 = new bool[] { false, true }; if (cliq_test2.Length != cliq_res2.Length || izo_test2.GetLongLength(0) != izo_res2.Length) { throw new ApplicationException("Zle zddefiniowane testy"); } rgg.SetSeed(123); cliq_test2[0] = rgg.UndirectedGraph(typeof(AdjacencyListsGraph <HashTableAdjacencyList>), 4000, 0.001); rgg.SetSeed(125); cliq_test2[1] = rgg.DirectedGraph(typeof(AdjacencyListsGraph <HashTableAdjacencyList>), 3000, 0.05); n = 1500; cliq_test2[2] = new AdjacencyListsGraph <HashTableAdjacencyList>(false, n); for (int i = 0; i < n; ++i) { for (int j = 1; j <= 4; ++j) { cliq_test2[2].AddEdge(i, (i + j) % n); } } n = 50; izo_test2[0, 0] = new AdjacencyMatrixGraph(true, n); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (i != j) { izo_test2[0, 0].AddEdge(i, j); } } } izo_test2[0, 1] = izo_test2[0, 0].Clone(); for (int i = 0; i < n; ++i) { izo_test2[0, 0].DelEdge(i, (i + 1) % n); } for (int i = 0; i < n; ++i) { izo_test2[0, 1].DelEdge(i, (i + 2) % n); } rgg.SetSeed(1234); izo_test2[1, 0] = rgg.DirectedGraph(typeof(AdjacencyMatrixGraph), 2500, 0.95, 1, 999); izo_test2[1, 1] = new AdjacencyListsGraph <HashTableAdjacencyList>(izo_test2[1, 0]); izo_test2[1, 1] = rgg.Permute(izo_test2[1, 1]); }
/// <summary> /// Metoda zwraca największą możliwą do wyprodukowania liczbę smerfonów /// </summary> /// <param name="providers">Dostawcy</param> /// <param name="factories">Fabryki</param> /// <param name="distanceCostMultiplier">współczynnik kosztu przewozu</param> /// <param name="productionCost">Łączny koszt produkcji wszystkich smerfonów</param> /// <param name="transport">Tablica opisująca ilości transportowanych surowców miedzy poszczególnymi dostawcami i fabrykami</param> /// <param name="maximumProduction">Maksymalny rozmiar produkcji</param> public static double CalculateFlow(Provider[] providers, Factory[] factories, double distanceCostMultiplier, out double productionCost, out int[,] transport, int maximumProduction = int.MaxValue) { Graph gFlow = new AdjacencyListsGraph <SimpleAdjacencyList>(true, providers.Length + factories.Length * 2 + 3); Graph gCost = new AdjacencyListsGraph <SimpleAdjacencyList>(true, providers.Length + factories.Length * 2 + 3); int i = 1; for (int z = 1; z < providers.Length + 1; z++) { gFlow.AddEdge(0, z, providers[z - 1].Capacity); gCost.AddEdge(0, z, providers[z - 1].Cost); } foreach (var provider in providers) { int k = providers.Length + 1; foreach (var factory in factories) { double distance = Math.Ceiling(Math.Sqrt((factory.Position.X - provider.Position.X) * (factory.Position.X - provider.Position.X) + (factory.Position.Y - provider.Position.Y) * (factory.Position.Y - provider.Position.Y)) * distanceCostMultiplier); gFlow.AddEdge(new Edge(i, k, double.MaxValue)); gCost.AddEdge(new Edge(i, k, distance)); gFlow.AddEdge(new Edge(i, k + factories.Length, double.MaxValue)); gCost.AddEdge(new Edge(i, k + factories.Length, distance)); k++; } i++; } for (int z = providers.Length + 1; z < factories.Length + providers.Length + 1; z++) { gFlow.AddEdge(z, providers.Length + factories.Length * 2 + 1, factories[z - providers.Length - 1].Limit); gCost.AddEdge(z, providers.Length + factories.Length * 2 + 1, factories[z - providers.Length - 1].LowerCost); gFlow.AddEdge(z + factories.Length, providers.Length + factories.Length * 2 + 1, int.MaxValue); gCost.AddEdge(z + factories.Length, providers.Length + factories.Length * 2 + 1, factories[z - providers.Length - 1].HigherCost); } Graph fl; gCost.Add(new Edge(providers.Length + factories.Length * 2 + 1, providers.Length + factories.Length * 2 + 2, 0)); gFlow.Add(new Edge(providers.Length + factories.Length * 2 + 1, providers.Length + factories.Length * 2 + 2, maximumProduction)); double max = gFlow.MinCostFlow(gCost, 0, providers.Length + factories.Length * 2 + 2, out productionCost, out fl); transport = new int[providers.Length, factories.Length]; for (int z = 1; z < providers.Length + 1; z++) { foreach (Edge e in fl.OutEdges(z)) { int to = e.To; if (to > providers.Length + factories.Length) { to -= factories.Length; } transport[e.From - 1, to - providers.Length - 1] += (int)e.Weight; } } return(max); }
/// <summary> /// Część 2. zadania - zaplanowanie produkcji telewizorów dla wielu kontrahentów. /// </summary> /// <remarks> /// Do przeprowadzenia testów wyznaczających produkcję dającą maksymalny zysk wymagane jest jedynie zwrócenie obiektu <see cref="PlanData"/>. /// Testy weryfikujące plan wymagają przypisania tablicy z planem do parametru wyjściowego <see cref="weeklyPlan"/>. /// </remarks> /// <param name="production"> /// Tablica obiektów zawierających informacje o produkcji fabryki w kolejnych tygodniach. /// Wartość pola <see cref="PlanData.Quantity"/> oznacza limit produkcji w danym tygodniu, /// a pola <see cref="PlanData.Value"/> - koszt produkcji jednej sztuki. /// </param> /// <param name="sales"> /// Dwuwymiarowa tablica obiektów zawierających informacje o sprzedaży w kolejnych tygodniach. /// Pierwszy wymiar tablicy jest równy liczbie kontrahentów, zaś drugi - liczbie tygodni w planie. /// Wartości pola <see cref="PlanData.Quantity"/> oznaczają maksymalną sprzedaż w danym tygodniu, /// a pola <see cref="PlanData.Value"/> - cenę sprzedaży jednej sztuki. /// Każdy wiersz tablicy odpowiada jednemu kontrachentowi. /// </param> /// <param name="storageInfo"> /// Obiekt zawierający informacje o magazynie. /// Wartość pola <see cref="PlanData.Quantity"/> oznacza pojemność magazynu, /// a pola <see cref="PlanData.Value"/> - koszt przechowania jednego telewizora w magazynie przez jeden tydzień. /// </param> /// <param name="weeklyPlan"> /// Parametr wyjściowy, przez który powinien zostać zwrócony szczegółowy plan sprzedaży. /// </param> /// <returns> /// Obiekt <see cref="PlanData"/> opisujący wyznaczony plan. /// W polu <see cref="PlanData.Quantity"/> powinna znaleźć się optymalna liczba wyprodukowanych telewizorów, /// a w polu <see cref="PlanData.Value"/> - wyznaczony maksymalny zysk fabryki. /// </returns> public PlanData CreateComplexPlan(PlanData[] production, PlanData[,] sales, PlanData storageInfo, out WeeklyPlan[] weeklyPlan) { int verticesPerWeek = 2 + sales.GetLength(0); int verticesCount = verticesPerWeek * production.Length + 2; Graph initialGraph = new AdjacencyListsGraph <HashTableAdjacencyList>(true, verticesCount); Graph flowsGraph = initialGraph.IsolatedVerticesGraph(); Graph costGraph = initialGraph.IsolatedVerticesGraph(); for (int week = 0; week < production.Length; week++) { flowsGraph.AddEdge(0, week * verticesPerWeek + 1, double.PositiveInfinity); costGraph.AddEdge(0, week * verticesPerWeek + 1, 0); flowsGraph.AddEdge(week * verticesPerWeek + 1, week * verticesPerWeek + 2, production[week].Quantity); costGraph.AddEdge(week * verticesPerWeek + 1, week * verticesPerWeek + 2, production[week].Value); if (production.Length - week >= 2) { flowsGraph.AddEdge(week * verticesPerWeek + 2, week * verticesPerWeek + verticesPerWeek + 2, storageInfo.Quantity); costGraph.AddEdge(week * verticesPerWeek + 2, (week + 1) * verticesPerWeek + 2, storageInfo.Value); } //for (int i = 0; i < length; i++) //{ //} //flowsGraph.AddEdge(week * verticesPerWeek + 2, week * verticesPerWeek + 3, sales[week].Quantity); //costGraph.AddEdge(week * verticesPerWeek + 2, week * verticesPerWeek + 3, -sales[week].Value); flowsGraph.AddEdge(week * verticesPerWeek + 3, verticesCount - 1, double.PositiveInfinity); costGraph.AddEdge(week * verticesPerWeek + 3, verticesCount - 1, 0); } (double tvQuantity, double cost, Graph resultFlow) = flowsGraph.MinCostFlow(costGraph, 0, verticesCount - 1, true); weeklyPlan = new WeeklyPlan[production.Length]; for (int week = 0; week < production.Length; week++) { weeklyPlan[week].UnitsProduced = (int)resultFlow.GetEdgeWeight(week * verticesPerWeek + 1, week * verticesPerWeek + 2); //weeklyPlan[week].UnitsSold = (int)resultFlow.GetEdgeWeight(week * verticesPerWeek + 2, week * verticesPerWeek + 3); if (production.Length - week >= 2) { weeklyPlan[week].UnitsStored = (int)resultFlow.GetEdgeWeight(week * verticesPerWeek + 2, (week + 1) * verticesPerWeek + 2); } else { weeklyPlan[week].UnitsStored = 0; } } return(new PlanData { Quantity = (int)tvQuantity, Value = -cost }); }
/// <summary> /// Wersja III i IV zadania /// Zwraca najkrótszy możliwy czas przejścia przez labirynt z użyciem co najwyżej k lasek dynamitu /// </summary> /// <param name="maze">labirynt</param> /// <param name="k">liczba dostępnych lasek dynamitu, dla wersji III k=1</param> /// <param name="path">zwracana ścieżka</param> /// <param name="t">czas zburzenia ściany</param> /// // pomysl: k+1 takich samych grafow(warstw) bez krawedzi X , a krawedzie X to takie "mosty" miedzy warstwami // ETAP 3 i 4 public int FindShortestPathWithKDynamites(char[,] maze, int k, out string path, int t) { path = ""; int X = maze.GetLength(1); int Y = maze.GetLength(0); int n = X * Y; // liczba punktow w tablicy, dla ulatwienia w szukaniu numeru wierzcholka w innej warstwie grafu int start = -1; int end = -1; AdjacencyListsGraph <AVLAdjacencyList> g = new AdjacencyListsGraph <AVLAdjacencyList>(true, (k + 1) * n); PathsInfo[] p = null; createGraph(maze, g, t, out start, out end, k, n); ShortestPathsGraphExtender.DijkstraShortestPaths(g, start, out p); int[] dist = new int[k + 1]; // tablica najlepszych drog dla uzycia dynamitow od 0 do k for (int i = 0; i <= k; ++i) { dist[i] = -1; } int min = int.MaxValue; int index = 0; // ilosc dynamitow zuzytych dla najlepszej drogi for (int i = 0; i <= k; ++i) // sprawdzenie dla kazdej ilosci uzytego dynamitu najlepszej drogi { int tmp = (int)p[end + i * n].Dist; if (!Double.IsNaN(p[end + i * n].Dist)) // jesli nie NaN to porownac z wartoscia najmniejsza { dist[i] = tmp; if (tmp < min) // jesli nowa wartosc lepsza to zapisac jako min { min = tmp; index = i; } } } if (min == int.MaxValue) { return(-1); // jesli nie znaleziono sciezki to -1 } else { if (X > 1) { path = constructStringE34(PathsInfo.ConstructPath(start, end + index * n, p), X, n); } else // jesli kolejne wierzcholki grafu nie sa na tablicy po prawo/lewo, tylko gora/dol (bo wymiar 1xN czy Nx1 nie wiem) { path = constructStringE341xN(PathsInfo.ConstructPath(start, end + index * n, p), X, n); } return(min); } }
public static Graph wheel() { int veticesCount = rnd.Next(4, 101); Graph wheel = new AdjacencyListsGraph <SimpleAdjacencyList>(false, veticesCount); for (int i = 1; i < veticesCount; i++) { wheel.AddEdge(0, i); wheel.AddEdge(i - 1, i); } wheel.AddEdge(1, veticesCount - 1); return(changeVerticesNumeration(wheel)); }
//Część 2 // Konstruowanie grafu na podstawie podanego ciągu grafowego public Graph ConstructGraph(int[] sequence) { Graph g = new AdjacencyListsGraph <HashTableAdjacencyList>(false, sequence.Length); if (sequence.Length == 1) { if (sequence[0] == 0) { return(g); } else { return(null); } } List <(int, int)> t = new List <(int, int)>(); int sum = 0; for (int i = 0; i < sequence.Length; i++) { t.Add((sequence[i], i)); sum += sequence[i]; } if (sum % 2 == 1) { return(null); } t.Sort(); int count = t.Count; while (count > 1 && t[count - 1].Item1 > 0) { for (int i = 0; i < t[count - 1].Item1; i++) { if (t[count - 2 - i].Item1 == 0) { return(null); } g.AddEdge(t[count - 1].Item2, t[count - 2 - i].Item2); t[count - 2 - i] = (t[count - 2 - i].Item1 - 1, t[count - 2 - i].Item2); } t.RemoveAt(count - 1); count--; t.Sort(); } return(g); }
public static Graph changeVerticesNumeration(Graph g) { int[] perm = permutation(g.VerticesCount); Graph gnew = new AdjacencyListsGraph <SimpleAdjacencyList>(false, g.VerticesCount); for (int i = 0; i < g.VerticesCount; i++) { foreach (Edge e in g.OutEdges(i)) { gnew.AddEdge(perm[e.From], perm[e.To]); } } return(gnew); }
//Część 2 // Konstruowanie grafu na podstawie podanego ciągu grafowego // 1.5 pkt public Graph ConstructGraph(int[] sequence) { if (sequence == null) { return(null); } if (!IsGraphic(sequence)) { return(null); } AdjacencyListsGraph <SimpleAdjacencyList> g = new AdjacencyListsGraph <SimpleAdjacencyList>(false, sequence.Length); List <(int, int)> lista = new List <(int, int)>(); sequence = sequence.OrderByDescending(x => x).ToArray(); for (int i = 0; i < sequence.Length; i++) { lista.Add((i, sequence[i]));
//Część 3 // Wyznaczanie minimalnego drzewa (bądź lasu) rozpinającego algorytmem Kruskala // 2 pkt public Graph MinimumSpanningTree(Graph graph, out double min_weight) { if (graph.Directed == true) { throw new ArgumentException(); } EdgesMinPriorityQueue edges = new EdgesMinPriorityQueue(); Predicate <Edge> wyjscie = delegate(Edge a) { if (a.From < a.To) { edges.Put(a); } return(true); }; graph.GeneralSearchAll <EdgesStack>(null, null, wyjscie, out int cc); UnionFind union = new UnionFind(graph.VerticesCount); Graph graf = new AdjacencyListsGraph <SimpleAdjacencyList>(false, graph.VerticesCount); min_weight = 0; int ile_wstawione_krawedzi = 0; int ile_wierzcholkow = graph.VerticesCount; while (edges.Empty == false) { Edge e = edges.Get(); if (union.Find(e.From) != union.Find(e.To)) { union.Union(e.From, e.To); graf.AddEdge(e); min_weight += e.Weight; ile_wstawione_krawedzi++; } if (ile_wstawione_krawedzi == ile_wierzcholkow - 1) { break; } } return(graf); }
/// <summary> /// Procedura określająca czy drużyna jest wyeliminowana z rozgrywek /// </summary> /// <param name="teamId">indeks drużyny do sprawdzenia</param> /// <param name="teams">lista zespołów</param> /// <param name="predictedResults">wyniki gwarantujące zwycięstwo sprawdzanej drużyny</param> /// <returns></returns> public static bool IsTeamEliminated(int teamId, Team[] teams, out int[,] predictedResults) { predictedResults = null; int n = teams.Length; Graph g = new AdjacencyListsGraph <SimplyAdjacencyList>(true, (n * (n - 1)) / 2 + n + 2); int s = g.VerticesCount - 2; int t = g.VerticesCount - 1; // krawędzie drużyna -> ujście for (int i = 0; i < n; i++) { g.AddEdge(i, t, teams[teamId].NumberOfWins + teams[teamId].NumberOfGamesToPlay - teams[i].NumberOfWins); } int v = n; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { g.AddEdge(s, v, teams[i].NumberOfGamesToPlayByTeam[j]); g.AddEdge(v, i, int.MaxValue); g.AddEdge(v, j, int.MaxValue); v++; } } Graph flow; g.FordFulkersonMaxFlow(s, t, out flow); foreach (Edge e in flow.OutEdges(s)) { if (e.Weight < g.GetEdgeWeight(s, e.To).Value) { return(false); } } return(true); }
public static Graph rawHelm() { int verticesCount = rnd.Next(4, 1000); if (verticesCount % 2 == 0) { verticesCount++; } Graph helm = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); int i; int ringSize = verticesCount / 2; for (i = 1; i <= ringSize; i++) // 1:ringSize is first cycle; ringsize+1:2*ringSize is second cycle { helm.AddEdge(new Edge(i - 1, i)); helm.AddEdge(new Edge(0, i)); helm.AddEdge(new Edge(i, ringSize + i)); // connecting outer vertices } helm.AddEdge(new Edge(ringSize, 1)); return(helm); }
// ETAP 1 i 2 public int FindShortestPath(char[,] maze, bool withDynamite, out string path, int t = 0) { path = ""; int X = maze.GetLength(1); int Y = maze.GetLength(0); int start = -1; int end = -1; AdjacencyListsGraph <AVLAdjacencyList> g = new AdjacencyListsGraph <AVLAdjacencyList>(true, X * Y); PathsInfo[] p = null; if (t == 0) { createGraph(maze, g, out start, out end); } else { createGraph(maze, g, t, out start, out end); } ShortestPathsGraphExtender.DijkstraShortestPaths(g, start, out p); int dist = (int)p[end].Dist; if (!Double.IsNaN(p[end].Dist)) { if (X > 1) { path = constructString(PathsInfo.ConstructPath(start, end, p)); } else { path = constructString1xN(PathsInfo.ConstructPath(start, end, p)); } return(dist); } else { return(-1); } }
private void button1_Click(object sender, EventArgs e) { Random rand = new Random(); int x = 100; int y = 100; IGraph g = new AdjacencyListsGraph(false, x * y); for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { if (rand.Next(0, 3) != 3) { g.AddEdge(i, j, rand.Next(1, 3)); } } } textBox1.Text = ""; Edge[] path; int s = 3, t = 24; g.DelEdge(s, t); Stopwatch sw = new Stopwatch(); sw.Start(); if (g.AStar(s, t, out path)) { foreach (var p in path) { textBox1.Text += p.From + ","; } textBox1.Text += t; } textBox2.Text = sw.Elapsed.Milliseconds.ToString(); }
public static void WeightedTest() { Console.Out.WriteLine("Grafy ważone"); Graph grid3 = new AdjacencyListsGraph <SimpleAdjacencyList>(false, 9); for (int i = 0; i < 9; i += 3) { grid3.AddEdge(i, i + 1, 3); grid3.AddEdge(i + 1, i + 2, 2); } for (int i = 0; i < 3; i++) { grid3.AddEdge(i + 0, i + 3, 2); grid3.AddEdge(i + 3, i + 6, 1); } RandomGraphGenerator rgg = new RandomGraphGenerator(240044); Graph eCycle24 = rgg.UndirectedCycle(typeof(AdjacencyListsGraph <SimpleAdjacencyList>), 24, 1, 5, true); Graph oCycle23 = rgg.UndirectedCycle(typeof(AdjacencyListsGraph <SimpleAdjacencyList>), 23, 1, 5, true); Graph g3 = rgg.UndirectedGraph(typeof(AdjacencyListsGraph <SimpleAdjacencyList>), 20, 0.2, 1, 11, true); TestSet set2 = new TestSet(); set2.TestCases.Add(new MatchingTestCase(10, grid3, 0, 4, 5)); set2.TestCases.Add(new MatchingTestCase(10, grid3, 1, 5, 7)); set2.TestCases.Add(new MatchingTestCase(10, grid3, 2 * grid3.EdgesCount - grid3.VerticesCount, grid3.EdgesCount, 3 + 6 + 6 + 9)); set2.TestCases.Add(new MatchingTestCase(10, grid3, 2 * grid3.EdgesCount - grid3.VerticesCount - 1, grid3.EdgesCount - 1, 3 + 6 + 6 + 6)); set2.TestCases.Add(new MatchingTestCase(10, eCycle24, 0, 12, 33)); set2.TestCases.Add(new MatchingTestCase(10, oCycle23, 0, 11, 30)); set2.TestCases.Add(new MatchingTestCase(10, eCycle24, 1, 12, 24)); set2.TestCases.Add(new MatchingTestCase(10, oCycle23, 1, 12, 32)); set2.TestCases.Add(new MatchingTestCase(10, g3, 0, 10, 45)); set2.TestCases.Add(new MatchingTestCase(10, g3, 2, 11, 43)); set2.TestCases.Add(new MatchingTestCase(10, g3, 3, 11, 35)); set2.PreformTests(true, false); }
public static Graph cycle() { int verticesCount = rnd.Next(3, 100); Graph cycle = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); for (int i = 1; i < verticesCount; i++) { cycle.AddEdge(i - 1, i); } cycle.AddEdge(0, verticesCount - 1); cycle = changeVerticesNumeration(cycle); //FOR USER - checking changeVerticesNumeration /* * if (cycle.VerticesCount < 11) * { * int vert = 0; * int vold = -1; * int v = 0; * Console.Write("vert count = " + verticesCount); * Console.WriteLine(); * Edge e; ; * do * { * Console.Write(v + " "); * e = cycle.OutEdges(v).ToArray()[0]; * if (e.To == vold || e.From == vold) * e = cycle.OutEdges(v).ToArray()[1]; * vold = v; * if (vold == e.To) * v = e.From; * else * v = e.To; * } * while (v != vert); * Console.WriteLine(); * } */ return(cycle); }
static Graph randomRegularBipartite(int vertices, int degree, int seed) { Random rand = new Random(seed); Graph ret = new AdjacencyListsGraph <HashTableAdjacencyList>(false, 2 * vertices); for (int j = 0; j < degree; j++) { for (int i = 0; i < vertices; i++) { int curi = i; int v2 = -1; while (true) { v2 = 2 * rand.Next(vertices) + 1; //while (ret.OutDegree(v2) != j) // v2 = 2 * rand.Next(vertices) + 1; while (!ret.GetEdgeWeight(2 * curi, v2).IsNaN()) { v2 = 2 * rand.Next(vertices) + 1; } if (ret.OutDegree(v2) != j) { int tmpi = ret.OutEdges(v2).ToArray()[rand.Next(ret.OutDegree(v2))].To / 2; while (ret.OutDegree(2 * tmpi) != j + 1) { tmpi = ret.OutEdges(v2).ToArray()[rand.Next(ret.OutDegree(v2))].To / 2; } ret.DelEdge(2 * tmpi, v2); ret.AddEdge(2 * curi, v2); curi = tmpi; continue; } break; } ret.AddEdge(2 * curi, v2); } } return(ret); }
internal static Graph BuildSeekFlowGraph(int teamId, Team[] teams) { int teamsCount = teams.Length; int pairLayerCount = (int)GetBinCoeff(teamsCount - 1, 2); int teamLayerCount = teamsCount - 1; int verticesCount = 2 + pairLayerCount + teamLayerCount; Graph h = new AdjacencyListsGraph <SimpleAdjacencyList>(true, verticesCount); //Directed // start - 0 // target - 1 // team pairs - 2 => 2 + pairLayerCount // teams - 2 + pairLayerCount => verticesCount var matchesToPlayBetweenTeams = new int[pairLayerCount]; for (int i = 0; i < pairLayerCount + 1; i++) { if (i != teamId) //If not input team { for (int j = i + 1; j < teamsCount; j++) { if (j != teamId) //if not corresponding to input team { matchesToPlayBetweenTeams[i] = teams[i].NumberOfGamesToPlayByTeam[j]; //Number of games to play by team pairs } } } } for (int i = 0; i < pairLayerCount; i++) { if (i != teamId) { for (int j = i + 1; j < teamsCount; j++) { h.AddEdge(0, i, matchesToPlayBetweenTeams[i]); } } } }
public static Graph eulerian2() { int verticesCount = rnd.Next(4, 1000); Graph hamiltonian = new AdjacencyListsGraph <SimpleAdjacencyList>(false, verticesCount); int timesInStartVertice = rnd.Next(1, verticesCount / 2); int timesInStartv = 0; int v = 0; int t; while (timesInStartv < timesInStartVertice) { do { t = rnd.Next(0, verticesCount); } while (t == v); hamiltonian.AddEdge(v, t); v = t; if (v == 0) { timesInStartv += 2; } } return(changeVerticesNumeration(hamiltonian)); }
//Część 2 // Konstruowanie grafu na podstawie podanego ciągu grafowego // 1.5 pkt public Graph ConstructGraph(int[] sequence) { Graph wynik = new AdjacencyListsGraph <SimpleAdjacencyList>(false, sequence.Length); if (IsGraphic(sequence) == false) { return(null); } List <KeyValuePair <int, int> > listapar = new List <KeyValuePair <int, int> >(); for (int i = 0; i < sequence.Length; i++) { KeyValuePair <int, int> el = new KeyValuePair <int, int>(i, sequence[i]); listapar.Add(el); } while (listapar.Count > 0) { listapar.Sort((x, y) => { return(-x.Value.CompareTo(y.Value)); }); for (int j = 1; j <= listapar[0].Value && j < listapar.Count; j++) { wynik.AddEdge(listapar[0].Key, listapar[j].Key); wynik.AddEdge(listapar[j].Key, listapar[0].Key); listapar[j] = new KeyValuePair <int, int>(listapar[j].Key, listapar[j].Value - 1); } listapar.RemoveAt(0); } return(wynik); }
public static IGraph CreateSimpleGraph(this GameMap gameMap, List <Fighter> fighters, List <Enemy> enemies, Vector2 start, Vector2 end) { Point p1 = start.GetMapPosition(gameMap); Point p2 = start.GetMapPosition(gameMap); IGraph g; if ((Math.Abs(p1.X - p2.X) + 4) * (Math.Abs(p1.Y - p2.Y) + 4) < 100) { g = new AdjacencyListsGraph(false, (Math.Abs(p1.X - p2.X) + 4) * (Math.Abs(p1.Y - p2.Y) + 4)); } else { g = new AdjacencyListsGraph(false, 100); // TODO do poprawy } /* * Point sourceMap = source.GetMapPosition(gameMap); * Point destinationMap = source.GetMapPosition(gameMap); * Point shift = new Point((int)Math.Min(sourceMap.X, destinationMap.X), (int)Math.Min(sourceMap.Y, destinationMap.Y)); * * IGraph g = new AdjacencyMatrixGraph(false,(int)(Math.Abs(destinationMap.X-sourceMap.X+4)*Math.Abs(destinationMap.Y-sourceMap.Y+4))); * * for (int i = -2; i < destinationMap.X - sourceMap.X + 2; i++) * { * for (int j = -2; j < destinationMap.Y - sourceMap.Y + 2; j++) * { * if (shift.X+i >= 0 && shift.X+i < gameMap.width && shift.Y + j - 2 >=0 && shift.Y+j-2 < gameMap.height && gameMap[shift.X + i, shift.Y + j - 2].mapObjects.Count == 0) * { * //g.AddEdge((int)( j * (destinationMap.X - sourceMap.X + 4) + i ),(int)( (j - 2) * (destinationMap.X - sourceMap.X + 4) + i - 1 )); * } * } * } */ return(g); }
public static void Main() { int[] backtrackingColors; int[] greedyColors; int n,i,j,mb,mg; long counter0, counter1, counter2; string[] message1 = { "Zwykly maly graf:", "Maly dwudzielny:", "Mala klika:" }; int[] bestColorsNumbers1 = { 4, 2, 9 }; string[] message2 = { "Zwykly graf:", "Graf dwudzielny:", "Cykl parzysty:", "Klika:" }; int[] bestColorsNumbers2 = { 6, 2, 2, 200 }; string[] message3 = { "Zwykly duzy graf:", "Duzy dwudzielny:", "Duza klika:" }; int[] bestColorsNumbers3 = { 59, 2, 4000 }; IGraph[] g1 = new IGraph[message1.Length]; IGraph[] g2 = new IGraph[message2.Length]; IGraph[] g3 = new IGraph[message3.Length]; var rgg = new RandomGraphGenerator(); //GraphExport ge = new GraphExport(true, "C:\\Users\\polgrabiat\\Desktop\\Graphviz2.26.3\\Graphviz2.26.3\\bin\\dot.exe"); Console.WriteLine(); Console.WriteLine("Generowanie grafow"); Console.WriteLine(); rgg.SetSeed(101); g1[0] = rgg.UndirectedGraph(typeof(AdjacencyMatrixGraph),8,0.5); rgg.SetSeed(102); g1[1] = rgg.BipariteGraph(typeof(AdjacencyMatrixGraph),5,3,0.75); n=9; g1[2] = new AdjacencyMatrixGraph(false,n); for ( i=0 ; i<n ; ++i ) for ( j=i+1 ; j<n ; ++ j ) g1[2].AddEdge(i,j); rgg.SetSeed(103); g2[0] = rgg.UndirectedGraph(typeof(AdjacencyMatrixGraph), 20, 0.5); rgg.SetSeed(104); g2[1] = rgg.BipariteGraph(typeof(AdjacencyMatrixGraph), 30, 20, 0.25); n = 50; g2[2] = new AdjacencyListsGraph(false, n); for (i = 1; i < n; ++i) g2[2].AddEdge(i - 1, i); g2[2].AddEdge(n - 1, 0); rgg.SetSeed(105); g2[2] = rgg.Permute(g2[2]); n = 200; g2[3] = new AdjacencyMatrixGraph(false, n); for (i = 0; i < n; ++i) { for (j = i + 1; j < n; ++j) g2[3].AddEdge(i, j); } rgg.SetSeed(106); g3[0] = rgg.UndirectedGraph(typeof(AdjacencyMatrixGraph), 75, 0.99); rgg.SetSeed(107); g3[1] = rgg.BipariteGraph(typeof(AdjacencyMatrixGraph), 2000, 2000, 0.55); n = 5000; g3[2] = new AdjacencyMatrixGraph(false, n); for (i = 0; i < n; ++i) { for (j = i + 1; j < n; ++j) g3[2].AddEdge(i, j); } //Console.WriteLine("{0}", g3[2].EdgesCount); Console.WriteLine("Grafy za 1 pkt"); Console.WriteLine(); for ( i=0 ; i<g1.Length ; ++i ) { // ge.Export(g1[i], "ala"); counter0=Graph.Counter; mb=g1[i].BacktrackingColor(out backtrackingColors); counter1=Graph.Counter; mg=g1[i].GreedyColor(out greedyColors); counter2=Graph.Counter; Console.WriteLine("{0,-17} liczba wierzcholkow {1,4}, optymalna liczba kolorow {2,4}", message1[i], g1[i].VerticesCount, bestColorsNumbers1[i]); Console.WriteLine(" Backtracking: liczba kolorow {0,4}, zlozonosc {1,8}", mb, counter1-counter0); Console.WriteLine(" Greedy: liczba kolorow {0,4}, zlozonosc {1,8}", mg, counter2-counter1); Console.WriteLine(); } Console.WriteLine("Grafy za 2 pkt"); Console.WriteLine(); for (i = 0; i < g2.Length; ++i) { counter0 = Graph.Counter; mb = g2[i].BacktrackingColor(out backtrackingColors); counter1 = Graph.Counter; mg = g2[i].GreedyColor(out greedyColors); counter2 = Graph.Counter; Console.WriteLine("{0,-17} liczba wierzcholkow {1,4}, optymalna liczba kolorow {2,4}", message2[i], g2[i].VerticesCount, bestColorsNumbers2[i]); Console.WriteLine(" Backtracking: liczba kolorow {0,4}, zlozonosc {1,8}", mb, counter1 - counter0); Console.WriteLine(" Greedy: liczba kolorow {0,4}, zlozonosc {1,8}", mg, counter2 - counter1); Console.WriteLine(); } Console.WriteLine("Grafy za 3 pkt"); Console.WriteLine(); for (i = 0; i < g3.Length; ++i) { counter0 = Graph.Counter; mb = g3[i].BacktrackingColor(out backtrackingColors); counter1 = Graph.Counter; mg = g3[i].GreedyColor(out greedyColors); counter2 = Graph.Counter; Console.WriteLine("{0,-17} liczba wierzcholkow {1,4}, optymalna liczba kolorow {2,4}", message3[i], g3[i].VerticesCount, bestColorsNumbers3[i]); Console.WriteLine(" Backtracking: liczba kolorow {0,4}, zlozonosc {1,8}", mb, counter1 - counter0); Console.WriteLine(" Greedy: liczba kolorow {0,4}, zlozonosc {1,8}", mg, counter2 - counter1); Console.WriteLine(); } Console.WriteLine("Koniec"); Console.WriteLine(); }
static void Main(string[] args) { try { var rgg = new RandomGraphGenerator(123); IGraph h1, h2; IGraph g1 = new AdjacencyMatrixGraph(false, 5); IGraph g2 = new AdjacencyListsGraph(true, 4); Console.WriteLine("# licznik: {0}", Graph.Counter); g1.AddEdge(0, 1); g1.AddEdge(1, 2); g1.AddEdge(0, 2); g1.AddEdge(0, 4); g1.AddEdge(2, 4); g1.AddEdge(2, 3); Console.WriteLine("# licznik: {0}", Graph.Counter); Console.WriteLine("Graf g1 jest typu: {0} i jest skierowany: {1}", g1.GetType(), g1.Directed); h1 = g1.AddVertex(); Console.WriteLine("\nDodawanie\nGraf h1 ma {0} (powinno być 6) wierzchołków, a ostatni wierzchołek ma stopień {1} (powinno być 0)", h1.VerticesCount, h1.InDegree(h1.VerticesCount - 1)); Console.WriteLine("Graf h1 ma {0} (powinno być 6) krawędzi", h1.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h1 = g1.DeleteVertex(2); Console.WriteLine("\nUsuwanie\nGraf h1 ma {0} (powinno być 4) wierzchołków, a wierzchołki 1,2,3 mają odpowiednio stopienie {1} (powinno być 1),{2} (powinno być 0),{3} (powinno być 1)", h1.VerticesCount, h1.InDegree(1), h1.InDegree(2), h1.InDegree(3)); Console.WriteLine("Graf h1 ma {0} (powinno być 2) krawędzi", h1.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h1 = g1.Complement(); Console.WriteLine("\nDopełnienie g1 ma {0} (powinno być 4) krawędzi", h1.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h1 = g1.Closure(); Console.WriteLine("\nDomknięcie g1 ma {0} (powinno być 10) krawędzi", h1.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h1 = (g1.AddVertex()).Closure(); Console.WriteLine("Domknięcie g1 + K1 ma {0} (powinno być 10) krawędzi", h1.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); Console.WriteLine("\nCzy h1 jest dwudzielny ?: {0} (powinno być False)", h1.IsBipartite()); Console.WriteLine("# licznik: {0}", Graph.Counter); h1 = rgg.BipariteGraph(typeof(AdjacencyMatrixGraph), 30, 50, 0.5); Console.WriteLine("\nCzy nowy h1 jest dwudzielny ?: {0} (powinno być True)", h1.IsBipartite()); Console.WriteLine("# licznik: {0}", Graph.Counter); Console.WriteLine("\n\n*************************\n\n"); g2.AddEdge(0, 1); g2.AddEdge(2, 1); g2.AddEdge(3, 2); Console.WriteLine("# licznik: {0}", Graph.Counter); Console.WriteLine("Graf g2 jest typu: {0} i jest skierowany: {1}", g2.GetType(), g2.Directed); h2 = g2.AddVertex(); Console.WriteLine("\nDodawanie\nGraf h2 ma {0} (powinno być 5) wierzchołków, a ostatni wierzchołek ma stopień wy: {1} (powinno być 0) i we: {2} (powinno być 0) ", h2.VerticesCount, h2.InDegree(h2.VerticesCount - 1), h2.OutDegree(h2.VerticesCount - 1)); Console.WriteLine("Graf h2 ma {0} (powinno być 3) krawędzi", h2.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h2 = g2.DeleteVertex(1); Console.WriteLine("\nUsuwanie\nGraf h2 ma {0} (powinno być 3) wierzchołków, a wierzchołek 1 ma stopień wy: {1} (powinno być 0) ", h2.VerticesCount, h2.OutDegree(1)); Console.WriteLine("Graf h2 ma {0} (powinno być 1) krawędzi", h2.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h2 = g2.Complement(); Console.WriteLine("\nDopełnienie g2 ma {0} (powinno być 9) krawędzi", h2.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h2 = g2.Closure(); Console.WriteLine("\nDomknięcie g2 + K1 ma {0} (powinno być 4) krawędzi", h2.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); h2 = (g2.AddVertex()).Closure(); Console.WriteLine("Domknięcie g2 + K1 ma {0} (powinno być 4) krawędzi", h2.EdgesCount); Console.WriteLine("# licznik: {0}", Graph.Counter); Console.WriteLine("\nCzy h2 jest dwudzielny ?: {0} (powinno być False)", g2.IsBipartite()); Console.WriteLine("# licznik: {0}", Graph.Counter); } catch (Exception e) { Console.WriteLine(e.Message); } }
/// <summary> /// Dodaje 2 cykle fundamentalne /// </summary> /// <param name="c1">Pierwszy cykl</param> /// <param name="c2">Drugi cykl</param> /// <returns>null, jeśli wynikiem nie jest cykl i suma cykli, jeśli wynik jest cyklem</returns> public Edge[] AddFundamentalCycles(Edge[] c1, Edge[] c2) { int maxV = 0; foreach (Edge e in c1) { if (e.To > maxV) { maxV = e.To; } } foreach (Edge e in c2) { if (e.To > maxV) { maxV = e.To; } } Graph g = new AdjacencyListsGraph <SimpleAdjacencyList>(false, maxV + 1); foreach (Edge e in c1) { g.AddEdge(e); } foreach (Edge e in c2) { if (g.GetEdgeWeight(e.From, e.To).IsNaN()) { g.AddEdge(e); } else { g.DelEdge(e); } } Edge[] result = null; bool moreEdges = false; bool[] visited = new bool[g.VerticesCount]; List <Edge> edgesList = new List <Edge>(); Predicate <Edge> onNewEdge = delegate(Edge e) { if (edgesList.Count > 0 && e.To == edgesList[0].From && e.From != edgesList[0].To) { edgesList.Add(e); result = edgesList.ToArray(); } else if (!visited[e.To]) { if (result == null) { edgesList.Add(e); } else { moreEdges = true; return(false); } } return(true); }; Predicate <int> onEntering = delegate(int n) { visited[n] = true; return(true); }; g.GeneralSearchAll <EdgesStack>(onEntering, null, onNewEdge, out _); if (moreEdges || result == null) { return(null); } else { return(result); } }
public static IGraph CreateSimpleGraph(this GameMap gameMap, List<Fighter> fighters, List<Enemy> enemies, Vector2 start, Vector2 end) { Point p1 = start.GetMapPosition(gameMap); Point p2 = start.GetMapPosition(gameMap); IGraph g; if ((Math.Abs(p1.X - p2.X) + 4) * (Math.Abs(p1.Y - p2.Y) + 4) < 100) g = new AdjacencyListsGraph(false, (Math.Abs(p1.X - p2.X) + 4) * (Math.Abs(p1.Y - p2.Y) + 4)); else g = new AdjacencyListsGraph(false, 100); // TODO do poprawy /* Point sourceMap = source.GetMapPosition(gameMap); Point destinationMap = source.GetMapPosition(gameMap); Point shift = new Point((int)Math.Min(sourceMap.X, destinationMap.X), (int)Math.Min(sourceMap.Y, destinationMap.Y)); IGraph g = new AdjacencyMatrixGraph(false,(int)(Math.Abs(destinationMap.X-sourceMap.X+4)*Math.Abs(destinationMap.Y-sourceMap.Y+4))); for (int i = -2; i < destinationMap.X - sourceMap.X + 2; i++) { for (int j = -2; j < destinationMap.Y - sourceMap.Y + 2; j++) { if (shift.X+i >= 0 && shift.X+i < gameMap.width && shift.Y + j - 2 >=0 && shift.Y+j-2 < gameMap.height && gameMap[shift.X + i, shift.Y + j - 2].mapObjects.Count == 0) { //g.AddEdge((int)( j * (destinationMap.X - sourceMap.X + 4) + i ),(int)( (j - 2) * (destinationMap.X - sourceMap.X + 4) + i - 1 )); } } } */ return g; }