График JUNG — PageRank с неориентированным графиком и взвешенными ребрами

Я реализую PageRank на неориентированном графе со взвешенными ребрами. Насколько я понимаю, поскольку мой граф неориентирован, вероятности перехода, представляющие веса ребер, будут разными в зависимости от исходной вершины. Это имеет смысл, так как вероятности должны составлять 1 для исходящих ребер вершины, но каждая инцидентная вершина ребра будет иметь разные требования, а это означает, что у меня не может быть общих вероятностей перехода между ними. (Если это понимание неверно, пожалуйста, поправьте меня).

Однако у меня возникли проблемы с реализацией этого, поскольку в примерах в тестах и ​​документах используются только простые веса ребер, тогда как мне нужны пары VertexEdge, привязанные к весам (я думаю). Класс VEPair выдает исключения нулевого указателя при замене стандартных весовых коэффициентов с целочисленным ключом.

Семантика следующая:

Я создаю UndirectedSparseGraph и добавляю вершины 0, 1, 2, 3.

g.addVertex(0);
g.addVertex(1);
g.addVertex(2);
g.addVertex(3);

Затем к графу я добавляю ребра 0, 1, 2, 3. соединяя вершины 0=>1 1=>2 2=>3 3=>0 т.е.

g.addEdge(0, 0, 1); 
g.addEdge(1, 1, 2); 
g.addEdge(2, 2, 3); 
g.addEdge(3, 3, 0);

Я добавляю равный вес ребра 0,5 для каждой вершины.

map.put(0, 0.5);
map.put(1, 0.5);
map.put(2, 0.5);
map.put(3, 0.5);

Я создаю экземпляр PageRank, используя график, преобразованные веса ребер и альфа-канал, равный 0, т.е.:

pr = new PageRank(g, MapTransformer.getInstance(map), 0);

Теперь оценка каждой вершины дает 0,25, что правильно, т. е.:

pr.getVertexScore(0); // 0.25
pr.getVertexScore(1); // 0.25

Моя проблема в том, что я не могу иметь вес ребра просто на ребрах, потому что граф неориентированный. Вес ребра должен различаться в зависимости от исходной вершины, потому что все исходящие ребра вершины должны иметь веса ребер, равные 1. Поэтому мне нужен способ не сказать, что ребро 0 имеет вес x, а то, что ребро 0 имеет вес x для вершины 0 и y для вершины 1.

Итак, я подумал, что можно было бы использовать класс VEPair в моем maptransformer вместо целых чисел выше, то есть:

map.put(new VEPair(0, 0), 0.5);
map.put(new VEPair(1, 0), 0.5);
map.put(new VEPair(1, 1), 0.5);
map.put(new VEPair(2, 1), 0.5);
map.put(new VEPair(2, 2), 0.5);
map.put(new VEPair(3, 2), 0.5);
map.put(new VEPair(3, 3), 0.5);
map.put(new VEPair(0, 3), 0.5);

Итак, сематика та же самая, я просто явно указываю вес каждого ребра с заданной исходной вершиной.

Однако вызов pr.evaluate() приводит к исключению Null Pointer в строке 87 PageRankWithPriors.update().

Этот код, в частности, пытается получить самый первый указанный вес ребра, и он равен нулю.

Обратите внимание, что простое использование старого простого MapTransformer из apache.commons с VEPairs в качестве ключей всегда будет приводить к нулевым значениям, поскольку класс VEPair не реализовал hashCode или равные. поэтому VEPair(0, 0) не равно VEPair(0, 0). Мне просто нужно переопределить этот класс и обеспечить семантику равенства, чтобы это работало? Или я использую совершенно неправильный подход?

Спасибо за вашу помощь.


person Scott Klarenbach    schedule 20.10.2014    source источник
comment
Пожалуйста, добавьте больше контекста о ваших требованиях (какой должна быть семантика весов ребер?) и предоставьте подробную информацию (трассировка стека с фрагментом кода была бы идеальной) об исключениях, которые вы видите.   -  person Joshua O'Madadhain    schedule 21.10.2014
comment
Извините за задержку @Joshua. Я добавил более подробную информацию, которая, надеюсь, покажет вам, чего я пытаюсь достичь. Дайте мне знать, если этого недостаточно. Код и трассировки не точны, так как я использую Clojure, а не Java, поэтому, надеюсь, то, что я предоставил, достаточно ясно, чтобы указать мне правильное направление.   -  person Scott Klarenbach    schedule 25.10.2014
comment
Вы знаете, я полагаю, что самое простое решение моей проблемы — просто использовать направленный граф с ребрами в каждую вершину и из нее, а веса ребер затем можно привязать к вершине, не прибегая к описанному выше подходу VEPair.   -  person Scott Klarenbach    schedule 26.10.2014


Ответы (1)


VEPair не очень подходит для внешнего использования. Он используется внутри в значительной степени для обработки общего случая (неориентированный граф, веса ребер которого неявно однородны).

Я вижу, что у вас уже есть решение, которое может вам подойти, но если вам нужно решение, которое не требует создания нового DirectedGraph, вы можете переопределить метод getEdgeWeight(V,E) PageRank (реализованный в AbstractIterativeScorer) делать все, что вы хотите с точки зрения ненаправленных весов ребер.

person Joshua O'Madadhain    schedule 03.11.2014
comment
Я отменил getEdgeWeight, как вы предлагаете, что дает тот же результат, что и подход DirectedSparseGraph, но требует только половины ребер, что убивает двух зайцев (поскольку у меня также есть проблема с производительностью). Спасибо за это. - person Scott Klarenbach; 26.11.2014