/// <summary> /// Generates a list of orders and bundles. TODO this has to be adapted to handle simple items too. While doing so use a configuration for all the settings and feed it to the GUI. /// </summary> /// <param name="wordFile">The word file.</param> /// <param name="baseColors">The colors</param> /// <param name="baseColorProbabilities"></param> /// <param name="seed"></param> /// <param name="minTime"></param> /// <param name="maxTime"></param> /// <param name="orderCount"></param> /// <param name="minItemWeight"></param> /// <param name="maxItemWeight"></param> /// <param name="minPositionCount"></param> /// <param name="maxPositionCount"></param> /// <param name="minBundleSize"></param> /// <param name="maxBundleSize"></param> /// <param name="relativeBundleCount"></param> /// <returns></returns> public static OrderList GenerateOrders( string wordFile, LetterColors[] baseColors, IDictionary <LetterColors, double> baseColorProbabilities, int seed, double minTime, double maxTime, int orderCount, double minItemWeight, double maxItemWeight, int minPositionCount, int maxPositionCount, int minBundleSize, int maxBundleSize, double relativeBundleCount) { // Init random IRandomizer randomizer = new RandomizerSimple(seed); // Read the words that serve as the base for the item types List <string> baseWords = new List <string>(); using (StreamReader sr = new StreamReader(wordFile)) { string line = ""; while ((line = sr.ReadLine()) != null) { baseWords.Add(line.Trim()); } } baseWords = baseWords.Distinct().ToList(); List <char> baseLetters = baseWords.SelectMany(w => w.ToCharArray()).Distinct().ToList(); // --> Build all necessary item descriptions OrderList orderList = new OrderList(ItemType.Letter); int currentItemDescriptionID = 0; foreach (var letter in baseLetters) { foreach (var color in baseColors) { orderList.ItemDescriptions.Add(new ColoredLetterDescription(null) { ID = currentItemDescriptionID++, Color = color, Letter = letter, Weight = randomizer.NextDouble(minItemWeight, maxItemWeight) }); } } // --> Generate orders randomly for (int i = 0; i < orderCount; i++) { // Choose a random word from the list string word = baseWords[randomizer.NextInt(baseWords.Count)]; Order order = new Order() { TimeStamp = randomizer.NextDouble(minTime, maxTime) }; // Add each letter to originalLetters for (int j = 0; j < word.Length; j++) { // Get color based on distribution double r = randomizer.NextDouble(); // Choose a default one just incase LetterColors chosenColor = baseColors.First(); // Go through and check the range of each color, pulling random number down to the current range foreach (var c in baseColors) { if (baseColorProbabilities[c] > r) { chosenColor = c; break; } r -= baseColorProbabilities[c]; } // Add letter to order order.AddPosition( orderList.ItemDescriptions.Single(d => (d as ColoredLetterDescription).Letter == word[j] && (d as ColoredLetterDescription).Color == chosenColor), randomizer.NextInt(minPositionCount, maxPositionCount + 1)); } // Add the order orderList.Orders.Add(order); } // Get probability of item-descriptions Dictionary <ItemDescription, int> itemFrequency = orderList.Orders.SelectMany(o => o.Positions).GroupBy(p => p.Key).ToDictionary(i => i.Key, i => i.Sum(e => e.Value)); double overallCount = itemFrequency.Sum(f => f.Value); Dictionary <ItemDescription, double> itemProbability = itemFrequency.ToDictionary(k => k.Key, v => (double)itemFrequency[v.Key] / overallCount); // --> Generate appropriate bundles for this list int itemsOrdered = (int)(orderList.Orders.Sum(o => o.Positions.Sum(p => p.Value)) * relativeBundleCount); int newItems = 0; int currentBundleID = 0; for (int itemsStored = 0; itemsStored < itemsOrdered; itemsStored += newItems) { // Draw a random item description based on the frequency of the items ItemDescription newBundleDescription = RandomizerHelper.DrawRandomly <ItemDescription>(itemProbability, randomizer); int bundleSize = randomizer.NextInt(minBundleSize, maxBundleSize); double timeStamp = randomizer.NextDouble(minTime, maxTime); ColoredLetterBundle bundle = new ColoredLetterBundle(null) { ID = currentBundleID++, ItemDescription = newBundleDescription, TimeStamp = timeStamp, ItemCount = bundleSize }; // Add bundle to list orderList.Bundles.Add(bundle); // Signal new items newItems = bundleSize; } // Order the orders and bundles orderList.Sort(); // Return it return(orderList); }
/// <summary> /// Generates a complete configuration for the simple item generator. /// </summary> /// <param name="preConfig">The pre-configuration defining characteristics of the actual configuration.</param> /// <returns>The complete configuration.</returns> public static SimpleItemGeneratorConfiguration GenerateSimpleItemConfiguration(SimpleItemGeneratorPreConfiguration preConfig) { // Init SimpleItemGeneratorConfiguration config = new SimpleItemGeneratorConfiguration() { DefaultWeight = preConfig.DefaultWeight, DefaultCoWeight = preConfig.DefaultCoWeight, ProbToUseCoWeight = preConfig.ProbToUseCoWeight }; RandomizerSimple randomizer = new RandomizerSimple(0); List <SimpleItemDescription> itemDescriptions = new List <SimpleItemDescription>(); List <Tuple <SimpleItemDescription, double> > itemDescriptionWeights = new List <Tuple <SimpleItemDescription, double> >(); List <Tuple <SimpleItemDescription, SimpleItemDescription, double> > itemDescriptionCoWeights = new List <Tuple <SimpleItemDescription, SimpleItemDescription, double> >(); // Add comment config.Description = string.Join(",", typeof(SimpleItemGeneratorPreConfiguration).GetFields().Select(f => { string fieldValue; if (f.GetValue(preConfig) is double) { fieldValue = ((double)f.GetValue(preConfig)).ToString(IOConstants.FORMATTER); } else { fieldValue = f.GetValue(preConfig).ToString(); } return(f.Name + "=" + fieldValue); })); // Generate a set of item-descriptions for (int i = 0; i < preConfig.ItemDescriptionCount; i++) { // Generate next item SimpleItemDescription description = new SimpleItemDescription(null) { ID = i }; // Randomly weight the item double itemDescriptionWeight = 0; switch (preConfig.WeightDistributionType) { case ItemDescriptionWeightDistributionType.Normal: itemDescriptionWeight = randomizer.NextNormalDouble(preConfig.ItemWeightMu, preConfig.ItemWeightSigma, preConfig.ItemWeightLB, preConfig.ItemWeightUB); break; case ItemDescriptionWeightDistributionType.Uniform: itemDescriptionWeight = randomizer.NextDouble(preConfig.ItemWeightLB, preConfig.ItemWeightUB); break; default: throw new ArgumentException("Unknown distribution: " + preConfig.WeightDistributionType); } description.Weight = itemDescriptionWeight; // Randomly determine bundle size of the item if (preConfig.SupplyBundleSize) { int itemDescriptionBundleSize = 0; switch (preConfig.BundleSizeDistributionType) { case ItemDescriptionBundleSizeDistributionType.Normal: itemDescriptionBundleSize = randomizer.NextNormalInt(preConfig.BundleSizeMu, preConfig.BundleSizeSigma, preConfig.BundleSizeLB, preConfig.BundleSizeUB); break; case ItemDescriptionBundleSizeDistributionType.Uniform: itemDescriptionBundleSize = randomizer.NextInt(preConfig.BundleSizeLB, preConfig.BundleSizeUB + 1); break; default: throw new ArgumentException("Unknown distribution: " + preConfig.BundleSizeDistributionType); } description.BundleSize = itemDescriptionBundleSize; } // Add a random hue value to distinguish the item from others description.Hue = randomizer.NextDouble(360); // Add it itemDescriptions.Add(description); // Set a weight for the probability of the item double weight = 0; switch (preConfig.ProbWeightDistributionType) { case ItemDescriptionProbabilityWeightDistributionType.Constant: weight = preConfig.ProbabilityWeightConstant; break; case ItemDescriptionProbabilityWeightDistributionType.Uniform: weight = randomizer.NextDouble(preConfig.ProbabilityWeightUniformMin, preConfig.ProbabilityWeightUniformMax); break; case ItemDescriptionProbabilityWeightDistributionType.Normal: weight = randomizer.NextNormalDouble(preConfig.ProbabilityWeightNormalMu, preConfig.ProbabilityWeightNormalSigma, preConfig.ProbabilityWeightLB, preConfig.ProbabilityWeightUB); break; case ItemDescriptionProbabilityWeightDistributionType.Exponential: weight = randomizer.NextExponentialDouble(preConfig.ProbabilityWeightExpLambda, preConfig.ProbabilityWeightLB, preConfig.ProbabilityWeightUB); break; case ItemDescriptionProbabilityWeightDistributionType.Gamma: weight = randomizer.NextGammaDouble(preConfig.ProbabilityWeightGammaK, preConfig.ProbabilityWeightGammaTheta, preConfig.ProbabilityWeightLB, preConfig.ProbabilityWeightUB); break; default: throw new ArgumentException("Unknown distribution: " + preConfig.ProbWeightDistributionType); } itemDescriptionWeights.Add(new Tuple <SimpleItemDescription, double>(description, weight)); } // Equally distribute items over two-dimensional space Dictionary <SimpleItemDescription, Tuple <double, double> > itemDescriptionPosition = new Dictionary <SimpleItemDescription, Tuple <double, double> >(); foreach (var description in itemDescriptions) { itemDescriptionPosition[description] = new Tuple <double, double>(randomizer.NextDouble(), randomizer.NextDouble()); } // Plot the distribution for reference GnuPlotter.Plot2DPoints( "itemdistribution", new List <Tuple <string, IEnumerable <Tuple <double, double> > > >() { new Tuple <string, IEnumerable <Tuple <double, double> > >("Item locations in 2D", itemDescriptionPosition.Values) }, "item distribution for co-probability emulation"); // Set conditional weights double maxDistance = Distances.CalculateEuclid(0, 0, 1, 1); foreach (var description in itemDescriptions.OrderBy(d => randomizer.NextDouble()).Take((int)(itemDescriptions.Count * preConfig.GivenCoWeights))) { foreach (var otherDescription in itemDescriptions.OrderBy(d => randomizer.NextDouble()).Take((int)(itemDescriptions.Count * preConfig.GivenCoWeights))) { itemDescriptionCoWeights.Add(new Tuple <SimpleItemDescription, SimpleItemDescription, double>( description, otherDescription, maxDistance - Distances.CalculateEuclid( itemDescriptionPosition[description].Item1, itemDescriptionPosition[description].Item2, itemDescriptionPosition[otherDescription].Item1, itemDescriptionPosition[otherDescription].Item2))); } } // Submit all config.ItemDescriptions = itemDescriptions.Select(d => new Skvp <int, double>() { Key = d.ID, Value = d.Hue }).ToList(); config.ItemDescriptionWeights = itemDescriptions.Select(d => new Skvp <int, double>() { Key = d.ID, Value = d.Weight }).ToList(); if (preConfig.SupplyBundleSize) { config.ItemDescriptionBundleSizes = itemDescriptions.Select(d => new Skvp <int, int>() { Key = d.ID, Value = d.BundleSize }).ToList(); } config.ItemWeights = itemDescriptionWeights.Select(d => new Skvp <int, double>() { Key = d.Item1.ID, Value = d.Item2 }).ToList(); config.ItemCoWeights = itemDescriptionCoWeights.Select(d => new Skkvt <int, int, double>() { Key1 = d.Item1.ID, Key2 = d.Item2.ID, Value = d.Item3 }).ToList(); // Name it config.Name = config.GetMetaInfoBasedName(); // Return it return(config); }