Я работаю над своими scala chops и реализовал небольшой график Api для отслеживания вершин и ребер, добавленных в график. У меня есть базовая функция GraphLike Trait и есть класс Undirected Graph (UnDiGraph
) и класс Directed graph (DiGraph
), который расширяет черту GraphLike
. Ниже перечислены некоторые из нихНужна помощь в определении узкого места производительности
trait GraphLike[T] {
val vertices: Map[T, VertexLike[T]]
def addEdge(a:T, b:T): GraphLike[T]
def addVertex(t:T): GraphLike[T]
def addVertex(vert: VertexLike[T]): GraphLike[T]
def adjacency(t:T): Option[ List[T] ] =
{
if (vertices contains t)
Some(vertices(t).adjList)
else
None
}
def vertNum: Integer = vertices size
def edgeNum: Integer =
{
def summer(sum: Integer, ms: Map[T, VertexLike[T] ]): Integer =
{
if (ms.isEmpty)
sum
else
summer(sum + ms.head._2.adjList.size, ms.tail)
}
summer(0, vertices)
}
def getVertex(t: T): VertexLike[T] =
{
vertices(t)
}
def edgeExists(a:T, b:T): Boolean =
{
try
{
if(vertices(a).adjList contains b)
true
else
false
}catch {
case ex: NoSuchElementException => false
}
}
}
Heres what the Directe Graph Понрателет.
class DiGraph[T](val vertices: Map[ T, VertexLike[ T ] ] = Map.empty) extends GraphLike[T] {
def makeVertex(t:T): VertexLike[T] = new Vertex(t)
def addEdge(a:T, b:T): GraphLike[T] =
{
//Make sure vertices exist
if(edgeExists(a, b))
this
else {
try {
vertices(b)
vertices(a)
} catch {
case ex: NoSuchElementException => println("Vertices not Found"); this
}
addVertex(vertices(a) + b)
}
}
def addVertex(t:T): DiGraph[T] =
{
if(vertices contains t) this
else
new DiGraph[T](vertices + (t -> makeVertex(t)))
}
def addVertex(vert: VertexLike[T]): DiGraph[T] =
{
new DiGraph[T](vertices + (vert.apply -> vert))
}
}
Вершины хранятся в карте, идущей от типа T до VertexLike [T]. Vertex Как обычно, имеет список смежности для конкретной вершины. Вот что выглядит VertexLike как:
trait VertexLike[T]
{
def addEdgeTo(dest: T): VertexLike[T]
def adjList: List[T]
def +(dest: T) = addEdgeTo(dest)
def apply: T
}
class Vertex[T](t: T, adj: List[T] = List()) extends VertexLike[T]
{
def apply() = t
def adjList = adj
def addEdgeTo(dest: T) =
if(adjList contains dest)
this
else
new Vertex[T](t, dest :: adjList)
}
(. Да ... я понимаю, что метод применяется в классе бесполезно, и он работает только на объектах Понял, что чуть позже).
В любом случае, у меня есть пример графика, где у меня около 80 000 вершин. Добавление вершин к графику происходит слишком долго. Я пытался делать что-то функционально и неизменно. Всякий раз, когда вы добавляете вершину или ребро к графу, вы получаете новый график (я пытался убедиться, что конструкторы типов графов не очень много). Это код клиента, который я использую для создания моего графика из моих данных.
def GraphInstantiater: GraphLike[Int] =
{
println("Total number of Vertices: " + synMap.keys.size)
def vertexAdder(ls: Iterable[Int], graph:GraphLike[Int]): GraphLike[Int] =
if(ls.isEmpty) graph else vertexAdder(ls.tail, graph.addVertex(ls.head))
val gr = vertexAdder(synMap.keys, new DiGraph[Int](Map()))
println("Vertices added. Total: %d".format(gr.vertices.size))
gr
}
Я знаю, что строить новые графики будут принимать циклы, но это на самом деле все, что больше, учитывая, что я не делаю много в конструкторах. Многократно создавал бы карту вершин, вызывающих проблемы (один из параметров класса графа). Любые идеи о том, что узкие места в этом методе будут высоко оценены. Также, если вам нужна дополнительная информация, пожалуйста, дайте мне знать.
Если все элементы вашего графика неизменны навсегда, и вы создаете новый график, добавляя/обновляя/удаляя узел, вы можете сделать новый график: 1) создавая ТОЛЬКО новые узлы, которые были произведены с помощью изменения 2) в противном случае все будет ссылкой на исходный граф. Аналогичная концепция для семантики copy-on-write – Patashu
Он уже делает именно это (он использует неизменяемые карты, которые делят свои общие элементы по ссылке) –
Должно ли это быть опубликовано в http://codereview.stackexchange.com/? – Dahdahm