├── GraphSharp
├── Common
│ ├── Usings.cs
│ ├── Interfaces
│ │ ├── IWeighted.cs
│ │ ├── IColored.cs
│ │ ├── IClonable{}.cs
│ │ ├── IPositioned.cs
│ │ ├── IForest.cs
│ │ ├── IPath.cs
│ │ └── IStatesHandler.cs
│ └── Implementations
│ │ ├── UnmanagedColor.cs
│ │ ├── PrimForest.cs
│ │ ├── ObjectPool.cs
│ │ ├── Components.cs
│ │ ├── KruskalForest.cs
│ │ ├── UnionFind.cs
│ │ ├── ByteStatesHandler.cs
│ │ └── Path.cs
├── Exceptions
│ ├── GraphConverterException.cs
│ ├── NodeNotFoundException.cs
│ ├── FailedToSolveMaxFlowException.cs
│ ├── EdgeNotFoundException.cs
│ ├── WrongCyclesPairException.cs
│ ├── WrongGraphColoringException.cs
│ ├── GraphDataIntegrityException.cs
│ ├── WrongNodeSetException.cs
│ └── NotLineGraphException.cs
├── Algorithms
│ ├── GraphOperations
│ │ ├── MakeDirected.cs
│ │ ├── RemoveNodes.cs
│ │ ├── MakeUndirected.cs
│ │ ├── LineGraph.cs
│ │ ├── RemoveIsolatedNodes.cs
│ │ ├── ReverseEdges.cs
│ │ ├── CreateNodes.cs
│ │ ├── RemoveEdges.cs
│ │ ├── FindLowLinkValues.cs
│ │ ├── RemoveUndirectedEdges.cs
│ │ ├── GetComplement.cs
│ │ ├── ConnectAsHamiltonianCycle.cs
│ │ ├── ConnectNodes.cs
│ │ ├── Induce.cs
│ │ ├── ConnectNodeToNodes.cs
│ │ ├── Isolate.cs
│ │ ├── IndependentSetFinder.cs
│ │ ├── TopologicalSort.cs
│ │ ├── DistanceMatrix.cs
│ │ ├── FindComponents.cs
│ │ ├── MakeComplete.cs
│ │ ├── ColorNodes.cs
│ │ ├── MakeSources.cs
│ │ ├── ContractEdge.cs
│ │ ├── ConnectRandomly.cs
│ │ ├── TransitiveClosureOnRadius.cs
│ │ ├── PlanarRender.cs
│ │ ├── FindSourceRepresentativeSet.cs
│ │ ├── Arrange.cs
│ │ ├── DelaunayTriangulation.cs
│ │ ├── FindEccentricity.cs
│ │ ├── FindCyclesBasis.cs
│ │ ├── FindLocalClusteringCoefficients.cs
│ │ ├── MinCut.cs
│ │ ├── Reindex.cs
│ │ ├── FindStronglyConnectedComponents.cs
│ │ ├── FindShortestPaths.cs
│ │ └── FindArticulationPoints.cs
│ ├── Coloring
│ │ ├── GreedyColoring.cs
│ │ ├── QuickGraphColoring.cs
│ │ ├── RLFColoring.cs
│ │ ├── ColoringAlgorithmBase.cs
│ │ ├── DSaturColoring.cs
│ │ └── ColoringResult.cs
│ ├── AlgorithmBase.cs
│ ├── IndependentSet
│ │ ├── IndependentSetResult.cs
│ │ ├── MaximalIndependentSetAlgorithmBase.cs
│ │ └── BallardMyerIndependentSet.cs
│ ├── KruskalAlgorithm.cs
│ ├── MathUtils.cs
│ ├── LowLinkValuesFinder copy
│ └── LowLinkValuesFinder.cs
├── Nodes
│ ├── NodeComparer.cs
│ ├── INode.cs
│ ├── Node.cs
│ └── NodePropertiesMap.cs
├── Edges
│ ├── EdgeComparer.cs
│ ├── IEdge.cs
│ ├── Edge.cs
│ └── EdgePropertiesMap.cs
├── Visitors
│ ├── Interfaces
│ │ ├── IVisitorWithSteps.cs
│ │ └── IVisitor{TNode,TEdge}.cs
│ ├── BaseClasses
│ │ ├── VisitorWithPropagator.cs
│ │ ├── EdgeSelect.cs
│ │ └── VisitorBase.cs
│ └── Implementations
│ │ ├── AnyPathFinder.cs
│ │ ├── ActionVisitor{TNode,TEdge}.cs
│ │ ├── SourceCreator.cs
│ │ ├── DijkstrasAlgorithm.cs
│ │ └── ShortestPathLengthFinderAlgorithms.cs
├── GraphStructures
│ ├── Implementations
│ │ ├── DefaultGraph.cs
│ │ ├── GraphStructureOperation.cs
│ │ ├── BaseEdgeSource.cs
│ │ ├── GraphConfiguration.cs
│ │ ├── GraphStructure.cs
│ │ └── ImmutableGraphOperation.cs
│ ├── Interfaces
│ │ ├── INodeSource.cs
│ │ ├── IEdgeSource.cs
│ │ ├── IImmutableNodeSource.cs
│ │ ├── IGraphConfiguration.cs
│ │ ├── IImmutableGraph.cs
│ │ ├── IImmutableEdgeSource.cs
│ │ └── IGraph{}.cs
│ └── Extensions
│ │ ├── ICollectionExtensions.cs
│ │ ├── EdgeNodeExtensions.cs
│ │ ├── DictionaryExtensions.cs
│ │ └── GraphOperationUtills.cs
├── Propagators
│ ├── Interfaces
│ │ └── IPropagator.cs
│ ├── BaseClasses
│ │ └── UsedNodeStates.cs
│ └── Implementations
│ │ ├── Propagator.cs
│ │ └── ParallelPropagator.cs
├── GraphDrawer
│ └── IShapeDrawer.cs
├── GraphSharp.sln
├── Adapters
│ └── EdgeAdapter.cs
└── GraphSharp.csproj
├── SimplestExample
├── NotoSans-Bold.ttf
├── SimplestExample.csproj
└── Program.cs
├── GraphSharp.Tests
├── ExtensionsTests.cs
├── helpers
│ ├── NodesComparer.cs
│ └── NodeEqualityComparer.cs
├── Common.cs
├── Operations
│ ├── BaseTest.cs
│ ├── ColoringTests.cs
│ └── PathFindersTests.cs
├── Models
│ ├── TestGraphConfiguration.cs
│ └── TestVisitor.cs
├── GraphSharp.Tests.csproj
├── GraphSharp.Tests.sln
└── ManualTestData.cs
├── .gitignore
├── GraphSharp.GoogleOrTools
├── GraphSharp.GoogleOrTools.csproj
├── GraphSharp.GoogleOrTools.sln
├── Extensions.cs
├── MinCostFlowResult.cs
├── Coloring.cs
└── TSP.cs
├── LICENSE
└── GraphSharp.sln
/GraphSharp/Common/Usings.cs:
--------------------------------------------------------------------------------
1 | global using RentedArraySharp;
2 | global using GraphSharp.Common;
--------------------------------------------------------------------------------
/SimplestExample/NotoSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kemsekov/GraphSharp/HEAD/SimplestExample/NotoSans-Bold.ttf
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IWeighted.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Common;
2 | ///
3 | public interface IWeighted
4 | {
5 | ///
6 | /// Weight of given element
7 | ///
8 | double Weight { get; set; }
9 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/ExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using GraphSharp.Graphs;
6 | using Xunit;
7 |
8 | namespace GraphSharp.Tests;
9 | public class ExtensionsTests
10 | {
11 |
12 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IColored.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | namespace GraphSharp.Common;
3 |
4 | ///
5 | public interface IColored
6 | {
7 | ///
8 | /// Color assigned to given element
9 | ///
10 | Color Color { get; set; }
11 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IClonable{}.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Common;
3 |
4 | ///
5 | public interface ICloneable : ICloneable
6 | where T : ICloneable
7 | {
8 | ///
9 | /// Clones object
10 | ///
11 | new T Clone();
12 | object ICloneable.Clone() => Clone();
13 | }
14 |
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/GraphConverterException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Occurs when any graph converter failed
6 | ///
7 | public class GraphConverterException : Exception
8 | {
9 | ///
10 | public GraphConverterException(string message) : base(message)
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IPositioned.cs:
--------------------------------------------------------------------------------
1 | using MathNet.Numerics.LinearAlgebra.Single;
2 |
3 | namespace GraphSharp.Common;
4 |
5 | ///
6 | /// Contains vector that describes position
7 | ///
8 | public interface IPositioned{
9 | ///
10 | /// Object position in n-dimensional space
11 | ///
12 | public Vector Position{get;}
13 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/NodeNotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Occurs required node is not found
6 | ///
7 | public class NodeNotFoundException : KeyNotFoundException
8 | {
9 | ///
10 | public NodeNotFoundException(string message) : base(message)
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/FailedToSolveMaxFlowException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Executed when algorithms fails to find max flow
6 | ///
7 | public class FailedToSolveMaxFlowException : Exception{
8 |
9 | ///
10 | public FailedToSolveMaxFlowException(string message) : base(message)
11 | {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/EdgeNotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Exception that occurs when requested edge is not found
6 | ///
7 | public class EdgeNotFoundException : KeyNotFoundException
8 | {
9 | ///
10 | public EdgeNotFoundException(string message) : base(message)
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/helpers/NodesComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 |
7 | namespace GraphSharp.Tests.helpers
8 | {
9 | public class NodesComparer : IComparer
10 | {
11 | public int Compare(INode x, INode y)
12 | {
13 | return x.Id-y.Id;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/WrongCyclesPairException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Occurs when you feed two linear-dependent cycles in cycle combiner
6 | ///
7 | public class WrongCyclesPairException : Exception
8 | {
9 | ///
10 | public WrongCyclesPairException(string message) : base(message)
11 | {
12 |
13 | }
14 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/WrongGraphColoringException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Exception that occurs when graph coloring is invalid(two adjacent edges have same color)
6 | ///
7 | public class WrongGraphColoringException : Exception
8 | {
9 | ///
10 | public WrongGraphColoringException(string message) : base(message)
11 | {
12 |
13 | }
14 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/GraphDataIntegrityException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Exceptions;
3 |
4 | ///
5 | /// Occurs when there is inconsistency in nodes and / or edges in a graph.
6 | /// When graph's internal structure is invalid.
7 | ///
8 | public class GraphDataIntegrityException : Exception
9 | {
10 | ///
11 | public GraphDataIntegrityException(string message) : base(message)
12 | {
13 | }
14 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.project
6 | **/.settings
7 | **/.toolstarget
8 | **/.vs
9 | **/.vscode
10 | **/*.*proj.user
11 | **/*.dbmdl
12 | **/*.jfm
13 | **/azds.yaml
14 | **/bin
15 | **/charts
16 | **/docker-compose*
17 | **/compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | **/publish
25 | **/log.txt
26 | **/*.jpg
27 | README.md
28 |
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/MakeDirected.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Randomly makes every connection between two nodes directed.
10 | ///
11 | public GraphOperation MakeDirected()
12 | {
13 | Edges.MakeDirected();
14 | return this;
15 | }
16 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/WrongNodeSetException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace GraphSharp.Exceptions;
7 | ///
8 | /// Occurs when node id not equals to index that used to store it.
9 | ///
10 | public class WrongNodeSetException : Exception
11 | {
12 | ///
13 | public WrongNodeSetException(string msg) : base(msg)
14 | {
15 |
16 | }
17 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/helpers/NodeEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 |
5 | namespace GraphSharp.Tests.Helpers
6 | {
7 | public class NodeEqualityComparer : IEqualityComparer
8 | {
9 | public bool Equals(INode x, INode y)
10 | {
11 | return x.Id==y.Id;
12 | }
13 |
14 | public int GetHashCode([DisallowNull] INode obj)
15 | {
16 | return obj.Id;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/RemoveNodes.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Graphs;
2 |
3 | public partial class GraphOperation
4 | where TNode : INode
5 | where TEdge : IEdge
6 | {
7 | ///
8 | /// Isolate and removes specified nodes
9 | ///
10 | public GraphOperation RemoveNodes(params int[] nodes)
11 | {
12 | Isolate(nodes);
13 |
14 | foreach (var n in nodes)
15 | {
16 | Nodes.Remove(n);
17 | }
18 |
19 | return this;
20 | }
21 | }
--------------------------------------------------------------------------------
/GraphSharp/Nodes/NodeComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | namespace GraphSharp;
4 |
5 | ///
6 | /// Node comparer that uses to compare two nodes.
7 | ///
8 | public class NodeComparer : IComparer
9 | where TNode : INode
10 | {
11 | ///
12 | public int Compare(TNode? x, TNode? y)
13 | {
14 | if (x is null || y is null) throw new NullReferenceException("Cannot compare nodes that null!");
15 | return x.CompareTo(y);
16 | }
17 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/Common.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace GraphSharp.Tests;
7 | public static class Common
8 | {
9 | public static void Shuffle(this IList list, Random rng = null)
10 | {
11 | rng ??= new Random();
12 | int n = list.Count;
13 | while (n > 1)
14 | {
15 | n--;
16 | int k = rng.Next(n + 1);
17 | T value = list[k];
18 | list[k] = list[n];
19 | list[n] = value;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/MakeUndirected.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Makes every connection between two nodes bidirectional by adding missing edges.
10 | ///
11 | public GraphOperation MakeBidirected(Action? onCreatedEdge = null)
12 | {
13 | Edges.MakeBidirected((a,b)=>Configuration.CreateEdge(Nodes[a],Nodes[b]),onCreatedEdge);
14 | return this;
15 | }
16 | }
--------------------------------------------------------------------------------
/GraphSharp/Edges/EdgeComparer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | namespace GraphSharp;
4 |
5 | ///
6 | /// Edge comparer that uses to compare two edges
7 | ///
8 | public class EdgeComparer : IComparer
9 | where TNode : INode
10 | where TEdge : IEdge
11 | {
12 | ///
13 | public int Compare(TEdge? x, TEdge? y)
14 | {
15 | if (x is null || y is null) throw new NullReferenceException("Cannot compare null edges!");
16 | return x.CompareTo(y);
17 | }
18 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Implementations/UnmanagedColor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace GraphSharp;
8 | ///
9 | /// Unmanaged ARGB color structure
10 | ///
11 | public struct UnmanagedColor
12 | {
13 | ///
14 | /// Corresponding color element
15 | ///
16 | public byte A,R,G,B;
17 | ///
18 | /// Color converter
19 | ///
20 | public static explicit operator Color(UnmanagedColor c) => Color.FromArgb(c.A,c.R,c.G,c.B);
21 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IForest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace GraphSharp.Common;
4 |
5 | ///
6 | /// Forest interface
7 | ///
8 | public interface IForest{
9 | ///
10 | /// Determine whatever given two nodes in same component
11 | ///
12 | public bool InSameComponent(int nodeId1, int nodeId2);
13 | ///
14 | /// Edges of forest
15 | ///
16 | IEnumerable Forest{get;}
17 | /// Degree of given node in a forest, or -1 if not found
18 | public int Degree(int nodeId);
19 |
20 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/LineGraph.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using GraphSharp.Common;
3 |
4 | namespace GraphSharp.Graphs;
5 |
6 | public partial class ImmutableGraphOperation
7 | where TNode : INode
8 | where TEdge : IEdge
9 | {
10 | ///
11 | /// Builds line graph out of current graph.
12 | /// Line graph is a graph, where edges became nodes and two nodes connected if
13 | /// their underlying edges have a common node.
14 | ///
15 | public LineGraph LineGraph()
16 | {
17 | return new LineGraph(StructureBase);
18 | }
19 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/Operations/BaseTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using GraphSharp.Graphs;
7 | using GraphSharp.Tests.Models;
8 | using MathNet.Numerics.LinearAlgebra.Single;
9 | using Xunit;
10 |
11 | namespace GraphSharp.Tests.Operations
12 | {
13 | public class BaseTest
14 | {
15 |
16 | public IGraph _Graph;
17 |
18 | public BaseTest()
19 | {
20 | this._Graph = new Graph(new TestGraphConfiguration(new Random()));
21 | _Graph.Do.CreateNodes(1000);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/GraphSharp/Exceptions/NotLineGraphException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | namespace GraphSharp.Exceptions;
6 |
7 | ///
8 | /// Exception that occurs when some graph needs to be line graph for execution of algorithm,
9 | /// but given graph is not a line graph
10 | ///
11 | public class NotLineGraphException : Exception
12 | {
13 | ///
14 | ///
15 | public NotLineGraphException() : base("Given graph is not a line graph")
16 | {
17 | }
18 | ///
19 | ///
20 | public NotLineGraphException(string msg) : base(msg){}
21 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/Models/TestGraphConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 |
4 | using GraphSharp.Graphs;
5 | using MathNet.Numerics.LinearAlgebra.Single;
6 |
7 | namespace GraphSharp.Tests.Models
8 | {
9 | public class TestGraphConfiguration : GraphConfiguration
10 | {
11 | public TestGraphConfiguration(Random rand) :
12 | base(
13 | rand ?? new Random(),
14 | (n1,n2)=>new Edge(n1,n2){Weight=(n1.MapProperties().Position-n2.MapProperties().Position).L2Norm()},
15 | id=> new Node(id).With(p=>p.Position = DenseVector.Create(2,i=>rand.NextSingle())))
16 | {}
17 | }
18 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/RemoveIsolatedNodes.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Removes isolated nodes
10 | ///
11 | public GraphOperation RemoveIsolatedNodes()
12 | {
13 | var toRemove =
14 | Nodes
15 | .Where(x => Edges.IsIsolated(x.Id))
16 | .Select(x => x.Id)
17 | .ToArray();
18 |
19 | foreach (var n in toRemove)
20 | {
21 | Nodes.Remove(n);
22 | }
23 |
24 | return this;
25 | }
26 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ReverseEdges.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Reverse every edge connection ==> like swap(edge.Source,edge.Target)
10 | ///
11 | public GraphOperation ReverseEdges()
12 | {
13 | foreach (var e in Edges.ToList())
14 | {
15 | Edges.Remove(e);
16 | var tmp = e.SourceId;
17 | e.SourceId = e.TargetId;
18 | e.TargetId = tmp;
19 | Edges.Add(e);
20 | }
21 | return this;
22 | }
23 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/CreateNodes.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Graphs;
2 |
3 | public partial class GraphOperation
4 | where TNode : INode
5 | where TEdge : IEdge
6 | {
7 | ///
8 | /// Clears graph and creates some count of nodes.
9 | ///
10 | /// Count of nodes to create
11 | public GraphOperation CreateNodes(int nodesCount)
12 | {
13 | this.StructureBase.Clear();
14 | //create nodes
15 | for (int i = 0; i < nodesCount; i++)
16 | {
17 | var node = Configuration.CreateNode(i);
18 | Nodes.Add(node);
19 | }
20 | return this;
21 | }
22 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/RemoveEdges.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | namespace GraphSharp.Graphs;
4 |
5 | public partial class GraphOperation
6 | where TNode : INode
7 | where TEdge : IEdge
8 | {
9 | ///
10 | /// Removes all edges that satisfies predicate.
11 | ///
12 | public GraphOperation RemoveEdges(Predicate toRemove)
13 | {
14 | var edgesToRemove =
15 | Edges.Where(x => toRemove(x))
16 | .Select(x => (x.SourceId, x.TargetId))
17 | .ToArray();
18 |
19 | foreach (var e in edgesToRemove)
20 | Edges.Remove(e.Item1, e.Item2);
21 |
22 | return this;
23 | }
24 | }
--------------------------------------------------------------------------------
/GraphSharp/Visitors/Interfaces/IVisitorWithSteps.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Visitors;
2 | ///
3 | /// Visitor that counts it's steps and completion state
4 | ///
5 | public interface IVisitorWithSteps : IVisitor
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Indicates if algorithm is done and do not need any further executions
10 | ///
11 | bool Done {get;}
12 | ///
13 | /// Count of how many steps executed so far
14 | ///
15 | ///
16 | int Steps{get;}
17 | ///
18 | /// Whatever given algorithm did anything in last iteration
19 | ///
20 | public bool DidSomething{get;set;}
21 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/FindLowLinkValues.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using GraphSharp.Common;
3 | using Unchase.Satsuma.Core.Extensions;
4 |
5 | namespace GraphSharp.Graphs;
6 |
7 | public partial class ImmutableGraphOperation
8 | where TNode : INode
9 | where TEdge : IEdge
10 | {
11 | ///
12 | /// Finds low link values for nodes. Can be used to get strongly connected components
13 | ///
14 | /// Array where index is node id and value is low link value. When value is -1 it means that there is not node with given index.
15 | public RentedArray FindLowLinkValues()
16 | {
17 | return new LowLinkValuesFinder(Nodes.Cast(),Edges).FindLowLinkValues();
18 | }
19 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/RemoveUndirectedEdges.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Removes bidirected edges.
10 | ///
11 | public GraphOperation RemoveBidirectedEdges()
12 | {
13 | foreach (var n in Nodes)
14 | {
15 | var edges = Edges.OutEdges(n.Id).ToArray();
16 | foreach (var edge in edges)
17 | {
18 | if (Edges.Remove(edge.TargetId, edge.SourceId))
19 | {
20 | Edges.Remove(edge);
21 | }
22 | }
23 | }
24 | return this;
25 | }
26 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Implementations/DefaultGraph.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Graphs;
3 |
4 | ///
5 | /// Default graph implementation. Uses and as node and edge types
6 | ///
7 | public class Graph : Graph
8 | {
9 | ///
10 | /// Initialize new graph
11 | ///
12 | public Graph() : base(id => new(id), (n1, n2) => new(n1, n2))
13 | {
14 | }
15 | ///
16 | /// Initialize new graph
17 | ///
18 | /// How to create node
19 | /// How to create edge
20 | public Graph(Func createNode, Func createEdge) : base(createNode, createEdge)
21 | {
22 |
23 | }
24 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/GetComplement.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace GraphSharp.Graphs;
5 |
6 | public partial class ImmutableGraphOperation
7 | where TNode : INode
8 | where TEdge : IEdge
9 | {
10 | ///
11 | /// Computes graph complement(including self-edges)
12 | ///
13 | public IList GetComplement(){
14 | var n = Nodes.Count();
15 | var result = new List(n*(n-1));
16 | foreach(var n1 in Nodes){
17 | foreach(var n2 in Nodes){
18 | if(Edges.Contains(n1.Id,n2.Id)) continue;
19 | var toAdd = Configuration.CreateEdge(n1,n2);
20 | result.Add(toAdd);
21 | }
22 | }
23 | return result;
24 | }
25 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ConnectAsHamiltonianCycle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using MathNet.Numerics.LinearAlgebra.Single;
4 |
5 | namespace GraphSharp.Graphs;
6 |
7 | public partial class GraphOperation
8 | where TNode : INode
9 | where TEdge : IEdge
10 | {
11 | ///
12 | /// Connects graph nodes as hamiltonian cycle
13 | ///
14 | public GraphOperation ConnectAsHamiltonianCycle(Func getPos)
15 | {
16 | var tsp = TspCheapestLinkOnPositions(getPos);
17 | tsp = TspSmallRandomOpt2(tsp.Tour,tsp.TourCost,(n1,n2)=>(getPos(n1)-getPos(n2)).L2Norm());
18 | tsp.Tour.Aggregate((n1,n2)=>{
19 | Edges.Add(Configuration.CreateEdge(n1,n2));
20 | return n2;
21 | }).ToString();
22 | return this;
23 | }
24 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ConnectNodes.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Randomly create edgesCount of edges for each node.
10 | ///
11 | /// How much edges each node need
12 | public GraphOperation ConnectNodes(int edgesCount)
13 | {
14 | var availableNodes = Nodes.Select(x => x.Id).ToList();
15 | edgesCount = edgesCount > Nodes.Count ? Nodes.Count : edgesCount;
16 |
17 | foreach (var node in Nodes)
18 | {
19 | int startIndex = Configuration.Rand.Next(availableNodes.Count);
20 | ConnectNodeToNodes(node, startIndex, edgesCount, availableNodes);
21 | }
22 | return this;
23 | }
24 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/Induce.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using GraphSharp.Common;
4 |
5 | namespace GraphSharp.Graphs;
6 |
7 | public partial class ImmutableGraphOperation
8 | where TNode : INode
9 | where TEdge : IEdge
10 | {
11 | ///
12 | /// Get induced subgraph from this graph structure.
13 | /// Induced graph is a subgraph of graph such that all edges connecting any pair of nodes from subgraph also in subgraph
14 | ///
15 | /// Nodes to induce
16 | /// Induced subgraph of current graph
17 | public Graph Induce(IEnumerable nodes){
18 | var result = new Graph(Configuration);
19 | result.SetSources(nodes: nodes.Select(id=>Nodes[id]),edges:Edges.InducedEdges(nodes));
20 | return result;
21 | }
22 | }
--------------------------------------------------------------------------------
/SimplestExample/SimplestExample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 | Always
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/Coloring/GreedyColoring.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | ///
5 | /// Linear-time greedy graph nodes coloring algorithm.
6 | ///
7 | public class GreedyColoring : ColoringAlgorithmBase
8 | where TNode : INode
9 | where TEdge : IEdge
10 | {
11 | ///
12 | public GreedyColoring(IImmutableNodeSource nodes, IImmutableEdgeSource edges) : base(nodes, edges)
13 | {
14 | }
15 | ///
16 | public override ColoringResult Color()
17 | {
18 | var order = Nodes.OrderBy(x => -Edges.Neighbors(x.Id).Count());
19 | // var order = Nodes;
20 |
21 | var colors = ArrayPoolStorage.RentArray(Nodes.MaxNodeId + 1);
22 |
23 | foreach (var n in order)
24 | {
25 | AssignColor(n.Id, colors);
26 | }
27 |
28 | return new(colors);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/INodeSource.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Graphs;
3 | ///
4 | /// Node source.
5 | ///
6 | public interface INodeSource : IImmutableNodeSource, ICollection
7 | {
8 | ///
9 | /// Removes node by it's id
10 | ///
11 | /// True if removed, else false
12 | bool Remove(int nodeId);
13 | ///
14 | /// Get node by it's id. Assign node by id
15 | ///
16 | new TNode this[int nodeId] { get; set; }
17 | ///
18 | /// Changes node Id by moving it
19 | ///
20 | /// True if moved successfully, else false
21 | bool Move(TNode node, int newId);
22 | ///
23 | /// Changes node Id by moving it
24 | ///
25 | /// true if moved successfully, else false
26 | bool Move(int nodeId, int newId);
27 | }
--------------------------------------------------------------------------------
/GraphSharp.GoogleOrTools/GraphSharp.GoogleOrTools.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | enable
13 | true
14 | Library
15 | net6.0
16 | MIT
17 | 3.1.3
18 | Kemsekov.GraphSharp.GoogleOrTools
19 | True
20 | $(Version)
21 | Kemsekov
22 | https://github.com/Kemsekov/GraphSharp
23 | 6
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/GraphSharp/Nodes/INode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using GraphSharp.Common;
5 | namespace GraphSharp;
6 |
7 | ///
8 | /// Node interface. Each node used with graph and must be inherited from this interface.
9 | ///
10 | public interface INode : IComparable, ICloneable, System.IEquatable
11 | {
12 | ///
13 | /// Get or set node property
14 | ///
15 | object this[string propertyName]{get;set;}
16 | ///
17 | /// Node properties
18 | ///
19 | IDictionary Properties { get; }
20 | ///
21 | /// Unique identifier for node
22 | ///
23 | int Id { get; set; }
24 | int IComparable.CompareTo(INode? other)
25 | {
26 | other = other ?? throw new NullReferenceException("Cannot compare node that is null");
27 | return Id - other.Id;
28 | }
29 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ConnectNodeToNodes.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Create some count of random edges for given node. Help function
10 | ///
11 | private void ConnectNodeToNodes(TNode node, int startIndex, int edgesCount, IList source)
12 | {
13 | lock (node)
14 | for (int i = 0; i < edgesCount; i++)
15 | {
16 | int index = (startIndex + i) % source.Count;
17 | var targetId = source[index];
18 | if (node.Id == targetId)
19 | {
20 | startIndex++;
21 | i--;
22 | continue;
23 | }
24 | var target = Nodes[targetId];
25 |
26 | Edges.Add(Configuration.CreateEdge(node, target));
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/Isolate.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using GraphSharp.Common;
3 |
4 | namespace GraphSharp.Graphs;
5 |
6 | public partial class GraphOperation
7 | where TNode : INode
8 | where TEdge : IEdge
9 | {
10 | ///
11 | /// Isolates nodes. Removes all incoming and outcoming edges from each node that satisfies predicate. It is faster to pass many nodes in single call of this function than make many calls of this function on each node.
12 | ///
13 | public GraphOperation Isolate(params int[] nodes)
14 | {
15 | using var toIsolate = ArrayPoolStorage.RentArray(Nodes.MaxNodeId + 1);
16 | foreach (var n in nodes)
17 | toIsolate[n] = 1;
18 | var toRemove =
19 | Edges.Where(x => toIsolate[x.SourceId] == 1 || toIsolate[x.TargetId] == 1)
20 | .ToArray();
21 |
22 | foreach (var e in toRemove)
23 | {
24 | Edges.Remove(e);
25 | }
26 | return this;
27 | }
28 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/IndependentSetFinder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GraphSharp.Graphs;
4 |
5 | public partial class ImmutableGraphOperation
6 | where TNode : INode
7 | where TEdge : IEdge
8 | {
9 | ///
10 | /// Finds maximal independent set.
11 | /// Altered implementation of this algorithm:
12 | ///
13 | ///
14 | /// You may need to find independent set from some subset of nodes. Use this to control it.
15 | /// Only nodes that pass a condition can be added to independent set
16 | ///
17 | /// Nodes from maximal independent set
18 | public IndependentSetResult FindMaximalIndependentSet(Predicate condition)
19 | {
20 | using var alg = new BallardMyerIndependentSet(Nodes,Edges,condition);
21 | var result = alg.Find();
22 | return result;
23 | }
24 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/IEdgeSource.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Graphs;
3 |
4 | ///
5 | /// Represents edges storage object
6 | ///
7 | public interface IEdgeSource : IImmutableEdgeSource, ICollection
8 | {
9 | ///
10 | /// Removes all edges that equals to by default .
11 | /// This method of removal allows to remove some of parallel edges, which
12 | /// are not equal to each other.
13 | /// Meanwhile other Remove methods will remove all parallel edges.
14 | ///
15 | new bool Remove(TEdge edge);
16 | bool ICollection.Remove(TEdge item) => Remove(item);
17 | ///
18 | /// Removes all edges that directs sourceId -> targetId (including parallel edges)
19 | ///
20 | bool Remove(int sourceId, int targetId);
21 | ///
22 | /// Clears a memory from empty(unused) edges
23 | ///
24 | void Trim();
25 | }
--------------------------------------------------------------------------------
/GraphSharp/Propagators/Interfaces/IPropagator.cs:
--------------------------------------------------------------------------------
1 |
2 | using GraphSharp.Graphs;
3 | using GraphSharp.Visitors;
4 | namespace GraphSharp.Propagators;
5 |
6 | ///
7 | /// Algorithm that uses to do graph exploration and modification
8 | /// in a specific way designed by implementations
9 | ///
10 | public interface IPropagator
11 | where TEdge : IEdge
12 | {
13 | ///
14 | /// Will push forward (deeper) in a graph execution of an algorithm
15 | ///
16 | void Propagate();
17 | ///
18 | /// Change current propagator visit position.
19 | /// Assigns to given nodes state to be visited in next iteration.
20 | ///
21 | void SetPosition(params int[] nodeIndices);
22 | ///
23 | /// Sets new graph edges and visitor.
24 | /// Clears all node states for current propagator and resets them to default settings.
25 | ///
26 | void Reset(IImmutableEdgeSource edges, IVisitor visitor, int maxNodeId = -1);
27 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphDrawer/IShapeDrawer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using MathNet.Numerics.LinearAlgebra.Single;
5 |
6 | namespace GraphSharp.GraphDrawer;
7 |
8 | ///
9 | /// Interface for basic drawing operations.
10 | ///
11 | public interface IShapeDrawer
12 | {
13 | ///
14 | /// Draws text on given position, with given size and color
15 | ///
16 | void DrawText(string text, Vector position, Color color, double size);
17 | ///
18 | /// Fills ellipse on given position, with given with and height and color
19 | ///
20 | void FillEllipse(Vector position, double width, double height, Color color);
21 | ///
22 | /// Draws a line between two points with given thickness and color
23 | ///
24 | void DrawLine(Vector start, Vector end, Color color, double thickness);
25 | ///
26 | /// Clears whole window with
27 | ///
28 | void Clear(Color color);
29 | }
--------------------------------------------------------------------------------
/GraphSharp/Propagators/BaseClasses/UsedNodeStates.cs:
--------------------------------------------------------------------------------
1 | using GraphSharp.Propagators;
2 |
3 | namespace GraphSharp.Common;
4 | ///
5 | /// Contains all states used by
6 | ///
7 | public struct UsedNodeStates
8 | {
9 | ///
10 | /// None state for node.
11 | ///
12 | public const byte None = 0;
13 | ///
14 | /// In this state node is in check for visit in next iteration of any algorithm
15 | ///
16 | public const byte ToVisit = 1;
17 | ///
18 | /// In this state node is required to visit for current iteration
19 | ///
20 | public const byte Visited = 2;
21 | ///
22 | /// In this state on each iteration "in edges" of node is chosen as next generation
23 | ///
24 | public const byte IterateByInEdges = 4;
25 | ///
26 | /// In this state on each iteration "out edges" of node is chosen as next generation
27 | ///
28 | public const byte IterateByOutEdges = 8;
29 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/Models/TestVisitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using GraphSharp.Common;
6 | using GraphSharp.Graphs;
7 |
8 | using GraphSharp.Propagators;
9 | using GraphSharp.Visitors;
10 |
11 | namespace GraphSharp.Tests.Models
12 | {
13 | public class TestVisitor : VisitorWithPropagator
14 | {
15 |
16 | public override PropagatorBase Propagator{get;}
17 | public TestVisitor(IGraph graph)
18 | {
19 | this.Propagator = new ParallelPropagator(graph.Edges,this,graph.Nodes.MaxNodeId);
20 | }
21 |
22 | protected override void StartImpl()
23 | {
24 | }
25 |
26 | protected override bool SelectImpl(EdgeSelect edge)
27 | {
28 | return true;
29 | }
30 |
31 | protected override void VisitImpl(int node)
32 | {
33 | }
34 |
35 | protected override void EndImpl()
36 | {
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/TopologicalSort.cs:
--------------------------------------------------------------------------------
1 | using GraphSharp.Visitors;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class ImmutableGraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Do topological sort on the graph.
10 | ///
11 | /// Points that will be starting points for topological sort. If empty will assign them to a sources nodes. If will not find sources nodes then will throw.
12 | /// Object that contains List of layers where each layer is a list of nodes at a certain layer of topological sort.
13 | /// Use to change X coordinates to a certain value defined by sorting.
14 | public TopologicalSorter TopologicalSort(params int[] startNodes)
15 | {
16 | var alg = new TopologicalSorter(StructureBase,startNodes);
17 | while (!alg.Done)
18 | {
19 | alg.Propagate();
20 | }
21 | return alg;
22 | }
23 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/IImmutableNodeSource.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Graphs;
3 | ///
4 | /// Immutable nodes source
5 | ///
6 | public interface IImmutableNodeSource : IEnumerable
7 | {
8 | ///
9 | /// Max id value of all nodes. If there is no nodes, returns -1.
10 | ///
11 | int MaxNodeId { get; }
12 | ///
13 | /// Min id value of all nodes. If there is no nodes, returns -1.
14 | ///
15 | int MinNodeId { get; }
16 | ///
17 | /// Get node by it's id. Assign node by id
18 | ///
19 | TNode this[int nodeId] { get; }
20 | ///
21 | /// Tries to get node by it's id
22 | ///
23 | /// Node id
24 | /// Retrieved node
25 | /// True if found, else false
26 | bool TryGetNode(int nodeId, out TNode? node);
27 | /// True if found node with given id, else false
28 | bool Contains(int nodeId);
29 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Implementations/PrimForest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using GraphSharp.Graphs;
4 |
5 | namespace GraphSharp.Common;
6 |
7 | ///
8 | /// Prim's algorithm result
9 | ///
10 | public class PrimForest : IForest
11 | where TEdge : IEdge
12 | {
13 | Lazy> Components;
14 |
15 | IEdgeSource EdgeSource { get; }
16 | ///
17 | /// Creates new PrimForest instance
18 | ///
19 | public PrimForest(IEdgeSource edges, Func> getComponents)
20 | {
21 | Components = new(getComponents);
22 | this.EdgeSource = edges;
23 | }
24 | ///
25 | public IEnumerable Forest => EdgeSource;
26 | ///
27 |
28 | public int Degree(int nodeId)
29 | {
30 | return EdgeSource.Degree(nodeId);
31 | }
32 | ///
33 |
34 | public bool InSameComponent(int nodeId1, int nodeId2)
35 | {
36 | return Components.Value.InSameComponent(nodeId1,nodeId2);
37 | }
38 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/Coloring/QuickGraphColoring.cs:
--------------------------------------------------------------------------------
1 | using GraphSharp.Adapters;
2 | using QuikGraph.Algorithms.VertexColoring;
3 | namespace GraphSharp.Graphs;
4 |
5 | ///
6 | /// QuikGraph's coloring algorithm
7 | ///
8 | public class QuickGraphColoring : ColoringAlgorithmBase
9 | where TNode : INode
10 | where TEdge : IEdge
11 | {
12 | ///
13 | public QuickGraphColoring(IImmutableNodeSource nodes, IImmutableEdgeSource edges) : base(nodes, edges)
14 | {
15 | }
16 | ///
17 | public override ColoringResult Color()
18 | {
19 |
20 | var quikGraph = new ToQuikGraphAdapter(Nodes, Edges);
21 | var coloring = new VertexColoringAlgorithm>(quikGraph);
22 | coloring.Compute();
23 | var result = ArrayPoolStorage.RentArray(Nodes.MaxNodeId + 1);
24 | for (int i = 0; i < result.Length; i++)
25 | {
26 | if (coloring.Colors[i] is int color)
27 | result[i] = color;
28 | }
29 | return new(result);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/GraphSharp/Visitors/Interfaces/IVisitor{TNode,TEdge}.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Visitors;
2 | ///
3 | /// Contains method to control execution of algorithms on a graph.
4 | ///
5 | public interface IVisitor
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// First function to call in each algorithm step.
10 | ///
11 | void Start();
12 | ///
13 | /// Method to process and filter edges that will be passed forward for execution
14 | ///
15 | /// Edge to process
16 | /// True if we need to step into given edge, else false
17 | bool Select(EdgeSelect edge);
18 | ///
19 | /// Method to process nodes that was passed by selected edges.
20 | ///
21 | /// Node id to process
22 | void Visit(int node);
23 | ///
24 | /// After each select and visit iterations are done this method will do clean-up
25 | /// or states changes or any specific task at the end of algorithm step
26 | ///
27 | void End();
28 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/DistanceMatrix.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using MathNet.Numerics.LinearAlgebra.Single;
6 | using QuikGraph;
7 |
8 | namespace GraphSharp.Graphs;
9 |
10 | public partial class ImmutableGraphOperation
11 | where TNode : INode
12 | where TEdge : IEdge
13 | {
14 | ///
15 | /// Computes distance matrix from graph nodes, using distance metric.
16 | ///
17 | /// How to compute distances between nodes
18 | /// Matrix where each (i,j) element corresponds to distance between node under index i and node under index j
19 | public T[,] DistanceMatrix(Func distance)
20 | {
21 | var nodes = Nodes.ToList();
22 | var distances = new T[Nodes.MaxNodeId+1,Nodes.MaxNodeId+1];
23 | Parallel.ForEach(nodes,n1=>{
24 | foreach(var n2 in nodes){
25 | distances[n1.Id,n2.Id]=distance(n1,n2);
26 | }
27 | });
28 | return distances;
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Vlad Kemsekov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IPath.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace GraphSharp.Common;
7 | ///
8 | /// Path finding algorithm result
9 | ///
10 | public interface IPath : IList
11 | {
12 | ///
13 | /// Type of path. Can be directed or undirected. Also directness can be defined on out edges or on in edges.
14 | ///
15 | PathType PathType{get;}
16 | ///
17 | /// A list of nodes, which order defines a path
18 | ///
19 | IList Path{get;}
20 | ///
21 | /// Path cost
22 | ///
23 | double Cost{get;}
24 | }
25 |
26 | ///
27 | /// Path finder
28 | ///
29 | public interface IPathFinder{
30 | ///
31 | /// Type of path. Can be directed or undirected. Also directness can be defined on out edges or on in edges.
32 | ///
33 | PathType PathType{get;}
34 | /// Path between two given nodes
35 | IPath GetPath(int node1, int node2);
36 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/GraphSharp.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | false
5 |
6 |
7 |
8 |
9 |
10 | runtime; build; native; contentfiles; analyzers; buildtransitive
11 | all
12 |
13 |
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 | all
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/GraphSharp/Edges/IEdge.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using GraphSharp.Common;
5 | using GraphSharp.Extensions;
6 | namespace GraphSharp;
7 |
8 | ///
9 | /// Interface for all edges.
10 | ///
11 | public interface IEdge : IComparable, ICloneable
12 | {
13 | ///
14 | /// Get or set edge property
15 | ///
16 | object this[string propertyName]{get;set;}
17 | ///
18 | /// Edge properties
19 | ///
20 | IDictionary Properties{get;}
21 | ///
22 | /// Id of a source node of this edge
23 | ///
24 | int SourceId { get; set; }
25 | ///
26 | /// Id of a target node of this edge
27 | ///
28 | int TargetId { get; set; }
29 | int IComparable.CompareTo(IEdge? other)
30 | {
31 | if (other is null)
32 | return 1;
33 | var d1 = SourceId - other.SourceId;
34 | var d2 = TargetId - other.TargetId;
35 | if (d1 == 0) return d2;
36 | return d1;
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/FindComponents.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using GraphSharp.Common;
4 | namespace GraphSharp.Graphs;
5 |
6 | public partial class ImmutableGraphOperation
7 | where TNode : INode
8 | where TEdge : IEdge
9 | {
10 | ///
11 | /// Finds all unconnected components of a graph
12 | ///
13 | /// Class that can be used to get components and determine of two nodes in the same component
14 | public ComponentsResult FindComponents()
15 | {
16 | UnionFind u = new(Nodes.MaxNodeId + 1);
17 | foreach (var n in Nodes)
18 | u.MakeSet(n.Id);
19 | foreach (var e in Edges)
20 | u.UnionSet(e.SourceId, e.TargetId);
21 |
22 | var result = new Dictionary>(u.SetsCount+1);
23 | foreach(var n in Nodes){
24 | var set = u.FindSet(n.Id);
25 | if(result.TryGetValue(set,out var list))
26 | list.Add(n);
27 | else
28 | result[set] = new List(){n};
29 | }
30 | return new (result.Values.ToArray(), u);
31 | }
32 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphSharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.002.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphSharp", "GraphSharp.csproj", "{541C0104-983B-4C24-8CF2-37463FAEB025}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {541C0104-983B-4C24-8CF2-37463FAEB025}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {541C0104-983B-4C24-8CF2-37463FAEB025}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {541C0104-983B-4C24-8CF2-37463FAEB025}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {541C0104-983B-4C24-8CF2-37463FAEB025}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {3B6739B5-FCE9-4708-BEAC-4238661BDFA2}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/GraphSharp/Propagators/Implementations/Propagator.cs:
--------------------------------------------------------------------------------
1 | using GraphSharp.Common;
2 | using GraphSharp.Graphs;
3 | using GraphSharp.Visitors;
4 | namespace GraphSharp.Propagators;
5 |
6 | ///
7 | /// Single threaded implementation.
8 | ///
9 | ///
10 | public class Propagator : PropagatorBase
11 | where TEdge : IEdge
12 | {
13 | ///
14 | public Propagator(IImmutableEdgeSource edges,IVisitor visitor, int maxNodeId = -1) : base(edges, visitor,maxNodeId)
15 | {
16 | }
17 | ///
18 | protected override void PropagateNodes()
19 | {
20 | byte state = 0;
21 | for (int nodeId = 0; nodeId < NodeStates.Length; ++nodeId)
22 | {
23 | state = NodeStates.GetState(nodeId);
24 | if (ByteStatesHandler.IsInState(UsedNodeStates.ToVisit,state))
25 | PropagateNode(nodeId,state);
26 | };
27 | for (int nodeId = 0; nodeId < NodeStates.Length; ++nodeId)
28 | {
29 | if (NodeStates.IsInState(UsedNodeStates.Visited,nodeId))
30 | Visitor.Visit(nodeId);
31 | };
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Implementations/GraphStructureOperation.cs:
--------------------------------------------------------------------------------
1 | using GraphSharp.Common;
2 | using GraphSharp.Propagators;
3 | using GraphSharp.Visitors;
4 |
5 | namespace GraphSharp.Graphs;
6 |
7 | ///
8 | /// Contains graph algorithms.
9 | ///
10 | public partial class GraphOperation : ImmutableGraphOperation
11 | where TNode : INode
12 | where TEdge : IEdge
13 | {
14 | ///
15 | /// Source graph
16 | ///
17 | public new IGraph StructureBase{get;}
18 | ///
19 | /// Graph nodes
20 | ///
21 | public new INodeSource Nodes => StructureBase.Nodes;
22 | ///
23 | /// Graph edges
24 | ///
25 | public new IEdgeSource Edges => StructureBase.Edges;
26 | ///
27 | /// Graph configuration
28 | ///
29 | public new IGraphConfiguration Configuration => StructureBase.Configuration;
30 | ///
31 | public GraphOperation(IGraph structureBase) : base(structureBase)
32 | {
33 | StructureBase = structureBase;
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/IGraphConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace GraphSharp.Graphs;
3 |
4 | ///
5 | /// A set of methods and properties that used in graph
6 | ///
7 | public interface IGraphConfiguration
8 | {
9 | ///
10 | /// that used to implement's any logic when some algorithm requires random values
11 | ///
12 | public Random Rand { get; set; }
13 | ///
14 | /// Creates a edges source that works as storage for edges
15 | ///
16 | IEdgeSource CreateEdgeSource();
17 | ///
18 | /// Creates a nodes source that works as storage for nodes
19 | ///
20 | INodeSource CreateNodeSource();
21 | ///
22 | /// Method that used to create instance of from it's as argument
23 | ///
24 | TNode CreateNode(int nodeId);
25 | ///
26 | /// Method that used to create new from two nodes of type
27 | ///
28 | TEdge CreateEdge(TNode source, TNode target);
29 | }
--------------------------------------------------------------------------------
/GraphSharp.Tests/GraphSharp.Tests.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.002.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphSharp.Tests", "GraphSharp.Tests.csproj", "{AB5FF099-EA61-428E-A5A1-0C782330619C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {AB5FF099-EA61-428E-A5A1-0C782330619C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {AB5FF099-EA61-428E-A5A1-0C782330619C}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {AB5FF099-EA61-428E-A5A1-0C782330619C}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {AB5FF099-EA61-428E-A5A1-0C782330619C}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {3653BAF8-2702-4652-A304-A853B174EB58}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/IImmutableGraph.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace GraphSharp.Graphs;
7 | ///
8 | /// Immutable graph
9 | ///
10 | public interface IImmutableGraph
11 | where TNode : INode
12 | where TEdge : IEdge
13 | {
14 | ///
15 | /// Graph nodes
16 | ///
17 | IImmutableNodeSource Nodes { get; }
18 | ///
19 | /// Graph edges
20 | ///
21 | IImmutableEdgeSource Edges { get; }
22 | ///
23 | /// Graph configuration
24 | ///
25 | IGraphConfiguration Configuration { get; }
26 | ///
27 | /// Graph operations object that required to perform operations on a graph. Contains a lot of methods to do various tasks.
28 | ///
29 | ImmutableGraphOperation Do { get; }
30 | ///
31 | /// Graph converter. If you need to convert current graph to different representations or initialize current graph from different representations then look at this objects methods.
32 | ///
33 | ImmutableGraphConverters Converter { get; }
34 | }
--------------------------------------------------------------------------------
/GraphSharp/Adapters/EdgeAdapter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GraphSharp.Graphs;
3 |
4 | namespace GraphSharp.Adapters;
5 |
6 | ///
7 | /// Adapter for edges from GraphSharp to work as edges from QuikGraph
8 | ///
9 | public struct EdgeAdapter : QuikGraph.IEdge, QuikGraph.IUndirectedEdge
10 | where TEdge : IEdge
11 | {
12 | ///
13 | public int Source => GraphSharpEdge.SourceId;
14 | ///
15 | public int Target => GraphSharpEdge.TargetId;
16 | ///
17 | /// Original GraphSharp's edge
18 | ///
19 | public TEdge GraphSharpEdge { get; }
20 | ///
21 | /// Creates a new edge adapter out of GraphSharp edge
22 | ///
23 | ///
24 | public EdgeAdapter(TEdge edge)
25 | {
26 | GraphSharpEdge = edge;
27 | }
28 | ///
29 | public override bool Equals(object? obj)
30 | {
31 | if (obj is EdgeAdapter e)
32 | {
33 | return e.GraphSharpEdge.Equals(GraphSharpEdge);
34 | }
35 | return base.Equals(obj);
36 | }
37 | ///
38 | public override int GetHashCode()
39 | {
40 | return GraphSharpEdge.GetHashCode();
41 | }
42 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/IImmutableEdgeSource.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | namespace GraphSharp.Graphs;
3 |
4 | ///
5 | /// Represents edges storage object
6 | ///
7 | public interface IImmutableEdgeSource : IEnumerable
8 | {
9 | ///
10 | /// Whatever parallel edges allowed
11 | ///
12 | bool AllowParallelEdges{get;}
13 | /// All out edges
14 | IEnumerable OutEdges(int sourceId);
15 | /// All in edges
16 | IEnumerable InEdges(int targetId);
17 | /// Both in and out edges. If you need to get both of edges this method will be faster.
18 | (IEnumerable OutEdges, IEnumerable InEdges) BothEdges(int nodeId);
19 | /// A list of combined in and out edges
20 | IEnumerable InOutEdges(int nodeId);
21 | ///
22 | /// Get first found edge with same and
23 | ///
24 | TEdge this[int sourceId, int targetId] { get; }
25 | ///
26 | /// Get first found edge with same and
27 | ///
28 | TEdge this[INode source, INode target] { get; }
29 | }
--------------------------------------------------------------------------------
/GraphSharp/GraphSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | enable
4 | true
5 | Library
6 | net6.0
7 | MIT
8 | 3.1.2
9 | Kemsekov.GraphSharp
10 | True
11 | $(Version)
12 | Kemsekov
13 | https://github.com/Kemsekov/GraphSharp
14 | 6
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/MakeComplete.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Graphs;
2 |
3 | public partial class GraphOperation
4 | where TNode : INode
5 | where TEdge : IEdge
6 | {
7 | ///
8 | /// Ensures that graph is complete by adding missing edges. Produces bidirected graph.
9 | ///
10 | public GraphOperation MakeComplete(){
11 | foreach(var n1 in Nodes){
12 | foreach(var n2 in Nodes){
13 | if(n1.Id==n2.Id) continue;
14 | if(Edges.Contains(n1.Id,n2.Id)) continue;
15 | var toAdd = Configuration.CreateEdge(n1,n2);
16 | Edges.Add(toAdd);
17 | }
18 | }
19 | return this;
20 | }
21 | ///
22 | /// Ensures that subgraph containing given nodes is a complete graph. Creates a clique out of given nodes.
23 | ///
24 | public GraphOperation MakeComplete(params int[] nodes){
25 | foreach(var n1 in nodes){
26 | foreach(var n2 in nodes){
27 | if(n1==n2) continue;
28 | if(Edges.Contains(n1,n2)) continue;
29 | var toAdd = Configuration.CreateEdge(Nodes[n1],Nodes[n2]);
30 | Edges.Add(toAdd);
31 | }
32 | }
33 | return this;
34 | }
35 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Implementations/ObjectPool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 |
5 | namespace GraphSharp.Common;
6 | ///
7 | /// Objects pool that helps to store many objects and reuse them when need
8 | ///
9 | public class ObjectPool
10 | {
11 | private readonly ConcurrentBag _objects;
12 | private readonly Func _objectGenerator;
13 | ///
14 | /// Creates a new instance of object pool
15 | ///
16 | /// Function to create object
17 | public ObjectPool(Func objectGenerator)
18 | {
19 | _objectGenerator = objectGenerator ?? throw new ArgumentNullException(nameof(objectGenerator));
20 | _objects = new ConcurrentBag();
21 | }
22 | ///
23 | /// Retrieves a object from pool
24 | ///
25 | public T Get() => _objects.TryTake(out T? item) ? item : _objectGenerator();
26 | ///
27 | /// Returns a back to pool
28 | ///
29 | public void Return(T item) => _objects.Add(item);
30 | ///
31 | /// Returns many objects back to pool
32 | ///
33 | public void Return(IEnumerable items){
34 | foreach(var i in items)
35 | Return(i);
36 | }
37 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ColorNodes.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Graphs;
2 |
3 |
4 | public partial class ImmutableGraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Apply linear-time greedy graph nodes coloring algorithm.
10 | ///
11 | public ColoringResult GreedyColorNodes()
12 | {
13 | return new GreedyColoring(Nodes, Edges).Color();
14 | }
15 | ///
16 | /// Slightly different implementation of DSatur coloring algorithm.
17 | /// A lot better than greedy algorithm and just about a half of it's speed.
18 | ///
19 | public ColoringResult DSaturColorNodes()
20 | {
21 | return new DSaturColoring(Nodes, Edges).Color();
22 | }
23 | ///
24 | /// Recursive largest first algorithm. The most efficient in colors used algorithm,
25 | /// but the slowest one.
26 | ///
27 | public ColoringResult RLFColorNodes()
28 | {
29 | return new RLFColoring(Nodes, Edges).Color();
30 | }
31 | ///
32 | /// QuikGraph's coloring algorithm
33 | ///
34 | public ColoringResult QuikGraphColorNodes()
35 | {
36 | return new QuickGraphColoring(Nodes, Edges).Color();
37 | }
38 | }
--------------------------------------------------------------------------------
/GraphSharp/Propagators/Implementations/ParallelPropagator.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using GraphSharp.Common;
3 | using GraphSharp.Graphs;
4 | using GraphSharp.Visitors;
5 | namespace GraphSharp.Propagators;
6 |
7 | ///
8 | /// Concurrent implementation.
9 | /// Every that accompany this propagator must be implemented
10 | /// as thread-safe one.
11 | ///
12 | ///
13 | public class ParallelPropagator : PropagatorBase
14 | where TEdge : IEdge
15 | {
16 | ///
17 | public ParallelPropagator(IImmutableEdgeSource edges,IVisitor visitor, int maxNodeId = -1) : base(edges, visitor,maxNodeId)
18 | {
19 | }
20 | ///
21 | protected override void PropagateNodes()
22 | {
23 | Parallel.For(0, NodeStates.Length, nodeId =>
24 | {
25 | var state = NodeStates.GetState(nodeId);
26 | if (ByteStatesHandler.IsInState(UsedNodeStates.ToVisit,state))
27 | PropagateNode(nodeId,state);
28 | });
29 | Parallel.For(0, NodeStates.Length, nodeId =>
30 | {
31 | if (NodeStates.IsInState(UsedNodeStates.Visited,nodeId))
32 | Visitor.Visit(nodeId);
33 | });
34 | }
35 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Implementations/Components.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace GraphSharp.Common;
7 | ///
8 | /// Result of components finder algorithms
9 | ///
10 | ///
11 | public class ComponentsResult : IDisposable
12 | {
13 | ///
14 | public ComponentsResult(IEnumerable[] components, UnionFind setFinder)
15 | {
16 | this.Components = components;
17 | this.SetFinder = setFinder;
18 | }
19 | ///
20 | /// An array of components, where each component contains a set of nodes it contains
21 | ///
22 | public IEnumerable[] Components { get; }
23 | ///
24 | /// Set finder that stores relationships between nodes. If two nodes in same set they in same component.
25 | ///
26 | public UnionFind SetFinder { get; }
27 |
28 | ///
29 | public void Dispose()
30 | {
31 | SetFinder.Dispose();
32 | }
33 | ///
34 | /// Function that helps to determine whatever two nodes in same component
35 | ///
36 | public bool InSameComponent(int nodeId1,int nodeId2){
37 | return SetFinder.FindSet(nodeId1)==SetFinder.FindSet(nodeId2);
38 | }
39 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/MakeSources.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using GraphSharp.Visitors;
4 | namespace GraphSharp.Graphs;
5 |
6 | public partial class GraphOperation
7 | where TNode : INode
8 | where TEdge : IEdge
9 | {
10 | ///
11 | /// Will create sources on nodes with id equal to nodeIndices.
12 | /// In other words after this method used any possible path in a reversed graph
13 | /// will land on one of the nodes you specified.
14 | ///
15 | ///
16 | public GraphOperation MakeSources(params int[] nodeIndices)
17 | {
18 | if (nodeIndices.Count() == 0 || Nodes.Count == 0) return this;
19 |
20 | foreach (var i in nodeIndices)
21 | if (i > Nodes.MaxNodeId)
22 | throw new ArgumentException("nodeIndex is out of range");
23 | var sourceCreator = new SourceCreator(StructureBase);
24 |
25 | foreach (var n in nodeIndices)
26 | {
27 | foreach (var inEdge in Edges.InEdges(n).ToArray())
28 | {
29 | Edges.Remove(inEdge.SourceId, n);
30 | }
31 | }
32 |
33 | sourceCreator.SetPosition(nodeIndices);
34 | while (!sourceCreator.Done)
35 | {
36 | sourceCreator.Propagate();
37 | }
38 | return this;
39 |
40 | }
41 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/AlgorithmBase.cs:
--------------------------------------------------------------------------------
1 | using GraphSharp.Graphs;
2 |
3 | namespace GraphSharp.Algorithms;
4 |
5 | ///
6 | /// Base class for all algorithms on immutable graphs
7 | ///
8 | public abstract class ImmutableAlgorithmBase
9 | where TNode : INode
10 | where TEdge : IEdge
11 | {
12 | ///
13 | public ImmutableAlgorithmBase(IImmutableNodeSource nodes, IImmutableEdgeSource edges)
14 | {
15 | Nodes = nodes;
16 | Edges = edges;
17 | }
18 | ///
19 | /// Nodes used in algorithm
20 | ///
21 | public IImmutableNodeSource Nodes { get; }
22 | ///
23 | /// Edges used in algorithm
24 | ///
25 | public IImmutableEdgeSource Edges { get; }
26 | }
27 |
28 | ///
29 | /// Base class for all algorithms
30 | ///
31 | public abstract class AlgorithmBase
32 | where TNode : INode
33 | where TEdge : IEdge
34 | {
35 | ///
36 | public AlgorithmBase(INodeSource nodes, IEdgeSource edges)
37 | {
38 | Nodes = nodes;
39 | Edges = edges;
40 | }
41 | ///
42 | /// Nodes used in algorithm
43 | ///
44 | public INodeSource Nodes { get; }
45 | ///
46 | /// Edges used in algorithm
47 | ///
48 | public IEdgeSource Edges { get; }
49 | }
--------------------------------------------------------------------------------
/GraphSharp/Nodes/Node.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using MathNet.Numerics.LinearAlgebra.Single;
3 | using GraphSharp.Common;
4 | using System.Collections.Generic;
5 | using System.Collections.Concurrent;
6 | using GraphSharp.Extensions;
7 | namespace GraphSharp;
8 |
9 | ///
10 | /// Default implementation.
11 | ///
12 | public class Node : INode
13 | {
14 | ///
15 | public static Color DefaultColor = Color.Brown;
16 | ///
17 | public int Id { get; set; }
18 |
19 | ///
20 | public IDictionary Properties{get;init;}
21 |
22 | ///
23 | public object this[string propertyName] { get => Properties[propertyName]; set => Properties[propertyName]=value; }
24 |
25 | ///
26 | public Node(int id)
27 | {
28 | Id = id;
29 | Properties = new Dictionary();
30 | }
31 | ///
32 | public override string ToString()
33 | {
34 | return $"Node {Id}";
35 | }
36 |
37 | ///
38 | public Node Clone()
39 | {
40 | return new Node(Id)
41 | {
42 | Properties=this.Properties.Clone()
43 | };
44 | }
45 |
46 | INode ICloneable.Clone() => Clone();
47 |
48 | ///
49 | public bool Equals(INode? other)
50 | {
51 | return other?.Id == Id;
52 | }
53 | }
--------------------------------------------------------------------------------
/GraphSharp/Visitors/BaseClasses/VisitorWithPropagator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GraphSharp.Graphs;
3 | using GraphSharp.Propagators;
4 | namespace GraphSharp.Visitors;
5 |
6 | ///
7 | /// Base implementation of and proxy of in one instance.
8 | ///
9 | public abstract class VisitorWithPropagator : VisitorBase, IPropagator
10 | where TEdge : IEdge
11 | {
12 | ///
13 | /// implementation that used for this proxy class
14 | ///
15 | public abstract PropagatorBase Propagator { get; }
16 | ///
17 | /// Function that used to propagate any exploration algorithm
18 | ///
19 | public void Propagate()
20 | {
21 | Propagator.Propagate();
22 | }
23 |
24 | ///
25 | /// Changes current exploration position
26 | ///
27 | public void SetPosition(params int[] nodeIndices)
28 | {
29 | Propagator.SetPosition(nodeIndices);
30 | }
31 | ///
32 | /// Resets propagator and whole exploration algorithm with new graph and visitor
33 | ///
34 | public void Reset(IImmutableEdgeSource edges, IVisitor visitor, int maxNodeId = -1)
35 | {
36 | Propagator.Reset(edges,visitor,maxNodeId);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/IndependentSet/IndependentSetResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace GraphSharp.Graphs;
6 |
7 | ///
8 | /// Result of independent set finders algorithms
9 | ///
10 | public class IndependentSetResult : IEnumerable, IDisposable
11 | {
12 | const byte Added = 1;
13 | RentedArray NodeState { get; }
14 | ///
15 | /// Nodes in given independent set
16 | ///
17 | public IEnumerable Nodes { get; }
18 | ///
19 | ///
20 | public IndependentSetResult(RentedArray nodeState, IEnumerable nodes)
21 | {
22 | NodeState = nodeState;
23 | Nodes = nodes;
24 | }
25 | ///
26 | /// Determine whatever given node is in given independent set
27 | ///
28 | ///
29 | ///
30 | public bool IsAdded(int nodeId) => (NodeState[nodeId] & Added) == Added;
31 | ///
32 |
33 | public IEnumerator GetEnumerator()
34 | {
35 | return Nodes.GetEnumerator();
36 | }
37 |
38 | IEnumerator IEnumerable.GetEnumerator()
39 | {
40 | return ((IEnumerable)Nodes).GetEnumerator();
41 | }
42 | ///
43 | public void Dispose()
44 | {
45 | NodeState.Dispose();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/Coloring/RLFColoring.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | namespace GraphSharp.Graphs;
4 |
5 | ///
6 | /// Recursive largest first algorithm. The most efficient in colors used algorithm,
7 | /// but the slowest one.
8 | ///
9 | public class RLFColoring : ColoringAlgorithmBase
10 | where TNode : INode
11 | where TEdge : IEdge
12 | {
13 | ///
14 | public RLFColoring(IImmutableNodeSource nodes, IImmutableEdgeSource edges) : base(nodes, edges)
15 | {
16 | }
17 | ///
18 | public override ColoringResult Color()
19 | {
20 | int coloredNodesCount = 0;
21 | int colorIndex = 1;
22 | var colors = ArrayPoolStorage.RentArray(Nodes.MaxNodeId+1);
23 | while (coloredNodesCount != Nodes.Count())
24 | {
25 | var S = FindMaximalIndependentSet(colors,x => colors[x.Id]==0);
26 | var count = S.Count();
27 | coloredNodesCount += count;
28 | foreach (var node in S)
29 | colors[node.Id] = colorIndex;
30 | colorIndex++;
31 | }
32 | return new(colors);
33 | }
34 |
35 | private IndependentSetResult FindMaximalIndependentSet(RentedArray colors, Predicate condition)
36 | {
37 | using var alg = new BallardMyerIndependentSet(Nodes,Edges,x => colors[x.Id]==0);
38 | return alg.Find();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/GraphSharp/Visitors/Implementations/AnyPathFinder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using GraphSharp.Graphs;
4 | namespace GraphSharp.Visitors;
5 |
6 | ///
7 | /// Finds any first found paths between start node and all other nodes
8 | ///
9 | public class AnyPathFinder : PathFinderBase
10 | where TNode : INode
11 | where TEdge : IEdge
12 | {
13 | ///
14 | /// Creates a new instance of
15 | ///
16 | public AnyPathFinder(int startNodeId, IImmutableGraph graph, PathType pathType) : base(graph,pathType)
17 | {
18 | this.StartNodeId = startNodeId;
19 | }
20 | ///
21 | /// Clears all internal path information stored and resets path finding
22 | ///
23 | public void Clear(int startNodeId, int endNodeId)
24 | {
25 | this.StartNodeId = startNodeId;
26 | Path.Fill(-1);
27 | Done = false;
28 | }
29 | ///
30 | protected override bool SelectImpl(EdgeSelect edge)
31 | {
32 | (var sourceId,var targetId) = (edge.SourceId,edge.TargetId);
33 | if (Path[targetId] == -1)
34 | {
35 | Path[targetId] = sourceId;
36 | return true;
37 | }
38 | return false;
39 | }
40 | ///
41 | protected override void VisitImpl(int node)
42 | {
43 | DidSomething = true;
44 | }
45 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ContractEdge.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Contract edge. Target node will be merged with source node so only source node will remain. If there is n
10 | ///
11 | /// True if successfully contracted edge, else false.
12 | public GraphOperation ContractEdge(int sourceId, int targetId)
13 | {
14 | //With edge contraction we need to remove edge we contracting first
15 | Edges.Remove(sourceId, targetId);
16 | Edges.Remove(targetId,sourceId);
17 |
18 | //we will be merging everything into source
19 | var source = Nodes[sourceId];
20 |
21 | var targetEdges = Edges.OutEdges(targetId).ToArray();
22 | var toMove = Edges.InEdges(targetId).ToArray();
23 |
24 | //move target edges to became source edges
25 | foreach (var e in targetEdges)
26 | {
27 | Edges.Move(e,sourceId,e.TargetId);
28 | }
29 |
30 | //move target sources to because source sources (all edges that look like A->targetId became A->sourceId)
31 | foreach (var e in toMove)
32 | {
33 | Edges.Move(e.SourceId,targetId,e.SourceId,sourceId);
34 | }
35 |
36 | //after merging complete remove merged node
37 | Nodes.Remove(targetId);
38 | return this;
39 | }
40 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/Coloring/ColoringAlgorithmBase.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace GraphSharp.Graphs;
4 |
5 | ///
6 | /// Base class for coloring algorithms
7 | ///
8 | public abstract class ColoringAlgorithmBase : Algorithms.ImmutableAlgorithmBase
9 | where TNode : INode
10 | where TEdge : IEdge
11 | {
12 | ///
13 | protected ColoringAlgorithmBase(IImmutableNodeSource nodes, IImmutableEdgeSource edges) : base(nodes, edges)
14 | {
15 | }
16 | ///
17 | /// Performs graph nodes coloring
18 | ///
19 | /// Coloring result
20 | public abstract ColoringResult Color();
21 | /// Id of available color
22 | protected int GetAvailableColor(int nodeId, RentedArray colors)
23 | {
24 | var neighborsColors = Edges.Neighbors(nodeId).Select(x=>colors[x]).ToList();
25 | return Enumerable.Range(1,neighborsColors.Max()+1).Except(neighborsColors).First();
26 | }
27 | ///
28 | /// Assigns first available color
29 | ///
30 | protected void AssignColor(int nodeId, RentedArray colors)
31 | {
32 | colors[nodeId] = GetAvailableColor(nodeId, colors);
33 | }
34 | /// Amount of neighbors that have different colors
35 | protected int DegreeOfSaturation(int nodeId, RentedArray colors)
36 | {
37 | return Edges.Neighbors(nodeId).DistinctBy(x => colors[x]).Count();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/ConnectRandomly.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | public partial class GraphOperation
5 | where TNode : INode
6 | where TEdge : IEdge
7 | {
8 | ///
9 | /// Randomly create some range of edges for each node, so each node have more or equal than minEdgesCount but than less maxEdgesCount edges.
10 | ///
11 | /// Min count of edges for each node
12 | /// Max count of edges for each node
13 | public GraphOperation ConnectRandomly(int minEdgesCount, int maxEdgesCount)
14 | {
15 | minEdgesCount = minEdgesCount < 0 ? 0 : minEdgesCount;
16 | maxEdgesCount = maxEdgesCount > Nodes.Count ? Nodes.Count : maxEdgesCount;
17 |
18 | //swap using xor
19 | if (minEdgesCount > maxEdgesCount)
20 | {
21 | minEdgesCount = minEdgesCount ^ maxEdgesCount;
22 | maxEdgesCount = minEdgesCount ^ maxEdgesCount;
23 | minEdgesCount = minEdgesCount ^ maxEdgesCount;
24 | }
25 |
26 | var availableNodes = Nodes.Select(x => x.Id).ToList();
27 |
28 | foreach (var node in Nodes)
29 | {
30 | int edgesCount = Configuration.Rand.Next(minEdgesCount, maxEdgesCount);
31 | var startIndex = Configuration.Rand.Next(Nodes.Count);
32 | ConnectNodeToNodes(node, startIndex, edgesCount, availableNodes);
33 | }
34 | return this;
35 | }
36 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/GraphOperations/TransitiveClosureOnRadius.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using GraphSharp.Common;
4 |
5 | namespace GraphSharp.Graphs;
6 |
7 | public partial class GraphOperation
8 | where TNode : INode
9 | where TEdge : IEdge
10 | {
11 | // TODO: add tests for it
12 | ///
13 | /// Produce transitive closure on some radius.
14 | /// When we have a path like a -> b -> c -> d and calling this method with radius = 1
15 | /// we will create a edges: a -> c, b -> d.
16 | /// Param radius = 2 will just repeat this process twice, so in this
17 | /// case it will create edge a -> d as addition to already created edges
18 | ///
19 | public GraphOperation TransitiveClosureOnRadius(int radius)
20 | {
21 | var edgesToAdd = new List();
22 | for (int i = 0; i < radius; i++)
23 | {
24 | edgesToAdd.Clear();
25 | foreach (var n in Nodes)
26 | {
27 | foreach (var edge in Edges.OutEdges(n.Id))
28 | {
29 | foreach (var edge2 in Edges.OutEdges(edge.TargetId)){
30 | var n2 = Nodes[edge2.TargetId];
31 | if(!Edges.Contains(n.Id,n2.Id))
32 | edgesToAdd.Add(Configuration.CreateEdge(n, n2));
33 | }
34 | }
35 | }
36 | foreach (var e in edgesToAdd) Edges.Add(e);
37 | }
38 | return this;
39 | }
40 | }
--------------------------------------------------------------------------------
/GraphSharp/Common/Interfaces/IStatesHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace GraphSharp.Common;
7 | ///
8 | /// States handler
9 | ///
10 | public interface IStatesHandler
11 | {
12 | ///
13 | /// Adds state to all given objects
14 | ///
15 | void AddState(TState state,TObject[] objects);
16 | ///
17 | /// Adds states to all known objects
18 | ///
19 | void AddStateToAll(TState state);
20 | ///
21 | /// Removes state from all given objects
22 | ///
23 | void RemoveState(TState state,TObject[] objects);
24 | ///
25 | /// Removes state from all known objects
26 | ///
27 | void RemoveStateFromAll(TState state);
28 | ///
29 | /// Checks if given object is in given state
30 | ///
31 | bool IsInState(TState state,TObject obj);
32 | ///
33 | /// Sets state to all given objects.
34 | /// It differs from adding states in a way, that all other states are removed.
35 | ///
36 | void SetState(TState state, TObject[] objects);
37 | ///
38 | /// Sets state to all known objects.
39 | /// It differs from adding states in a way, that all other states are removed.
40 | ///
41 | void SetStateToAll(TState state);
42 | /// A state of given object
43 | TState GetState(TObject obj);
44 | }
--------------------------------------------------------------------------------
/GraphSharp/Algorithms/Coloring/DSaturColoring.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | namespace GraphSharp.Graphs;
3 |
4 | ///
5 | /// Slightly different implementation of DSatur coloring algorithm.
6 | /// A lot better than greedy algorithm and just about a half of it's speed.
7 | ///
8 | public class DSaturColoring : ColoringAlgorithmBase
9 | where TNode : INode
10 | where TEdge : IEdge
11 | {
12 | ///
13 | public DSaturColoring(IImmutableNodeSource nodes, IImmutableEdgeSource edges) : base(nodes, edges)
14 | {
15 | }
16 | ///
17 | public override ColoringResult Color()
18 | {
19 | var colors = ArrayPoolStorage.RentArray(Nodes.MaxNodeId + 1);
20 | var order = Nodes.OrderBy(x => -Edges.Neighbors(x.Id).Count());
21 |
22 | int coloredNodesCount = 0;
23 | foreach (var n in order)
24 | {
25 | if (colors[n.Id] != 0) continue;
26 | var toColor = n.Id;
27 | while (coloredNodesCount != Nodes.Count())
28 | {
29 | AssignColor(toColor, colors);
30 | coloredNodesCount++;
31 | var neighbors =
32 | Edges.Neighbors(toColor)
33 | .Where(x => colors[x] == 0)
34 | .ToList();
35 | if (neighbors.Count == 0)
36 | break;
37 | toColor = neighbors.MaxBy(x => DegreeOfSaturation(x, colors));
38 | }
39 | }
40 | return new(colors);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/GraphSharp/GraphStructures/Interfaces/IGraph{}.cs:
--------------------------------------------------------------------------------
1 | namespace GraphSharp.Graphs;
2 |
3 | ///
4 | /// Graph structure interface.
5 | ///
6 | public interface IGraph : IImmutableGraph
7 | where TNode : INode
8 | where TEdge : IEdge
9 | {
10 | ///
11 | /// Graph nodes
12 | ///
13 | new INodeSource Nodes { get; }
14 | IImmutableNodeSource IImmutableGraph.Nodes => Nodes;
15 | ///
16 | /// Graph edges
17 | ///
18 | new IEdgeSource Edges { get; }
19 | IImmutableEdgeSource IImmutableGraph.Edges => Edges;
20 | ///
21 | /// Graph operations object that required to perform operations on a graph. Contains a lot of methods to do various tasks.
22 | ///
23 | new GraphOperation Do { get; }
24 | ImmutableGraphOperation IImmutableGraph.Do => Do;
25 | ///
26 | /// Graph converter. If you need to convert current graph to different representations or initialize current graph from different representations then look at this objects methods.
27 | ///
28 | new GraphConverters Converter { get; }
29 | ImmutableGraphConverters