Я хотел бы ранжировать элементы в соответствии с предпочтениями пользователя (элементы, которые нравятся пользователю) на основе случайного блуждания по ориентированному двудольному графу с использованием gremlin в Groovy.
Граф имеет следующую базовую структуру:
[User1] --- 'лайки' ---> [ItemA] ‹--- 'лайки' --- [User2] --- 'лайки' ---> [ItemB]
Далее запрос, который я придумал:
def runRankQuery(def userVertex) {
def m = [:]
def c = 0
while (c < 1000) {
userVertex
.out('likes') // get all liked items of current or similar user
.shuffle[0] // select randomly one liked item
.groupCount(m) // update counts for selected item
.in('likes') // get all users who also liked item
.shuffle[0] // select randomly one user that liked item
.loop(5){Math.random() < 0.5} // follow liked edge of new user (feed new user in loop)
// OR abort query (restart from original user, outer loop)
.iterate()
c++
}
m = m.sort {a, b -> b.value <=> a.value}
println "intermediate result $m"
m.keySet().removeAll(userVertex.out('likes').toList())
// EDIT (makes no sense - remove): m.each{k,v -> m[k] = v / m.values().sum()}
// EDIT (makes no sense - remove): m.sort {-it.value }
return m.keySet() as List;
}
Однако этот код не находит новые элементы ([ItemB] в примере выше), а только понравившиеся элементы данного пользователя (например, [ItemA]).
Что мне нужно изменить, чтобы скормить новому пользователю (например, [User2]) шаг цикла назад к шагу 'out (' like ')', чтобы продолжить прогулку?
Как только этот код заработает, можно ли его рассматривать как реализацию «Персонализированного рейтинга страниц»?
Вот код для запуска примера:
g = new TinkerGraph()
user1 = g.addVertex()
user1.name ='User1'
user2 = g.addVertex()
user2.name ='User2'
itemA = g.addVertex()
itemA.name ='ItemA'
itemB = g.addVertex()
itemB.name ='ItemB'
g.addEdge(user1, itemA, 'likes')
g.addEdge(user2, itemA, 'likes')
g.addEdge(user2, itemB, 'likes')
println runRankQuery(user1)
И вывод:
intermediate result [v[2]:1000]
[]
==>null
gremlin> g.v(2).name
==>ItemA
gremlin>