How would I add a new ranking algorithm to Lemmy as a contributor? I'm a developer by trade, but unfamiliar with Rust and the codebase of Lemmy specifically. It doesn't seem like Lemmy has a concept of 'ranking plugins', so whatever I do would have to involve an MR.
Specifically, I'd like to introduce a ranking system that approximates Proportional Approval Voting, specifically using Thiele's elimination methods, like is used in LiquidFeedback.
I'm pretty sure that with a few tweaks to Thiele's rules, I can compute a complete ranking of all comments in a thread in O(ClogC + E + VlogC)
, where C
is the number of comments, E
is the total number of likes, and V
is the number of users. This would also support partial approvals, upvotes could decay with age.
I believe this would mitigate the tendency towards echo chambers that Lemmy inherits from Reddit. Lemmy effectively uses Block Approval Voting with decays to rank comments and posts, leading to the same people dominating every conversation.
The ranking is implemented in a rather complicated way for performance reasons:
post.hot_rank
)This is exactly the info I'm looking for, thanks! I knew there'd have to be some kind of scheduled task to recompute the rankings (IIRC the lemmy docs say ~10 minutes for recomputing ranks), I just wasn't sure where it was.
The change that would require the least effort to implement my voting system (whether the lemmy maintainers would accept the change notwithstanding) would be to target the schedule task, and introduce a server-wide configuration option that would allow admins to pick whether they're using Block Approval (what we have now) or Proportional Approval (what I'm introducing) based algorithms for their server's "hot" algorithm. No API or frontent changes required. Then, work towards community mods being able to set that on a per-community basis.
Something for me to experiment with, anyway.
Sounds interesting, though from your links it's not clear to me how exactly it works. Depending on that it could make more sense to implement as a separate sort option, then each user could try and compare it to the existing sorts.
I was thinking of it as a drop-in replacement for "hot" just so that it doesn't require any changes on the UI to implement. I'm a bit rusty with UI development, lol. The frontends wouldn't have to add a new button, and the Lemmy API wouldn't need to add a new sort type. That said, maybe that sort of thing is easy to do?
As far as it would work, Thiele's elimination rules is computed roughly as follows (I'm assuming that only upvotes are counted; I haven't considered yet if the process works if disapprovals count as a vote of "-1" or how the process could remain scalable if an abstention counts as a vote of "0.5":
For this algorithm, the
yield the removed post
statement will return the sorted posts in reverse order. So worst to best. You could also interpret that statement as "Give the post a rank in the final sorting ofcount(posts) - (i++)
".Thiele says that process can be used to elect a committee of size N by stopping your removal when N votes remain. But because it's a "house monotonic" process (electoral speak for "increasing the size of the committee by one and re-running an election is guaranteed not to cost any existing members their seat), I figure it could be repurposed to produce a ranking as well - the top one item is "best one", the top two items are the best two, the top three are the best three, etc.
To make the above process work for approvals that decay over time, we'd just treat a decayed approval as a partial approval. I still have some work to do on how exactly to integrate partial approvals into the "resistance to removing each post" calculations without ruining my time complexity. But basically it's a proportional score voting election instead of proportional approval.
Adding a new sort type is not a big deal, so dont worry about it. And a new admin setting for this would also require UI changes, so the new sort type is easier overall.
The current sort options calculate the rank for each post only from the data on that post (number of votes, creation time). Your suggested algorithm looks much more complicated than that, as it requires two iterations and needs to access data from multiple posts at once. Im not sure if this can really be implemented in a way thats performant enough for production use. Anyway feel free to open a pull request, then hopefully other contributors can help you to get it working.