/* TagRecommender: A framework to implement and evaluate algorithms for the recommendation of tags. Copyright (C) 2013 Dominik Kowald This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package engine; import common.DoubleMapComparator; import common.Utilities; import file.BookmarkReader; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; public class LanguageModelEngine implements EngineInterface { private BookmarkReader reader; private final Map<String, Map<Integer, Double>> userMaps; private final Map<String, Map<Integer, Double>> resMaps; private final Map<Integer, Double> topTags; public LanguageModelEngine() { this.userMaps = new HashMap<>(); this.resMaps = new HashMap<>(); topTags = new LinkedHashMap<>(); reader = null; } public void loadFile(String path, String filename) throws Exception { BookmarkReader reader = EngineUtils.getSortedBookmarkReader(path, filename); Map<String, Map<Integer, Double>> userMaps = new HashMap<>(); Map<String, Map<Integer, Double>> resMaps = new HashMap<>(); List<Map<Integer, Double>> userStats = Utilities.getNormalizedMaps(reader.getBookmarks(), false); int i = 0; for (Map<Integer, Double> map : userStats) { //Map<Integer, Double> resultMap = new HashMap<>(); //for (Map.Entry<Integer, Integer> entry : map.entrySet()) { // resultMap.put(entry.getKey(), (double) entry.getValue() / (double) Utilities.getMapCount(map)); //} userMaps.put(reader.getUsers().get(i++), map); } List<Map<Integer, Double>> resStats = Utilities.getNormalizedMaps(reader.getBookmarks(), true); i = 0; for (Map<Integer, Double> map : resStats) { //Map<Integer, Double> resultMap = new HashMap<>(); //for (Map.Entry<Integer, Integer> entry : map.entrySet()) { // resultMap.put(entry.getKey(), (double) entry.getValue() / (double) Utilities.getMapCount(map)); //} resMaps.put(reader.getResources().get(i++), map); } Map<Integer, Double> topTags = EngineUtils.calcTopEntities(reader, EntityType.TAG); resetStructures(userMaps, resMaps, reader, topTags); } public synchronized Map<String, Double> getEntitiesWithLikelihood(String user, String resource, List<String> topics, Integer count, Boolean filterOwnEntities, Algorithm algorithm, EntityType type) { if (count == null || count.doubleValue() < 1) { count = 10; } Map<Integer, Double> userMap = this.userMaps.get(user); if (filterOwnEntities == null) { filterOwnEntities = true; } List<Integer> filterTags = EngineUtils.getFilterTags(filterOwnEntities, this.reader, user, resource); Map<Integer, Double> resultMap = new LinkedHashMap<Integer, Double>(); if (algorithm == null || algorithm != Algorithm.MP) { Map<Integer, Double> resMap = this.resMaps.get(resource); if ((algorithm == null || algorithm == Algorithm.MPu || algorithm == Algorithm.MPur) && userMap != null) { for (Map.Entry<Integer, Double> entry : userMap.entrySet()) { if (!filterTags.contains(entry.getKey())) { resultMap.put(entry.getKey(), entry.getValue().doubleValue()); } } } if ((algorithm == null || algorithm == Algorithm.MPr || algorithm == Algorithm.MPur) && resMap != null) { for (Map.Entry<Integer, Double> entry : resMap.entrySet()) { if (!filterTags.contains(entry.getKey())) { double resVal = entry.getValue().doubleValue(); Double val = resultMap.get(entry.getKey()); resultMap.put(entry.getKey(), val == null ? resVal : val.doubleValue() + resVal); } } } } // add MP tags if necessary if (resultMap.size() < count) { for (Map.Entry<Integer, Double> t : this.topTags.entrySet()) { if (resultMap.size() < count) { if (!resultMap.containsKey(t.getKey()) && !filterTags.contains(t.getKey())) { resultMap.put(t.getKey(), t.getValue()); } } else { break; } } } // sort Map<Integer, Double> sortedResultMap = new TreeMap<Integer, Double>(new DoubleMapComparator(resultMap)); sortedResultMap.putAll(resultMap); // map tag-IDs back to strings int i = 0; Map<String, Double> tagMap = new LinkedHashMap<>(); for (Map.Entry<Integer, Double> entry : sortedResultMap.entrySet()) { if (i++ < count) { tagMap.put(this.reader.getTags().get(entry.getKey()), (double) entry.getValue()); } else { break; } } return tagMap; } private synchronized void resetStructures(Map<String, Map<Integer, Double>> userMaps, Map<String, Map<Integer, Double>> resMaps, BookmarkReader reader, Map<Integer, Double> topTags) { this.reader = reader; this.userMaps.clear(); this.userMaps.putAll(userMaps); this.resMaps.clear(); this.resMaps.putAll(resMaps); this.topTags.clear(); this.topTags.putAll(topTags); } }