/// <summary> /// Extension of the add default method. If the dictionary does not contains the clound, a single point cloud is added /// and the associated value is the point. If the dictionary contains the key, the values are added and the /// key is unchanged. /// </summary> /// <param name="clouds">The clouds of points</param> /// <param name="key">The key of a cloud</param> /// <param name="weightedPoint">The point to add to the cloud</param> public static void TryAdd(this Dictionary<string, StreamingCloud> clouds, string key, WeightedPoint weightedPoint) { if (clouds.ContainsKey(key)) { clouds[key].Add(weightedPoint); } else { StreamingCloud sc = new StreamingCloud(); sc.Add(weightedPoint); clouds.Add(key, sc); } }
/// <summary> /// Returns the Haversine distance between two weighted points. /// </summary> /// <param name="p1">First point</param> /// <param name="p2">Second point</param> /// <returns>Haversine's (geodesic) distance</returns> public static double Haversine(WeightedPoint p1, WeightedPoint p2) { double lat = Math.Abs(p1.X - p2.X) * _pi180, lon = Math.Abs(p1.Y - p2.Y) * _pi180; double lat1 = p1.X * _pi180, lat2 = p2.X * _pi180; double a = Math.Sin(lat / 2) * Math.Sin(lat / 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(lon / 2) * Math.Sin(lon / 2); double Hdist = REarth * 2f * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); return Hdist; }
/// <summary> /// Adds a point to a streaming cloud : the mean and variance of the clouds are updated. /// </summary> /// <param name="point">The point to add to the cloud.</param> public void Add(WeightedPoint point) { _nbPoints++; if (_barycenter == null) { _barycenter = new WeightedPoint(point.X, point.Y, 1); _dispersion = 0; } else { _barycenter = _barycenter.Multiply(_nbPoints - 1); _barycenter = _barycenter.Add(point); _barycenter = _barycenter.Divide(_nbPoints); _dispersion = (_dispersion * (_nbPoints - 1) + Distances.Euclide(_barycenter, point)) / _nbPoints; } }
/// <summary> /// Yields the lines from a file as predictors and final point (if train set) /// </summary> /// <param name="filePath">The training file path (after feature extraction).</param> /// <param name="train">Set to true for train files, to return the final points as labels.</param> /// <param name="learningParameters">The learning parameters.</param> /// <returns></returns> private IEnumerable<Tuple<WeightedPoint, List<string>>> YieldLines(string filePath, bool train, LearningParameters learningParameters) { using (StreamReader reader = new StreamReader(filePath)) { string line = ""; //No header in feature files while ((line = reader.ReadLine()) != null) { List<string> arrayLine = line.Split(',').ToList(); WeightedPoint bv = new WeightedPoint(0, 0, 0); if (train) { string[] bidimVector = arrayLine[0].Split('_'); bv = new WeightedPoint(Convert.ToDouble(bidimVector[0], CultureInfo.GetCultureInfo("en-US")), Convert.ToDouble(bidimVector[1], CultureInfo.GetCultureInfo("en-US")), 1); arrayLine.RemoveAt(0); } arrayLine = arrayLine.CartesianProduct(learningParameters.Keyword); yield return new Tuple<WeightedPoint, List<string>>(bv, arrayLine); } } }
private WeightedPoint PredictFromLine(Dictionary<string, StreamingCloud> clouds, List<string> predictors, LearningParameters predictionParameters) { List<WeightedPoint> bvs = new List<WeightedPoint>(); foreach (string predictor in predictors) if (clouds.ContainsKey(predictor) && clouds[predictor].Size > predictionParameters.MinOccurences && clouds[predictor].Size < predictionParameters.MaxOccurences) { StreamingCloud cloud = clouds[predictor]; WeightedPoint wp = new WeightedPoint(cloud.Barycenter); wp.Weight = Math.Pow(cloud.Size, predictionParameters.SizeExponent) / Math.Pow(cloud.Dispersion, predictionParameters.DispersionExponent); bvs.Add(wp); } if (bvs.Count == 0) // could not find any predictor respecting the learning conditions return new WeightedPoint(-8.611317, 41.146504, 1); return WeightedPoint.Barycenter(bvs); }
/// <summary> /// (Deep) copy constructor of a weighted point. /// </summary> /// <param name="wp">Weighted point to copy.</param> public WeightedPoint(WeightedPoint wp) { _x = wp.X; _y = wp.Y; _weight = wp.Weight; }
/// <summary> /// Performs \f$(x_1+x_2,y_1+y_2,m_1+m_2)\f$. /// </summary> /// <param name="p2">The point to add.</param> /// <returns>(x_1+x_2,y_1+y_2,m_1+m_2).</returns> public WeightedPoint Add(WeightedPoint p2) { return new WeightedPoint(_x + p2.X , _y + p2.Y , _weight + p2.Weight); }
/// <summary> /// Given a list of WeightedPoints returns. /// </summary> /// <param name="weightedPoints">Weighted points to average.</param> /// <returns>The barycenter of the input points.</returns> public static WeightedPoint Barycenter(IList<WeightedPoint> weightedPoints) { WeightedPoint res = new WeightedPoint(); double counter = 0; foreach (WeightedPoint pt in weightedPoints) { res = res.Add(pt.Multiply(pt.Weight)); counter += pt.Weight; } res = res.Divide(counter); return res; }
/// <summary> /// Returns the Euclide distance between two weighted points. /// </summary> /// <param name="p1">First point</param> /// <param name="p2">Second point</param> /// <returns>Euclide's distance</returns> public static double Euclide(WeightedPoint p1, WeightedPoint p2) { return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y)); }