{"action":"created","comment":{"url":"https://api.github.com/repos/lenskit/lenskit/pulls/comments/31959700","id":31959700,"diff_hunk":"@@ -0,0 +1,133 @@\n+/*\n+ * LensKit, an open source recommender systems toolkit.\n+ * Copyright 2010-2014 LensKit Contributors.  See CONTRIBUTORS.md.\n+ * Work on LensKit has been funded by the National Science Foundation under\n+ * grants IIS 05-34939, 08-08692, 08-12148, and 10-17697.\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU Lesser General Public License as\n+ * published by the Free Software Foundation; either version 2.1 of the\n+ * License, or (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\n+ * details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program; if not, write to the Free Software Foundation, Inc., 51\n+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n+ */\n+package org.lenskit.api;\n+\n+import javax.annotation.Nullable;\n+import java.util.Set;\n+\n+/**\n+ * Interface for recommending items. Several methods are provided, of varying\n+ * generality.\n+ *\n+ * The core idea of the recommend API is to recommend <i>n</i> items for a user,\n+ * where the items recommended are taken from a set of candidate items and\n+ * further constrained by an exclude set of forbidden items. Items in the\n+ * candidate set but not in the exclude set are considered viable for\n+ * recommendation.\n+ *\n+ * ## Candidate Items\n+ *\n+ * By default, the candidate set is the universe of all items the recommender\n+ * knows about. The default exclude set is somewhat more subtle. Its exact\n+ * definition varies across implementations, but will be the set of items the\n+ * system believes the user will not be interested in by virtue of already\n+ * having or knowing about them. For example, rating-based recommenders will\n+ * exclude the items the user has rated, and purchase-based recommenders will\n+ * typically exclude items the user has purchased. Some implementations may\n+ * allow this to be configured. Client code always has the option of manually\n+ * specifying the exclude set, however, so applications with particular needs in\n+ * this respect can manually provide the sets they need respected.\n+ *\n+ * ## Ordering\n+ *\n+ * If the recommender has an opinion about the order in which recommendations should be displayed,\n+ * the result set will present items in that order.  For many recommenders, this will be descending order\n+ * by score; however, this interface does not guarantee a relationship between scores and ordering.\n+ *\n+ * @compat Public\n+ */\n+public interface ItemRecommender {\n+    /**\n+     * Recommend all possible items for a user using the default exclude set.\n+     *\n+     * @param user The user ID.\n+     * @return The recommended items.\n+     * @see #recommend(long, int, Set, Set)\n+     */\n+    ResultList recommend(long user);\n+\n+    /**\n+     * Recommend up to <var>n</var> items for a user using the default exclude\n+     * set.\n+     *\n+     * @param user The user ID.\n+     * @param n    The number of recommendations to return.\n+     * @return The recommended items.\n+     * @see #recommend(long, int, Set, Set)\n+     */\n+    ResultList recommend(long user, int n);\n+\n+    /**\n+     * Recommend all possible items for a user from a set of candidates using\n+     * the default exclude set.\n+     *\n+     * @param user       The user ID.\n+     * @param candidates The candidate set (can be null to represent the\n+     *                   universe).\n+     * @return The recommended items.\n+     * @see #recommend(long, int, Set, Set)\n+     */\n+    ResultList recommend(long user, @Nullable Set<Long> candidates);\n+\n+    /**\n+     * Produce a set of recommendations for the user. This is the most general\n+     * recommendation method, allowing the recommendations to be constrained by\n+     * both a candidate set and an exclude set. The exclude set is applied to\n+     * the candidate set, so the final effective candidate set is\n+     * <var>canditates</var> minus <var>exclude</var>.\n+     *\n+     * @param user       The user's ID\n+     * @param n          The number of ratings to return. If negative, there is\n+     *                   no specific recommendation list size requested.\n+     * @param candidates A set of candidate items which can be recommended. If\n+     *                   {@code null}, all items are considered candidates.\n+     * @param exclude    A set of items to be excluded. If {@code null}, a default\n+     *                   exclude set is used.\n+     * @return A list of recommended items. If the recommender cannot assign\n+     *         meaningful scores, the scores will be {@link Double#NaN}. For\n+     *         most scoring recommenders, the items will be ordered in\n+     *         decreasing order of score. This is not a hard requirement — e.g.\n+     *         set recommenders are allowed to be more flexible.\n+     */\n+    ResultList recommend(long user, int n, @Nullable Set<Long> candidates,\n+                                 @Nullable Set<Long> exclude);\n+\n+    /**\n+     * Produce a set of recommendations for the user with additional details. This method functions identically to\n+     * {@link #recommend(long, int, Set, Set)}, except that it may produce more detailed results. Implementations will\n+     * return subclasses of {@link ResultList} that provide access to additional details about each recommendation.\n+     *\n+     * @param user       The user's ID\n+     * @param n          The number of ratings to return. If negative, there is\n+     *                   no specific recommendation list size requested.\n+     * @param candidates A set of candidate items which can be recommended. If\n+     *                   {@code null}, all items are considered candidates.\n+     * @param exclude    A set of items to be excluded. If {@code null}, a default\n+     *                   exclude set is used.\n+     * @return A list of recommended items. If the recommender cannot assign\n+     *         meaningful scores, the scores will be {@link Double#NaN}. For\n+     *         most scoring recommenders, the items will be ordered in\n+     *         decreasing order of score. This is not a hard requirement — e.g.\n+     *         set recommenders are allowed to be more flexible.\n+     */\n+    ResultList recommendWithDetails(long user, int n, @Nullable Set<Long> candidates,","path":"lenskit-api/src/main/java/org/lenskit/api/ItemRecommender.java","position":131,"original_position":131,"commit_id":"07ddd8fa1aa52a207a3eda7bb47c228400f94ffa","original_commit_id":"07ddd8fa1aa52a207a3eda7bb47c228400f94ffa","user":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"body":"But I think I will do it anyway.","created_at":"2015-06-08T21:08:32Z","updated_at":"2015-06-08T21:08:32Z","html_url":"https://github.com/lenskit/lenskit/pull/733#discussion_r31959700","pull_request_url":"https://api.github.com/repos/lenskit/lenskit/pulls/733","_links":{"self":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/comments/31959700"},"html":{"href":"https://github.com/lenskit/lenskit/pull/733#discussion_r31959700"},"pull_request":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733"}}},"pull_request":{"url":"https://api.github.com/repos/lenskit/lenskit/pulls/733","id":35973332,"html_url":"https://github.com/lenskit/lenskit/pull/733","diff_url":"https://github.com/lenskit/lenskit/pull/733.diff","patch_url":"https://github.com/lenskit/lenskit/pull/733.patch","issue_url":"https://api.github.com/repos/lenskit/lenskit/issues/733","number":733,"state":"open","locked":false,"title":"Create result set APIs","user":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"body":"This works on #727.\r\n\r\nWe are not ready to merge this - it is just interfaces. However, I would like to think about interfaces before taking the time to implement.\r\n\r\nThe idea here is that (almost) all recommendation operations return a *result set*: a (possibly ordered) map of item (or user, for finding related users) IDs to values. Individual algorithms can extend the result set to provide additional details (see [DetailedResults](//github.com/lenskit/lenskit/wiki/DetailedResults)).\r\n\r\nFor recommendation, the result set will be ordered in decreasing order of score.\r\n\r\nThis subsumes both `SparseVector` and `List<ScoredId>` for recommendation and prediction results.","created_at":"2015-05-21T20:21:01Z","updated_at":"2015-06-08T21:08:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5b0f485b5ee5ec54267018d25a2279821e868f75","assignee":{"login":"kluver","id":5695556,"avatar_url":"https://avatars.githubusercontent.com/u/5695556?v=3","gravatar_id":"","url":"https://api.github.com/users/kluver","html_url":"https://github.com/kluver","followers_url":"https://api.github.com/users/kluver/followers","following_url":"https://api.github.com/users/kluver/following{/other_user}","gists_url":"https://api.github.com/users/kluver/gists{/gist_id}","starred_url":"https://api.github.com/users/kluver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kluver/subscriptions","organizations_url":"https://api.github.com/users/kluver/orgs","repos_url":"https://api.github.com/users/kluver/repos","events_url":"https://api.github.com/users/kluver/events{/privacy}","received_events_url":"https://api.github.com/users/kluver/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/lenskit/lenskit/milestones/23","html_url":"https://github.com/lenskit/lenskit/milestones/3.0","labels_url":"https://api.github.com/repos/lenskit/lenskit/milestones/23/labels","id":433278,"number":23,"title":"3.0","description":"LensKit 3.0, upcoming major change + long-term stable version.","creator":null,"open_issues":59,"closed_issues":25,"state":"open","created_at":"2013-09-21T00:54:48Z","updated_at":"2015-06-05T16:58:35Z","due_on":"2015-07-31T05:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/lenskit/lenskit/pulls/733/commits","review_comments_url":"https://api.github.com/repos/lenskit/lenskit/pulls/733/comments","review_comment_url":"https://api.github.com/repos/lenskit/lenskit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lenskit/lenskit/issues/733/comments","statuses_url":"https://api.github.com/repos/lenskit/lenskit/statuses/07ddd8fa1aa52a207a3eda7bb47c228400f94ffa","head":{"label":"mdekstrand:feature/727-result-api","ref":"feature/727-result-api","sha":"07ddd8fa1aa52a207a3eda7bb47c228400f94ffa","user":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"repo":{"id":12954960,"name":"lenskit","full_name":"mdekstrand/lenskit","owner":{"login":"mdekstrand","id":186612,"avatar_url":"https://avatars.githubusercontent.com/u/186612?v=3","gravatar_id":"","url":"https://api.github.com/users/mdekstrand","html_url":"https://github.com/mdekstrand","followers_url":"https://api.github.com/users/mdekstrand/followers","following_url":"https://api.github.com/users/mdekstrand/following{/other_user}","gists_url":"https://api.github.com/users/mdekstrand/gists{/gist_id}","starred_url":"https://api.github.com/users/mdekstrand/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mdekstrand/subscriptions","organizations_url":"https://api.github.com/users/mdekstrand/orgs","repos_url":"https://api.github.com/users/mdekstrand/repos","events_url":"https://api.github.com/users/mdekstrand/events{/privacy}","received_events_url":"https://api.github.com/users/mdekstrand/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mdekstrand/lenskit","description":"LensKit recommender toolkit (Michael's work-in-progress fork, feature branches may be rebased).","fork":true,"url":"https://api.github.com/repos/mdekstrand/lenskit","forks_url":"https://api.github.com/repos/mdekstrand/lenskit/forks","keys_url":"https://api.github.com/repos/mdekstrand/lenskit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mdekstrand/lenskit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mdekstrand/lenskit/teams","hooks_url":"https://api.github.com/repos/mdekstrand/lenskit/hooks","issue_events_url":"https://api.github.com/repos/mdekstrand/lenskit/issues/events{/number}","events_url":"https://api.github.com/repos/mdekstrand/lenskit/events","assignees_url":"https://api.github.com/repos/mdekstrand/lenskit/assignees{/user}","branches_url":"https://api.github.com/repos/mdekstrand/lenskit/branches{/branch}","tags_url":"https://api.github.com/repos/mdekstrand/lenskit/tags","blobs_url":"https://api.github.com/repos/mdekstrand/lenskit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mdekstrand/lenskit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mdekstrand/lenskit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mdekstrand/lenskit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mdekstrand/lenskit/statuses/{sha}","languages_url":"https://api.github.com/repos/mdekstrand/lenskit/languages","stargazers_url":"https://api.github.com/repos/mdekstrand/lenskit/stargazers","contributors_url":"https://api.github.com/repos/mdekstrand/lenskit/contributors","subscribers_url":"https://api.github.com/repos/mdekstrand/lenskit/subscribers","subscription_url":"https://api.github.com/repos/mdekstrand/lenskit/subscription","commits_url":"https://api.github.com/repos/mdekstrand/lenskit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mdekstrand/lenskit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mdekstrand/lenskit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mdekstrand/lenskit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mdekstrand/lenskit/contents/{+path}","compare_url":"https://api.github.com/repos/mdekstrand/lenskit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mdekstrand/lenskit/merges","archive_url":"https://api.github.com/repos/mdekstrand/lenskit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mdekstrand/lenskit/downloads","issues_url":"https://api.github.com/repos/mdekstrand/lenskit/issues{/number}","pulls_url":"https://api.github.com/repos/mdekstrand/lenskit/pulls{/number}","milestones_url":"https://api.github.com/repos/mdekstrand/lenskit/milestones{/number}","notifications_url":"https://api.github.com/repos/mdekstrand/lenskit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mdekstrand/lenskit/labels{/name}","releases_url":"https://api.github.com/repos/mdekstrand/lenskit/releases{/id}","created_at":"2013-09-19T17:41:33Z","updated_at":"2015-05-05T20:43:43Z","pushed_at":"2015-06-05T20:52:18Z","git_url":"git://github.com/mdekstrand/lenskit.git","ssh_url":"git@github.com:mdekstrand/lenskit.git","clone_url":"https://github.com/mdekstrand/lenskit.git","svn_url":"https://github.com/mdekstrand/lenskit","homepage":"","size":21295,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"lenskit:master","ref":"master","sha":"fbd5b393b2159351496155da5d4f8947b22fd136","user":{"login":"lenskit","id":7562892,"avatar_url":"https://avatars.githubusercontent.com/u/7562892?v=3","gravatar_id":"","url":"https://api.github.com/users/lenskit","html_url":"https://github.com/lenskit","followers_url":"https://api.github.com/users/lenskit/followers","following_url":"https://api.github.com/users/lenskit/following{/other_user}","gists_url":"https://api.github.com/users/lenskit/gists{/gist_id}","starred_url":"https://api.github.com/users/lenskit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lenskit/subscriptions","organizations_url":"https://api.github.com/users/lenskit/orgs","repos_url":"https://api.github.com/users/lenskit/repos","events_url":"https://api.github.com/users/lenskit/events{/privacy}","received_events_url":"https://api.github.com/users/lenskit/received_events","type":"Organization","site_admin":false},"repo":{"id":12953256,"name":"lenskit","full_name":"lenskit/lenskit","owner":{"login":"lenskit","id":7562892,"avatar_url":"https://avatars.githubusercontent.com/u/7562892?v=3","gravatar_id":"","url":"https://api.github.com/users/lenskit","html_url":"https://github.com/lenskit","followers_url":"https://api.github.com/users/lenskit/followers","following_url":"https://api.github.com/users/lenskit/following{/other_user}","gists_url":"https://api.github.com/users/lenskit/gists{/gist_id}","starred_url":"https://api.github.com/users/lenskit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lenskit/subscriptions","organizations_url":"https://api.github.com/users/lenskit/orgs","repos_url":"https://api.github.com/users/lenskit/repos","events_url":"https://api.github.com/users/lenskit/events{/privacy}","received_events_url":"https://api.github.com/users/lenskit/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/lenskit/lenskit","description":"LensKit recommender toolkit.","fork":false,"url":"https://api.github.com/repos/lenskit/lenskit","forks_url":"https://api.github.com/repos/lenskit/lenskit/forks","keys_url":"https://api.github.com/repos/lenskit/lenskit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lenskit/lenskit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lenskit/lenskit/teams","hooks_url":"https://api.github.com/repos/lenskit/lenskit/hooks","issue_events_url":"https://api.github.com/repos/lenskit/lenskit/issues/events{/number}","events_url":"https://api.github.com/repos/lenskit/lenskit/events","assignees_url":"https://api.github.com/repos/lenskit/lenskit/assignees{/user}","branches_url":"https://api.github.com/repos/lenskit/lenskit/branches{/branch}","tags_url":"https://api.github.com/repos/lenskit/lenskit/tags","blobs_url":"https://api.github.com/repos/lenskit/lenskit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lenskit/lenskit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lenskit/lenskit/git/refs{/sha}","trees_url":"https://api.github.com/repos/lenskit/lenskit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lenskit/lenskit/statuses/{sha}","languages_url":"https://api.github.com/repos/lenskit/lenskit/languages","stargazers_url":"https://api.github.com/repos/lenskit/lenskit/stargazers","contributors_url":"https://api.github.com/repos/lenskit/lenskit/contributors","subscribers_url":"https://api.github.com/repos/lenskit/lenskit/subscribers","subscription_url":"https://api.github.com/repos/lenskit/lenskit/subscription","commits_url":"https://api.github.com/repos/lenskit/lenskit/commits{/sha}","git_commits_url":"https://api.github.com/repos/lenskit/lenskit/git/commits{/sha}","comments_url":"https://api.github.com/repos/lenskit/lenskit/comments{/number}","issue_comment_url":"https://api.github.com/repos/lenskit/lenskit/issues/comments{/number}","contents_url":"https://api.github.com/repos/lenskit/lenskit/contents/{+path}","compare_url":"https://api.github.com/repos/lenskit/lenskit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lenskit/lenskit/merges","archive_url":"https://api.github.com/repos/lenskit/lenskit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lenskit/lenskit/downloads","issues_url":"https://api.github.com/repos/lenskit/lenskit/issues{/number}","pulls_url":"https://api.github.com/repos/lenskit/lenskit/pulls{/number}","milestones_url":"https://api.github.com/repos/lenskit/lenskit/milestones{/number}","notifications_url":"https://api.github.com/repos/lenskit/lenskit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lenskit/lenskit/labels{/name}","releases_url":"https://api.github.com/repos/lenskit/lenskit/releases{/id}","created_at":"2013-09-19T16:19:33Z","updated_at":"2015-06-05T21:33:19Z","pushed_at":"2015-06-05T20:52:19Z","git_url":"git://github.com/lenskit/lenskit.git","ssh_url":"git@github.com:lenskit/lenskit.git","clone_url":"https://github.com/lenskit/lenskit.git","svn_url":"https://github.com/lenskit/lenskit","homepage":"http://lenskit.grouplens.org","size":25687,"stargazers_count":311,"watchers_count":311,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":137,"mirror_url":null,"open_issues_count":124,"forks":137,"open_issues":124,"watchers":311,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733"},"html":{"href":"https://github.com/lenskit/lenskit/pull/733"},"issue":{"href":"https://api.github.com/repos/lenskit/lenskit/issues/733"},"comments":{"href":"https://api.github.com/repos/lenskit/lenskit/issues/733/comments"},"review_comments":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733/comments"},"review_comment":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lenskit/lenskit/pulls/733/commits"},"statuses":{"href":"https://api.github.com/repos/lenskit/lenskit/statuses/07ddd8fa1aa52a207a3eda7bb47c228400f94ffa"}}}}