Immutable graph-like structures in Scala

2019-05-14 07:17发布

Good day! I'm trying to construct immutable graph in Scala 2.9.1. It's given to me with Seq[BO], where BO can represent one node in graph, and BO.attr_bo: Seq[String] who represents edges to other nodes, given by string name. And I need to construct "resolved" graph, represented by BO with ResolvedBO You can see possible realization here:

trait BO {
  def name: String
  def attr_bo: Seq[String]
}

trait ResolvedBO {
  x: BO =>
  val uni: Universe
  lazy val r_attr_bo: Seq[BO with ResolvedBO] = attr_bo map (uni.m_list_r(_))
}

class S_BO(val name: String, val attr_bo: Seq[String]) extends BO

class Universe(list: Seq[BO]) {
  val m_list: Map[String, BO] = list.map(x => (x.name, x))(collection.breakOut)
  val m_list_r: Map[String, BO with ResolvedBO] = ...???
}

val x: Uni = new Uni(Seq(new S_BO("a", Seq("b", "c")), new S_BO("b", Seq("a", "c")), new S_BO("c", Seq("a", "b"))))

where class Universe represents graph at all (it can also be disconnected one) Also, if it's important, I can restrict graph to be without cycles.

So my main questions:

  1. Since nodes (trait BO) can be quite complex objects and can be realized with several subtypes, what is the best way to implement "resolved nodes" - i.e. nodes with direct links to other nodes? (BO with ResolvedBO).
  2. If resolving nodes by themselves is the best way (lazy val r_attr_bo: Seq[BO with ResolvedBO] = attr_bo map (uni.m_list_r(_)) in trait ResolvedBO), how can I initialize graph's reference (val uni: Universe) in trait ResolvedBO?
  3. At all, what's the best way to work with graph-like structures in Scala?

thank you

1条回答
趁早两清
2楼-- · 2019-05-14 07:48

For point 3, it depends on your definition of what "best" means. I would recommend not implementing a lib yourself and use scala-graph which seems to be suited to your needs (immutable graphs).

If you really insist to write your own graph library (it's a good way to improve your knowledge in Scala), try avoiding a graph of objects (using references to represent the connections). Rather go for a Graph class with generic operations like: myGraph.neighborsOf( myVertex ).

A nice representation (easy to implement but slow for huge graphs) is to represent the graph as a set of edges. To add a new edge, you just add a new object to the set. To get the set of all vertices, you just flatten the set of edges. To get the neighbors of a vertex, you iterate on every edges, etc.

A faster solution is to use a more complex representation, like a Map where the keys are vertices and the values the set of neighbors.

Have a look at scala-graph source code for inspiration.

查看更多
登录 后发表回答