/* * Copyright (c) 2013 LDBC * Linked Data Benchmark Council (http://ldbc.eu) * * This file is part of ldbc_socialnet_dbgen. * * ldbc_socialnet_dbgen is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ldbc_socialnet_dbgen 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ldbc_socialnet_dbgen. If not, see <http://www.gnu.org/licenses/>. * * Copyright (C) 2011 OpenLink Software <bdsmt@openlinksw.com> * All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; only Version 2 of the License dated * June 1991. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package ldbc.snb.datagen.dictionary; import ldbc.snb.datagen.generator.DateGenerator; import ldbc.snb.datagen.generator.PowerDistGenerator; import ldbc.snb.datagen.objects.FlashmobTag; import java.util.*; public class FlashmobTagDictionary { private DateGenerator dateGen; /** * < @brief The date generator used to generate dates. */ private PowerDistGenerator levelGenerator; /** * < @brief The powerlaw distribution generator used to generate the levels. */ private Random random; /** * < @brief A uniform random genereator. */ private TagDictionary tagDictionary; /** * < @brief The tag dictionary used to create the flashmob tags. */ private HashMap<Integer, ArrayList<FlashmobTag>> flashmobTags; /** * < @brief A map of identifiers of tags to flashmob tag instances. */ private FlashmobTag[] flashmobTagCumDist; /** * < @brief The cumulative distribution of flashmob tags sorted by date. */ private double flashmobTagsPerMonth; /** * < @brief The number of flashmob tags per month. */ private double probInterestFlashmobTag; /** * < @brief The probability to take an interest flashmob tag. */ private double probRandomPerLevel; /** * < @brief The probability per level to take a flashmob tag. */ public FlashmobTagDictionary(TagDictionary tagDictionary, DateGenerator dateGen, int flashmobTagsPerMonth, double probInterestFlashmobTag, double probRandomPerLevel, double flashmobTagMinLevel, double flashmobTagMaxLevel, double flashmobTagDistExp) { this.tagDictionary = tagDictionary; this.dateGen = dateGen; this.levelGenerator = new PowerDistGenerator(flashmobTagMinLevel, flashmobTagMaxLevel, flashmobTagDistExp); this.random = new Random(0); this.flashmobTags = new HashMap<Integer, ArrayList<FlashmobTag>>(); this.flashmobTagsPerMonth = flashmobTagsPerMonth; this.probInterestFlashmobTag = probInterestFlashmobTag; this.probRandomPerLevel = probRandomPerLevel; initialize(); } /** * @brief Initializes the flashmob tag dictionary, by selecting a set of tags as flashmob tags. */ private void initialize() { int numFlashmobTags = (int) (flashmobTagsPerMonth * dateGen.numberOfMonths(dateGen.getStartDateTime())); Integer[] tags = tagDictionary.getRandomTags(random, numFlashmobTags); flashmobTagCumDist = new FlashmobTag[numFlashmobTags]; double sumLevels = 0; for (int i = 0; i < numFlashmobTags; ++i) { ArrayList<FlashmobTag> instances = flashmobTags.get(tags[i]); if (instances == null) { instances = new ArrayList<FlashmobTag>(); flashmobTags.put(tags[i], instances); } FlashmobTag flashmobTag = new FlashmobTag(); flashmobTag.date = dateGen.randomDate(random, dateGen.getStartDateTime()); flashmobTag.level = levelGenerator.getValue(random); sumLevels += flashmobTag.level; flashmobTag.tag = tags[i]; instances.add(flashmobTag); flashmobTagCumDist[i] = flashmobTag; // if(tags[i] == 1761) System.out.println(flashmobTag); } Arrays.sort(flashmobTagCumDist); int size = flashmobTagCumDist.length; double currentProb = 0.0; for (int i = 0; i < size; ++i) { flashmobTagCumDist[i].prob = currentProb; currentProb += (double) (flashmobTagCumDist[i].level) / (double) (sumLevels); } } /** * @return The index to the earliest flashmob tag. * @brief Selects the earliest flashmob tag index from a given date. * @param[in] fromDate The minimum date to consider. */ private int searchEarliestIndex(long fromDate) { int lowerBound = 0; int upperBound = flashmobTagCumDist.length; int midPoint = (upperBound + lowerBound) / 2; while (upperBound > (lowerBound + 1)) { if (flashmobTagCumDist[midPoint].date > fromDate) { upperBound = midPoint; } else { lowerBound = midPoint; } midPoint = (upperBound + lowerBound) / 2; } return midPoint; } /** * @return true if the flashmob tag is selected. false otherwise. * @brief Makes a decision of selecting or not a flashmob tag. * @param[in] index The index of the flashmob tag to select. */ private boolean selectFlashmobTag(Random rand, int index) { return rand.nextDouble() > (1 - probRandomPerLevel * flashmobTagCumDist[index].level); } /** * @return A vector containing the selected flashmob tags. * @brief Given a set of interests and a date, generates a set of flashmob tags. * @param[in] interests The set of interests. * @param[in] fromDate The date from which to consider the flashmob tags. */ public ArrayList<FlashmobTag> generateFlashmobTags(Random rand, TreeSet<Integer> interests, long fromDate) { ArrayList<FlashmobTag> result = new ArrayList<FlashmobTag>(); Iterator<Integer> it = interests.iterator(); while (it.hasNext()) { Integer tag = it.next(); ArrayList<FlashmobTag> instances = flashmobTags.get(tag); if (instances != null) { Iterator<FlashmobTag> it2 = instances.iterator(); while (it2.hasNext()) { FlashmobTag instance = it2.next(); if (instance.date >= fromDate) { if (rand.nextDouble() > 1 - probInterestFlashmobTag) { result.add(instance); } } } } } int earliestIndex = searchEarliestIndex(fromDate); for (int i = earliestIndex; i < flashmobTagCumDist.length; ++i) { if (selectFlashmobTag(rand,i)) { result.add(flashmobTagCumDist[i]); } } return result; } public FlashmobTag[] getFlashmobTags() { return flashmobTagCumDist; } }