Я реализую 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). Мне просто нужно переопределить этот класс и обеспечить семантику равенства, чтобы это работало? Или я использую совершенно неправильный подход?
Спасибо за вашу помощь.