Support undirected graphs.
All checks were successful
/ Build and Release Library (push) Successful in 1m19s
All checks were successful
/ Build and Release Library (push) Successful in 1m19s
This commit is contained in:
parent
2dcb9f7c26
commit
4788240666
6 changed files with 145 additions and 52 deletions
|
|
@ -55,6 +55,8 @@ end Graph
|
|||
|
||||
object Graph:
|
||||
|
||||
/** The empty graph. Contains no vertices and no edges.
|
||||
*/
|
||||
object Empty extends Graph:
|
||||
|
||||
override def numberOfVertices: Size = Size.Zero
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package gs.graph.v0
|
||||
|
||||
/** Undirected implementation of [[Graph]].
|
||||
*
|
||||
* @param numberOfVertices
|
||||
* The number of vertices present in this graph.
|
||||
* @param adjacency
|
||||
* The [[Adjacency]] which describes this graph.
|
||||
*/
|
||||
class UndirectedGraph(
|
||||
val numberOfVertices: Size,
|
||||
val adjacency: Adjacency
|
||||
) extends Graph:
|
||||
/** @inheritDocs
|
||||
*/
|
||||
final override val disposition: GraphDisposition = GraphDisposition.Undirected
|
||||
end UndirectedGraph
|
||||
|
||||
object UndirectedGraph:
|
||||
|
||||
/** @return
|
||||
* An empty [[UndirectedGraph]].
|
||||
*/
|
||||
def empty(): UndirectedGraph = new UndirectedGraph(Size.Zero, Adjacency.Empty)
|
||||
|
||||
end UndirectedGraph
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package gs.graph.v0.data
|
||||
|
||||
import gs.graph.v0.Adjacency
|
||||
import gs.graph.v0.GraphDisposition
|
||||
import gs.graph.v0.GraphException
|
||||
import gs.graph.v0.Size
|
||||
import gs.graph.v0.Vertex
|
||||
|
||||
/** Trait that describes _any_ graph (undirected, directed, or other
|
||||
* specializations of those such as DAGs) that is correlated with data.
|
||||
*/
|
||||
trait AnyGraphWithData[A]:
|
||||
/** @return
|
||||
* The data stored by each [[gs.graph.v0.Vertex]] in this graph.
|
||||
*/
|
||||
def data: Vector[A]
|
||||
|
||||
/** @return
|
||||
* The number of vertices present in this graph.
|
||||
*/
|
||||
def numberOfVertices: Size
|
||||
|
||||
/** @return
|
||||
* The [[Adjacency]] that describes this graph.
|
||||
*/
|
||||
def adjacency: Adjacency
|
||||
|
||||
/** @return
|
||||
* The underlying disposition of this graph.
|
||||
*/
|
||||
def disposition: GraphDisposition
|
||||
|
||||
/** Retrieve the data associated with some [[Vertex]].
|
||||
*
|
||||
* This implementation throws an exception if the input [[Vertex]] is out of
|
||||
* range for this graph.
|
||||
*
|
||||
* @param vertex
|
||||
* The input [[Vertex]].
|
||||
* @return
|
||||
* The data associated with the input [[Vertex]].
|
||||
*/
|
||||
def dataAtUnsafe(vertex: Vertex): A =
|
||||
if vertex < numberOfVertices then data.apply(vertex.ordinal)
|
||||
else throw GraphException.VertexExceedsGraphBounds(vertex, numberOfVertices)
|
||||
|
||||
/** Retrieve the data associated with some [[Vertex]].
|
||||
*
|
||||
* @param vertex
|
||||
* The input [[Vertex]].
|
||||
* @return
|
||||
* The data associated with the input [[Vertex]], or `None` if the
|
||||
* [[Vertex]] is out of range for this graph.
|
||||
*/
|
||||
def dataAt(vertex: Vertex): Option[A] =
|
||||
if vertex < numberOfVertices then Some(data.apply(vertex.ordinal)) else None
|
||||
|
|
@ -13,32 +13,8 @@ final class DataDag[A] private (
|
|||
n: Size,
|
||||
a: Adjacency,
|
||||
r: Vector[Vertex]
|
||||
) extends Dag(n, a, r):
|
||||
|
||||
/** Retrieve the data associated with some [[Vertex]].
|
||||
*
|
||||
* This implementation throws an exception if the input [[Vertex]] is out of
|
||||
* range for this graph.
|
||||
*
|
||||
* @param vertex
|
||||
* The input [[Vertex]].
|
||||
* @return
|
||||
* The data associated with the input [[Vertex]].
|
||||
*/
|
||||
def dataAtUnsafe(vertex: Vertex): A =
|
||||
if vertex < n then data.apply(vertex.ordinal)
|
||||
else throw GraphException.VertexExceedsGraphBounds(vertex, n)
|
||||
|
||||
/** Retrieve the data associated with some [[Vertex]].
|
||||
*
|
||||
* @param vertex
|
||||
* The input [[Vertex]].
|
||||
* @return
|
||||
* The data associated with the input [[Vertex]], or `None` if the
|
||||
* [[Vertex]] is out of range for this graph.
|
||||
*/
|
||||
def dataAt(vertex: Vertex): Option[A] =
|
||||
if vertex < n then Some(data.apply(vertex.ordinal)) else None
|
||||
) extends Dag(n, a, r)
|
||||
with AnyGraphWithData[A]
|
||||
|
||||
object DataDag:
|
||||
|
||||
|
|
|
|||
|
|
@ -13,32 +13,8 @@ final class DataDigraph[A] private (
|
|||
n: Size,
|
||||
a: Adjacency,
|
||||
r: Vector[Vertex]
|
||||
) extends Digraph(n, a, r):
|
||||
|
||||
/** Retrieve the data associated with some [[Vertex]].
|
||||
*
|
||||
* This implementation throws an exception if the input [[Vertex]] is out of
|
||||
* range for this graph.
|
||||
*
|
||||
* @param vertex
|
||||
* The input [[Vertex]].
|
||||
* @return
|
||||
* The data associated with the input [[Vertex]].
|
||||
*/
|
||||
def dataAtUnsafe(vertex: Vertex): A =
|
||||
if vertex < n then data.apply(vertex.ordinal)
|
||||
else throw GraphException.VertexExceedsGraphBounds(vertex, n)
|
||||
|
||||
/** Retrieve the data associated with some [[Vertex]].
|
||||
*
|
||||
* @param vertex
|
||||
* The input [[Vertex]].
|
||||
* @return
|
||||
* The data associated with the input [[Vertex]], or `None` if the
|
||||
* [[Vertex]] is out of range for this graph.
|
||||
*/
|
||||
def dataAt(vertex: Vertex): Option[A] =
|
||||
if vertex < n then Some(data.apply(vertex.ordinal)) else None
|
||||
) extends Digraph(n, a, r)
|
||||
with AnyGraphWithData[A]
|
||||
|
||||
object DataDigraph:
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
package gs.graph.v0.data
|
||||
|
||||
import gs.graph.v0.Adjacency
|
||||
import gs.graph.v0.GraphException
|
||||
import gs.graph.v0.Size
|
||||
import gs.graph.v0.UndirectedGraph
|
||||
|
||||
/** Specialization of [[UndirectedGraph]] that associates _data_ with _each
|
||||
* [[Vertex]]_.
|
||||
*/
|
||||
final class UndirectedDataGraph[A] private (
|
||||
val data: Vector[A],
|
||||
n: Size,
|
||||
a: Adjacency
|
||||
) extends UndirectedGraph(n, a)
|
||||
with AnyGraphWithData[A]
|
||||
|
||||
object UndirectedDataGraph:
|
||||
|
||||
/** @return
|
||||
* An empty [[UndirectedGraph]] with no data.
|
||||
*/
|
||||
def empty[A]: UndirectedDataGraph[A] =
|
||||
new UndirectedDataGraph[A](
|
||||
Vector.empty,
|
||||
Size.Zero,
|
||||
Adjacency.Empty
|
||||
)
|
||||
|
||||
/** Instantiate a new [[UndirectedDataGraph]] given an input
|
||||
* [[UndirectedGraph]] and some data.
|
||||
*
|
||||
* Throws an exception if the input data vector does not exactly match the
|
||||
* number of nodes in the graph -- each node MUST have a data element.
|
||||
*
|
||||
* @param graph
|
||||
* The input [[UndirectedGraph]].
|
||||
* @param data
|
||||
* The data to associate with the [[UndirectedGraph]].
|
||||
* @return
|
||||
* The new [[UndirectedDataGraph]] instance.
|
||||
*/
|
||||
def fromUndirectedGraph[A](
|
||||
graph: UndirectedGraph,
|
||||
data: Vector[A]
|
||||
): UndirectedDataGraph[A] =
|
||||
if graph.numberOfVertices != Size.fromVector(data) then
|
||||
throw GraphException.DataGraphMismatch(
|
||||
graph.numberOfVertices,
|
||||
data.length
|
||||
)
|
||||
else
|
||||
new UndirectedDataGraph(
|
||||
data,
|
||||
graph.numberOfVertices,
|
||||
graph.adjacency
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue