/// <summary> /// Returns a computational context which is a set of nodes and a set "weights" to apply to the nodes to form a linear combination to get the mean value of the cells /// </summary> public async Task <LinearCombinationContext> CreateAsync(IEnumerable <ICellRequest> cells) { Stopwatch sw = Stopwatch.StartNew(); var tsAveragerTask = timeSeriesAveragerFactory.CreateAsync(); var liTask = linearInterpolatorFactory.CreateAsync(); var tsAverager = await tsAveragerTask; var linearInterpolator = await liTask; sw.Stop(); traceSource.TraceEvent(TraceEventType.Verbose, 1, "Time series averager and lenear interpolator constructed in {0}", sw.Elapsed); sw = Stopwatch.StartNew(); var resultTasks = cells.Select <ICellRequest, Task <Tuple <ICellRequest, RealValueNodes, IEnumerable <LinearWeight> > > >(async c => { var tsa = (RealValueNodes)(await tsAverager.GetAsync(c)); var w = (IEnumerable <LinearWeight>)(await linearInterpolator.GetLinearWeigthsAsync(tsa, c)); return(Tuple.Create(c, tsa, w)); }).ToArray(); var result = await Task.WhenAll(resultTasks); sw.Stop(); traceSource.TraceEvent(TraceEventType.Verbose, 2, "Linear weights for {0} cells prepared in {1}", resultTasks.Length, sw.Elapsed); LinearCombinationContext lcc = new LinearCombinationContext(result); return(lcc); }
public async Task LinearCombinationAggregatorTest() { LinearCombinationAggregator lca = new LinearCombinationAggregator(); var nodes = new RealValueNodes(new double[3], new double[3], new double[] { 2.0, 3.0, 5.0 }); var weights = new LinearWeight[] { new LinearWeight(1, 7.0), new LinearWeight(0, 11.0), new LinearWeight(2, 13.0) }; LinearCombinationContext lcc = new LinearCombinationContext(new Tuple <ICellRequest, RealValueNodes, IEnumerable <LinearWeight> >[] { new Tuple <ICellRequest, RealValueNodes, IEnumerable <LinearWeight> >(new RequestStubs(), nodes, (IEnumerable <LinearWeight>)weights) }); double[] result = await lca.AggregateCellsBatchAsync(lcc, new ICellRequest[] { new RequestStubs() }); Assert.AreEqual(1, result.Length); Assert.AreEqual(108, result[0]); }
public async Task <double[]> EvaluateCellsBatchAsync(LinearCombinationContext computationalContext, IEnumerable <ICellRequest> cells) { var variogramProvider = await variogramProviderFactory.ConstructAsync(); var combinationsIterator = computationalContext.Combinations.GetEnumerator(); traceSource.TraceEvent(TraceEventType.Start, 1, "Filtering out cells that are not requested"); var filtered = cells.Select(cell => { Tuple <ICellRequest, RealValueNodes, IEnumerable <LinearWeight> > currentElement; ICellRequest contextCell; do { var nextExists = combinationsIterator.MoveNext(); if (!nextExists) { throw new InvalidOperationException("Received linear combination does not containg information about requested cell. Context is not synchronize with requested cells sequenece."); } currentElement = combinationsIterator.Current; contextCell = currentElement.Item1; } while (!contextCell.Equals(cell)); return(currentElement); }).ToArray(); traceSource.TraceEvent(TraceEventType.Stop, 1, "Filtered out cells that are not requested"); traceSource.TraceEvent(TraceEventType.Start, 2, "Evaluating uncertatinty for sequence of cells using precomputed linear combinations"); var resultsTasks = filtered.AsParallel().AsOrdered().Select(async tuple => { if (tuple.Item2.Lats.Length == 0) { return(Double.NaN); //there are no nodes. Out of data request? can't produce uncertainty } var variogram = await variogramProvider.GetSpatialVariogramAsync(tuple.Item2); var cell = tuple.Item1; var weights = tuple.Item3.ToArray(); var nodes = tuple.Item2; Debug.Assert(Math.Abs(weights.Sum(w => w.Weight) - 1.0) < 1e-10); double sill = variogram.Sill; double cellLat = (cell.LatMax + cell.LatMin) * 0.5; double cellLon = (cell.LonMax + cell.LonMin) * 0.5; //var = cov(0)+ sum sum (w[i]*w[j]*cov(i,j))-2.0*sum(w[i]*cov(x,i)) double cov_at_0 = sill; double acc = cov_at_0; //cov(0) for (int i = 0; i < weights.Length; i++) { double w = weights[i].Weight; int idx1 = weights[i].DataIndex; double lat1 = nodes.Lats[idx1]; double lon1 = nodes.Lons[idx1]; for (int j = 0; j < i; j++) { int idx2 = weights[j].DataIndex; double lat2 = nodes.Lats[idx2]; double lon2 = nodes.Lons[idx2]; double dist = SphereMath.GetDistance(lat1, lon1, lat2, lon2); double cov = sill - variogram.GetGamma(dist); acc += 2.0 * w * weights[j].Weight * cov; } acc += w * w * cov_at_0; //diagonal elements double dist2 = SphereMath.GetDistance(lat1, lon1, cellLat, cellLon); double cov2 = sill - variogram.GetGamma(dist2); acc -= 2.0 * w * cov2; } return(acc * 0.5); //as dealing with full variogram instead of semivariogram }).ToArray(); var results = await Task.WhenAll(resultsTasks); traceSource.TraceEvent(TraceEventType.Stop, 2, "Evaluated uncertatinty for sequence of cells using precomputed linear combinations"); return(results); }