private static DocumentCollection GetDocumentCollection( string collectionId, string partitionKey = null, IndexingMode indexingMode = IndexingMode.Consistent) { var documentCollection = new DocumentCollection(); documentCollection.Id = collectionId; var rangeIndex = new RangeIndex(DataType.String); rangeIndex.Precision = -1; var indexingPolicy = new IndexingPolicy(rangeIndex); indexingPolicy.IndexingMode = indexingMode; documentCollection.IndexingPolicy = indexingPolicy; if (partitionKey != null) { var partitionKeyDefinition = new PartitionKeyDefinition(); partitionKeyDefinition.Paths = new Collection <string> { partitionKey }; documentCollection.PartitionKey = partitionKeyDefinition; } return(documentCollection); }
private static DocumentCollection CreateCollection() { return(BinaryEncodingOverTheWireTests.Client.CreateDocumentCollectionAsync( UriFactory.CreateDatabaseUri(BinaryEncodingOverTheWireTests.database.Id), new DocumentCollection { Id = Guid.NewGuid().ToString() + "collection", IndexingPolicy = new IndexingPolicy { IncludedPaths = new Collection <IncludedPath> { new IncludedPath { Path = "/*", Indexes = new Collection <Index> { RangeIndex.Range(DataType.Number, -1), RangeIndex.Range(DataType.String, -1), } } } }, }, new RequestOptions { OfferThroughput = 10000 }).Result); }
public async Task <ResourceResponse <DocumentCollection> > CreateCollectionIfNotExistsAsync( string databaseName, string id) { DocumentCollection collectionInfo = new DocumentCollection(); RangeIndex index = Index.Range(DataType.String, -1); collectionInfo.IndexingPolicy = new IndexingPolicy( new Index[] { index }); collectionInfo.Id = id; // Azure Cosmos DB collections can be reserved with // throughput specified in request units/second. RequestOptions requestOptions = new RequestOptions(); requestOptions.OfferThroughput = this.storageThroughput; string dbUrl = "/dbs/" + databaseName; string colUrl = dbUrl + "/colls/" + id; bool create = false; ResourceResponse <DocumentCollection> response = null; try { response = await this.client.ReadDocumentCollectionAsync( colUrl, requestOptions); } catch (DocumentClientException dcx) { if (dcx.StatusCode == HttpStatusCode.NotFound) { create = true; } else { this.log.Error("Error reading collection.", () => new { id, dcx }); } } if (create) { try { response = await this.client.CreateDocumentCollectionAsync( dbUrl, collectionInfo, requestOptions); } catch (Exception ex) { this.log.Error("Error creating collection.", () => new { id, dbUrl, collectionInfo, ex }); throw; } } return(response); }
public void WipeUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value target.Wipe(); }
public void MergeCells(RangeIndex initial, RangeIndex final, string text = null) { worksheet.Range[worksheet.Cells[initial.Initial, initial.Final], worksheet.Cells[final.Initial, final.Final]].Merge(); if (!string.IsNullOrEmpty(text)) { worksheet.Cells[initial.Initial, initial.Final] = text; } }
public void RemoveValueUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value AGraphElement graphElement = null; // TODO: Initialize to an appropriate value target.RemoveValue(graphElement); }
public async Task <ResourceResponse <DocumentCollection> > CreateCollectionIfNotExistsAsync( string databaseName, string id, string partitionKeyName = null) { RangeIndex index = Index.Range(DataType.String, -1); DocumentCollection collectionInfo = new DocumentCollection { IndexingPolicy = new IndexingPolicy(new Index[] { index }), Id = id, }; if (!string.IsNullOrEmpty(partitionKeyName)) { collectionInfo.PartitionKey = new PartitionKeyDefinition { Paths = new Collection <string> { $"/{partitionKeyName}" }, }; } // Azure Cosmos DB collections can be reserved with // throughput specified in request units/second. RequestOptions requestOptions = new RequestOptions { OfferThroughput = this.storageThroughput, ConsistencyLevel = ConsistencyLevel.Strong, }; string dbUrl = "/dbs/" + databaseName; try { await this.CreateDatabaseIfNotExistsAsync(databaseName); } catch (Exception e) { throw new Exception($"While attempting to create collection {id}, an error occured while attepmting to create its database {databaseName}.", e); } ResourceResponse <DocumentCollection> response; try { response = await this.client.CreateDocumentCollectionIfNotExistsAsync( dbUrl, collectionInfo, requestOptions); } catch (Exception e) { this.logger.LogError(e, "Error creating collection with ID {id}, database URL {databaseUrl}, and collection info {collectionInfo}", id, dbUrl, collectionInfo); throw; } return(response); }
public void AddOrUpdateUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value object keyObject = null; // TODO: Initialize to an appropriate value AGraphElement graphElement = null; // TODO: Initialize to an appropriate value target.AddOrUpdate(keyObject, graphElement); }
public void CountOfValuesUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value int expected = 0; // TODO: Initialize to an appropriate value int actual; actual = target.CountOfValues(); Assert.AreEqual(expected, actual); }
public void GetKeyValuesUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value IEnumerable <KeyValuePair <object, ReadOnlyCollection <AGraphElement> > > expected = null; // TODO: Initialize to an appropriate value IEnumerable <KeyValuePair <object, ReadOnlyCollection <AGraphElement> > > actual; actual = target.GetKeyValues(); Assert.AreEqual(expected, actual); }
public void GetKeysUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value IEnumerable <object> expected = null; // TODO: Initialize to an appropriate value IEnumerable <object> actual; actual = target.GetKeys(); Assert.AreEqual(expected, actual); }
public void TryRemoveKeyUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value object keyObject = null; // TODO: Initialize to an appropriate value bool expected = false; // TODO: Initialize to an appropriate value bool actual; actual = target.TryRemoveKey(keyObject); Assert.AreEqual(expected, actual); }
public void TryGetValueUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value ReadOnlyCollection <AGraphElement> result = null; // TODO: Initialize to an appropriate value ReadOnlyCollection <AGraphElement> resultExpected = null; // TODO: Initialize to an appropriate value object keyObject = null; // TODO: Initialize to an appropriate value bool expected = false; // TODO: Initialize to an appropriate value bool actual; actual = target.TryGetValue(out result, keyObject); Assert.AreEqual(resultExpected, result); Assert.AreEqual(expected, actual); }
public void LowerThanUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value ReadOnlyCollection <AGraphElement> result = null; // TODO: Initialize to an appropriate value ReadOnlyCollection <AGraphElement> resultExpected = null; // TODO: Initialize to an appropriate value IComparable key = null; // TODO: Initialize to an appropriate value bool includeKey = false; // TODO: Initialize to an appropriate value bool expected = false; // TODO: Initialize to an appropriate value bool actual; actual = target.LowerThan(out result, key, includeKey); Assert.AreEqual(resultExpected, result); Assert.AreEqual(expected, actual); }
public void BetweenUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); // TODO: Initialize to an appropriate value ReadOnlyCollection <AGraphElement> result = null; // TODO: Initialize to an appropriate value ReadOnlyCollection <AGraphElement> resultExpected = null; // TODO: Initialize to an appropriate value IComparable lowerLimit = null; // TODO: Initialize to an appropriate value IComparable upperLimit = null; // TODO: Initialize to an appropriate value bool includeLowerLimit = false; // TODO: Initialize to an appropriate value bool includeUpperLimit = false; // TODO: Initialize to an appropriate value bool expected = false; // TODO: Initialize to an appropriate value bool actual; actual = target.Between(out result, lowerLimit, upperLimit, includeLowerLimit, includeUpperLimit); Assert.AreEqual(resultExpected, result); Assert.AreEqual(expected, actual); }
/// <summary> /// Gets maximum value of the provided field. /// </summary> /// <typeparam name="TField"></typeparam> /// <param name="field"></param> /// <returns></returns> public TField Maximum <TField>(IField <TRecord, TField> field) { this.table.ValidateField(field); if (!this.IsEmpty()) { List <IIndex <TRecord> > list = this.table.Indexes[field.Order]; if (list != null) { foreach (IIndex <TRecord> index in list) { if (((IFieldHolder)index).Field == field) { RangeIndex <TField> rangeIndex = index as RangeIndex <TField>; if (rangeIndex != null) { return(rangeIndex.MaximumValue(this.StoreSnapshot.Version)); } } } } TField max = field.DefaultValue; bool first = true; foreach (RowId rowId in this) { if (first) { max = this.GetField(rowId, field); first = false; } else { TField value = this.GetField(rowId, field); if (field.Compare(max, value) < 0) { max = value; } } } return(max); } return(field.DefaultValue); }
/// <summary> /// Selects rows where value of provided field in range from min to max inclusively /// </summary> /// <typeparam name="TField"></typeparam> /// <param name="field"></param> /// <param name="min"></param> /// <param name="max"></param> /// <returns></returns> public IEnumerable <RowId> Select <TField>(IField <TRecord, TField> field, TField min, TField max) { this.table.ValidateField(field); List <IIndex <TRecord> > list = this.table.Indexes[field.Order]; if (list != null) { foreach (IIndex <TRecord> index in list) { if (!index.IsUnique) { RangeIndex <TField> rangeIndex = index as RangeIndex <TField>; if (rangeIndex != null && rangeIndex.Field == field) { return(rangeIndex.Find(min, max, this.StoreSnapshot.Version)); } } } } return(this.SelectDirect(field, min, max)); }
/// <summary> /// Creates the audit collection if it does not already exist. /// </summary> /// <returns></returns> private async Task CreateAuditCollectionIfNotExist() { using (var client = new DocumentClient(new Uri(this.accountEndpoint), this.accountKey)) { var database = new Database() { Id = DatabaseId }; await client.CreateDatabaseIfNotExistsAsync(database); var docDefinition = new DocumentCollection(); var rangeIndex = new RangeIndex(DataType.String) { Precision = -1 }; docDefinition.Id = CollectionId; docDefinition.PartitionKey.Paths.Add("/PartitionKey"); docDefinition.IndexingPolicy = new IndexingPolicy(rangeIndex); docDefinition.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/Data/*" }); var options = new RequestOptions() { OfferThroughput = DefaultThroughput }; var cosmosDbUri = UriFactory.CreateDatabaseUri(DatabaseId); await client.CreateDocumentCollectionIfNotExistsAsync(cosmosDbUri, docDefinition, options); } }
/// <summary> /// /// </summary> /// <typeparam name="TField1"></typeparam> /// <typeparam name="TField2"></typeparam> /// <param name="name"></param> /// <param name="field1"></param> /// <param name="field2"></param> /// <param name="unique"></param> private void CreateIndex <TField1, TField2>(string name, IField <TRecord, TField1> field1, IField <TRecord, TField2> field2, bool unique) { this.table.ValidateField(field1); this.table.ValidateField(field2); if (field1 == field2) { throw new ArgumentException(Properties.Resources.ErrorCompositeFields); } CompositeField <TField1, TField2> field = new CompositeField <TField1, TField2>(field1, field2); IFieldIndex <Composite <TField1, TField2> > index; if (unique) { index = new UniqueIndex <Composite <TField1, TField2> >(this.table, name, field); } else { index = new RangeIndex <Composite <TField1, TField2> >(this.table, name, field); } List <IIndex <TRecord> > list1 = this.table.Indexes[field1.Order]; if (list1 == null) { list1 = new List <IIndex <TRecord> >(); this.table.Indexes[field1.Order] = list1; } List <IIndex <TRecord> > list2 = this.table.Indexes[field2.Order]; if (list2 == null) { list2 = new List <IIndex <TRecord> >(); this.table.Indexes[field2.Order] = list2; } list1.Add(index); list2.Add(index); }
// implementation specific function-helper for better code re-use, // it enables us to measure approximations errors in results static public void InterpolateSegments ( List <RangeIndex> vec_ranges, List <LinearRegressionParams> vec_LR_params, List <double> data_x, // results List <double> data_x_interpol, List <double> data_y_interpol ) { data_x_interpol.Clear(); data_y_interpol.Clear(); int n_ranges = vec_ranges.Count; for (int i_rng = 0; i_rng < n_ranges; ++i_rng) { // in the current range we only need to interpolate y-data // using corresponding linear regression RangeIndex range_i = vec_ranges[i_rng]; LinearRegressionParams lr_params_i = vec_LR_params[i_rng]; double coef_a = lr_params_i.coef_a; double coef_b = lr_params_i.coef_b; int i_start = range_i.idx_a; int i_end = range_i.idx_b; for (int i = i_start; i < i_end; ++i) { double x_i = data_x[i]; double y_i = coef_a + coef_b * x_i; data_x_interpol.Add(x_i); data_y_interpol.Add(y_i); } } }
// the function CanSplitRangeThorough() // makes decision whether a given range should be split or not ; // // a given range is not subdivided if the specified accuracy of // linear regression has been achieved, otherwise, the function // searches for the best split point in the range ; // static public bool CanSplitRangeThorough ( // original dataset List <double> data_x, List <double> data_y, // the limit for maximum allowed approximation error (tolerance) double devn_max_user, // input range to be split if linear regression is not acceptable RangeIndex idx_range_in, // the position of a split point, when the function returns <true> ref int idx_split_out, // the parameters of linear regression for the given range, // when the function returns <false> LinearRegressionParams lr_params_out ) { // compute linear regression and approximation error for input range double error_range_in = double.MaxValue; ComputeLinearRegression(data_x, data_y, idx_range_in, lr_params_out, ref error_range_in); // if the approximation is acceptable, input range is not subdivided if (error_range_in < devn_max_user) { return(false); } // approximation error for a current split double err_split = double.MaxValue; // the position (index) of a current split int idx_split = -1; int idx_a = idx_range_in.idx_a; int idx_b = idx_range_in.idx_b; int end_offset = RangeLengthMin(); // sequential search for the best split point in the input range for (int idx = idx_a + end_offset; idx < idx_b - end_offset; ++idx) { // sub-divided ranges RangeIndex range_left = new RangeIndex(idx_a, idx); RangeIndex range_right = new RangeIndex(idx, idx_b); // parameters of linear regression in sub-divided ranges LinearRegressionParams lin_regr_left = new LinearRegressionParams(0.0, 0.0); LinearRegressionParams lin_regr_right = new LinearRegressionParams(0.0, 0.0); // corresponding approximation errors double err_left = double.MaxValue; double err_right = double.MaxValue; // compute linear regression and approximation error in each range ComputeLinearRegression(data_x, data_y, range_left, lin_regr_left, ref err_left); ComputeLinearRegression(data_x, data_y, range_right, lin_regr_right, ref err_right); // we use the worst approximation error double err_idx = Math.Max(err_left, err_right); // the smaller error the better split if (err_idx < err_split) { err_split = err_idx; idx_split = idx; } } // check that sub-division is valid, // the case of short segment: 2 or 3 data points ; // if (n==3) required approximation accuracy cannot be reached ; if (idx_split < 0) { return(false); } idx_split_out = idx_split; return(true); }
public void RangeIndexConstructorUnitTest() { Assert.Inconclusive("TODO"); var target = new RangeIndex(); }
private static async Task CreateIndex(DocumentClient client, string collectionName) { Console.WriteLine("Set up Indexes"); DocumentCollection collection = await client.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(databaseId, collectionName)); /* * Range over /prop/? (or /*) can be used to serve the following queries efficiently: * SELECT * FROM collection c WHERE c.prop = "value" * SELECT * FROM collection c WHERE c.prop > 5 * SELECT * FROM collection c ORDER BY c.prop */ Index indexNum = new RangeIndex(DataType.Number); collection.IndexingPolicy.IncludedPaths.Add(new IncludedPath() { Indexes = new Collection <Index>() { indexNum }, Path = @"/FamilyId/?" }); /* * Hash over /prop/? (or /*) can be used to serve the following queries efficiently: * SELECT * FROM collection c WHERE c.prop = "value" */ Index indexArray = new HashIndex(DataType.String); collection.IndexingPolicy.IncludedPaths.Add(new IncludedPath() { Indexes = new Collection <Index>() { indexArray }, Path = @"/Address/*" }); /* * Hash over /props/[]/? (or /* or /props/*) can be used to serve the following queries efficiently: * SELECT tag FROM collection c JOIN tag IN c.props WHERE tag = 5 */ Index indexArr = new HashIndex(DataType.String); collection.IndexingPolicy.IncludedPaths.Add(new IncludedPath() { Indexes = new Collection <Index>() { indexArr }, Path = @"/Children/[]/?" }); /* exclude from index Parents */ collection.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath() { Path = @"/Parents/*" }); await client.ReplaceDocumentCollectionAsync(collection); }
/// <summary> /// Creates a new collection with the specified name or re-creates the collection if it already exists /// </summary> /// <param name="databaseId">Name of the Cosmos DB database within which to create or re-create the collection</param> /// <param name="collectionId">Name of the Cosmos DB collection to create or re-create</param> /// <param name="deleteExistingColl">Flag indicating whether or not to delete an exisitng collection</param> /// <returns></returns> private async Task CreateDocumentCollectionAsync( string databaseId, string collectionId, bool deleteExistingColl = true) { Database database = (await this.DocumentClient.ReadDatabaseAsync(string.Format("/dbs/{0}", databaseId))).Resource; if (database != null) { Console.WriteLine("Database with resourceid: {0} retrieved", database.ResourceId); } string partitionKey = ConfigurationManager.AppSettings["CollectionPartitionKey"]; int offerThroughput = int.Parse(ConfigurationManager.AppSettings["CollectionThroughput"]); try { DocumentCollection existingColl = await this.DocumentClient.ReadDocumentCollectionAsync(string.Format("/dbs/{0}/colls/{1}", databaseId, collectionId)); if (existingColl != null) { if (!deleteExistingColl) { Console.WriteLine("Collection already present, returning..."); } else { Console.WriteLine("Collection already present. Deleting collection..."); await this.DocumentClient.DeleteDocumentCollectionAsync(string.Format("/dbs/{0}/colls/{1}", databaseId, collectionId)); Console.WriteLine("Finished deleting the collection."); } } } catch (DocumentClientException dce) { if (dce.StatusCode == HttpStatusCode.NotFound) { Console.WriteLine("Collection not found, continuing as normal..."); } else { throw; } } RangeIndex rangeIndexOverride1 = Index.Range(DataType.String, -1); RangeIndex rangeIndexOverride2 = Index.Range(DataType.Number, -1); SpatialIndex spatialIndexOverride = Index.Spatial(DataType.Point); IndexingPolicy indexingPolicy = new IndexingPolicy(rangeIndexOverride1, rangeIndexOverride2, spatialIndexOverride); Console.WriteLine("Creating collection.."); ResourceResponse <DocumentCollection> createResponse = null; PartitionKeyDefinition pkDefn = null; if (partitionKey != null) { Collection <string> paths = new Collection <string>(); paths.Add(partitionKey); pkDefn = new PartitionKeyDefinition() { Paths = paths }; } if (pkDefn != null) { createResponse = await this.DocumentClient.CreateDocumentCollectionAsync( database.SelfLink, new DocumentCollection { Id = collectionId, IndexingPolicy = indexingPolicy, PartitionKey = pkDefn }, new RequestOptions { OfferThroughput = offerThroughput }); } else { createResponse = await this.DocumentClient.CreateDocumentCollectionAsync( database.SelfLink, new DocumentCollection { Id = collectionId, IndexingPolicy = indexingPolicy }, new RequestOptions { OfferThroughput = offerThroughput }); } Console.WriteLine("Successfully created the collection\n"); }
// the function SegmentedRegressionFast() implements // algorithm for segmented linear (piecewise) regression, // which uses for range splitting local maxima of // absolute differences between original and smoothed values ; // the method of smoothing is simple moving average; // // the average performance of this algorithm is O(N logM), where // N is the number of given values and // M is the number of resulting line segments ; // in the worst case the performace is quadratic ; // // return value <false> shows that the required approximation accuracy // has not been achieved ; // public bool SegmentedRegressionFast ( // input dataset: // this function assumes that input x-data are equally spaced List <double> data_x, List <double> data_y, // user specified approximation accuracy (tolerance) ; // this parameter allows to control the total number // and lengths of segments detected ; double devn_max, // this parameter represents half length of window ( h_len+1+h_len ), // which is used by simple moving average to create smoothed dataset int sm_half_len, // the resulting segmented linear regression // is interpolated to match and compare against input values List <double> data_x_res, List <double> data_y_res ) { data_x_res.Clear(); data_y_res.Clear(); int size_x = data_x.Count; int size_y = data_y.Count; if (size_x != size_y) { return(false); } // check for indivisible range if (size_x < 2 * RangeLengthMin()) { return(false); } // vector of smoothed values List <double> data_y_smooth = new List <double>(); data_y_smooth.AddRange(data_y); SimpleMovingAverage(data_y_smooth, sm_half_len); // vector of deviations (as absolute differences) between original and smoothed values List <double> vec_deviations = new List <double>(); for (int i = 0; i < size_y; ++i) { vec_deviations.Add(Math.Abs(data_y_smooth[i] - data_y[i])); } // find positions of local maxima in the vector of deviations List <int> vec_max_indices = new List <int>(); FindLocalMaxima(vec_deviations, vec_max_indices); // ranges (segments) of linear regression List <RangeIndex> vec_ranges = new List <RangeIndex>(); // parameters of linear regression in each matching range List <LinearRegressionParams> vec_LR_params = new List <LinearRegressionParams>(); // the stage of recursive top-down subvision: // this processing starts from the entire range of given dataset RangeIndex range_top = new RangeIndex(0, size_x); // the position (index) of a current split point int idx_split = -1; // parameters of linear regression in a current range (segment) LinearRegressionParams lr_params = new LinearRegressionParams(0.0, 0.0); Stack <RangeIndex> stack_ranges = new Stack <RangeIndex>(); stack_ranges.Push(range_top); while (stack_ranges.Count > 0) { range_top = stack_ranges.Pop(); if (CanSplitRangeFast(data_x, data_y, vec_deviations, vec_max_indices, devn_max, range_top, ref idx_split, lr_params)) { // reverse order of pushing onto stack eliminates re-ordering vec_ranges // after this function is completed stack_ranges.Push(new RangeIndex(idx_split, range_top.idx_b)); stack_ranges.Push(new RangeIndex(range_top.idx_a, idx_split)); } else { // the range is indivisible, we add it to the result vec_ranges.Add(new RangeIndex(range_top.idx_a, range_top.idx_b)); vec_LR_params.Add(new LinearRegressionParams(lr_params.coef_a, lr_params.coef_b)); } } // interpolate the resulting segmented linear regression // and verify the accuracy of the approximation List <double> data_x_interpol = new List <double>(); List <double> data_y_interpol = new List <double>(); InterpolateSegments(vec_ranges, vec_LR_params, data_x, data_x_interpol, data_y_interpol); double appr_error = ApproximationErrorY(data_y, data_y_interpol); //if (appr_error > devn_max) // return false; // the result of this function when the required accuracy has been achieved data_x_res.AddRange(data_x_interpol); data_y_res.AddRange(data_y_interpol); return(true); }
// the function CanSplitRangeFast() // makes decision whether a given range should be split or not ; // // a given range is not subdivided if the specified accuracy of // linear regression has been achieved, otherwise, // the function selects for the best split the position of // the greatest local maximum of absolute differences // between original and smoothed values in a given range ; // static public bool CanSplitRangeFast ( // original dataset List <double> data_x, List <double> data_y, // absolute differences between original and smoothed values List <double> vec_devns_in, // positions (indices) of local maxima in vec_devns_in List <int> vec_max_ind_in, // the limit for maximum allowed approximation error (tolerance) double devn_max_user, // input range to be split if linear regression is not acceptable RangeIndex idx_range_in, // the position of a split point, when the function returns <true> ref int idx_split_out, // the parameters of linear regression for the given range, // when the function returns <false> LinearRegressionParams lr_params_out ) { idx_split_out = -1; if (vec_devns_in.Count != data_x.Count) { Console.WriteLine("SLR: size error"); return(false); } int end_offset = RangeLengthMin(); int range_len = idx_range_in.Length(); if (range_len < end_offset) { Console.WriteLine("SLR: input range is too small"); return(false); } // compute linear regression and approximation error for input range double err_range_in = double.MaxValue; ComputeLinearRegression(data_x, data_y, idx_range_in, lr_params_out, ref err_range_in); // if the approximation is acceptable, input range is not subdivided if (err_range_in < devn_max_user) { return(false); } // check for indivisible range if (range_len < 2 * RangeLengthMin()) { return(false); } if (vec_devns_in.Count == 0) { return(false); } // for the main criterion of splitting here we use // the greatest local maximum of deviations inside the given range int idx_split_local_max = -1; double devn_max = 0.0; double devn_cur = 0.0; int sz_loc_max = vec_max_ind_in.Count; // find inside given range local maximum with the largest deviation for (int k_max = 0; k_max < sz_loc_max; ++k_max) { int idx_max_cur = vec_max_ind_in[k_max]; // check if the current index is inside the given range and that // potential split will not create segment with 1 data point only if ((idx_max_cur < idx_range_in.idx_a + end_offset) || (idx_max_cur >= idx_range_in.idx_b - end_offset)) { continue; } devn_cur = vec_devns_in[idx_max_cur]; if (devn_cur > devn_max) { devn_max = devn_cur; idx_split_local_max = idx_max_cur; } } // the case of no one local maximum inside the given range if (idx_split_local_max < 0) { return(false); } // the case (idx_split_local_max==0) is not possible here due to (end_offset==RANGE_LENGTH_MIN), // this is a valid result ( idx_split_local_max > 0 ) idx_split_out = idx_split_local_max; return(true); }
// the function ComputeLinearRegression() computes parameters of // linear regression and approximation error // for a given range of a given dataset ; static public void ComputeLinearRegression ( // original dataset List <double> data_x, List <double> data_y, // semi-open range [ a , b ) RangeIndex idx_range, // coefficients of linear regression in the given range LinearRegressionParams lin_regr_out, // approximation error ref double err_appr_out ) { if (idx_range.Length() < RangeLengthMin()) { Console.WriteLine("SLR error: input range is too small"); return; } int idx_a = idx_range.idx_a; int idx_b = idx_range.idx_b; double n_vals = idx_range.Length(); double sum_x = 0.0; double sum_y = 0.0; double sum_xx = 0.0; double sum_xy = 0.0; // compute the required sums: for (int it = idx_a; it < idx_b; ++it) { double xi = data_x[it]; double yi = data_y[it]; sum_x += xi; sum_y += yi; sum_xx += xi * xi; sum_xy += xi * yi; } // compute parameters of linear regression in the given range if (!LinearRegressionParameters(n_vals, sum_x, sum_y, sum_xx, sum_xy, lin_regr_out)) { // this is a very unusual case for real data //Console.WriteLine("SLR: special case error"); return; } double coef_a = lin_regr_out.coef_a; double coef_b = lin_regr_out.coef_b; // use linear regression obtained to measure approximation error in the given range, // the error is the maximum of absolute differences between original and approximation values double diff_max = 0.0; for (int it = idx_a; it < idx_b; ++it) { double xi = data_x[it]; double yi_orig = data_y[it]; double yi_appr = coef_a + coef_b * xi; double diff_i = Math.Abs(yi_orig - yi_appr); if (diff_i > diff_max) { diff_max = diff_i; } } err_appr_out = diff_max; }