/// <summary> /// Calculates subsequences characteristics. /// </summary> /// <param name="characteristicTypeLinkIds"> /// The characteristic type link ids. /// </param> /// <param name="featureIds"> /// The features ids. /// </param> /// <param name="parentSequenceId"> /// The parent sequence id. /// </param> /// <param name="calculators"> /// The calculators. /// </param> /// <param name="links"> /// The links. /// </param> /// <param name="attributeValues"> /// Nonredundant array of all attributes. /// </param> /// <param name="filters"> /// Textual search filters for subsequences products. /// </param> /// <returns> /// The <see cref="T:SubsequenceData[]"/>. /// </returns> public static SubsequenceData[] CalculateSubsequencesCharacteristics( int[] characteristicTypeLinkIds, int[] featureIds, long parentSequenceId, IFullCalculator[] calculators, Link[] links, List<AttributeValue> attributeValues, string[] filters = null) { // creating local context to avoid memory overflow due to possibly big cache of characteristics using (var context = new LibiadaWebEntities()) { var subsequenceExtractor = new SubsequenceExtractor(context); var sequenceAttributeRepository = new SequenceAttributeRepository(context); var attributeRepository = new AttributeRepository(); var newCharacteristics = new List<Characteristic>(); // extracting data from database var dbSubsequences = filters == null ? subsequenceExtractor.GetSubsequences(parentSequenceId, featureIds) : subsequenceExtractor.GetSubsequences(parentSequenceId, featureIds, filters); var subsequenceIds = dbSubsequences.Select(s => s.Id).ToArray(); var dbSubsequencesAttributes = sequenceAttributeRepository.GetAttributes(subsequenceIds); var dbCharacteristics = context.Characteristic.Where(c => characteristicTypeLinkIds.Contains(c.CharacteristicTypeLinkId) && subsequenceIds.Contains(c.SequenceId)) .ToArray() .GroupBy(c => c.SequenceId) .ToDictionary(c => c.Key, c => c.ToDictionary(ct => ct.CharacteristicTypeLinkId, ct => ct.Value)); // converting to libiada sequences var sequences = subsequenceExtractor.ExtractChains(dbSubsequences, parentSequenceId); var subsequenceData = new SubsequenceData[sequences.Length]; // cycle through subsequences for (int i = 0; i < sequences.Length; i++) { var values = new double[characteristicTypeLinkIds.Length]; Dictionary<int, double> sequenceDbCharacteristics; if (!dbCharacteristics.TryGetValue(dbSubsequences[i].Id, out sequenceDbCharacteristics)) { sequenceDbCharacteristics = new Dictionary<int, double>(); } // cycle through characteristics and notations for (int j = 0; j < characteristicTypeLinkIds.Length; j++) { int characteristicTypeLinkId = characteristicTypeLinkIds[j]; if (!sequenceDbCharacteristics.TryGetValue(characteristicTypeLinkId, out values[j])) { values[j] = calculators[j].Calculate(sequences[i], links[j]); var currentCharacteristic = new Characteristic { SequenceId = dbSubsequences[i].Id, CharacteristicTypeLinkId = characteristicTypeLinkId, Value = values[j] }; newCharacteristics.Add(currentCharacteristic); } } AttributeValue[] attributes; if (!dbSubsequencesAttributes.TryGetValue(dbSubsequences[i].Id, out attributes)) { attributes = new AttributeValue[0]; } var attributeIndexes = new int[attributes.Length]; for (int j = 0; j < attributes.Length; j++) { if (!attributeValues.Contains(attributes[j])) { attributeValues.Add(attributes[j]); } attributeIndexes[j] = attributeValues.IndexOf(attributes[j]); } subsequenceData[i] = new SubsequenceData(dbSubsequences[i], values, attributeIndexes); } // trying to save calculated characteristics to database var characteristicRepository = new CharacteristicRepository(context); characteristicRepository.TrySaveCharacteristicsToDatabase(newCharacteristics); return subsequenceData; } }
/// <summary> /// Calculates subsequences characteristics. /// </summary> /// <param name="characteristicIds"> /// The ids of characteristic types, arrangement types and links as <see cref="FullCharacteristicLink"/>. /// </param> /// <param name="features"> /// The features ids of subsequences to extract. /// </param> /// <param name="parentSequenceId"> /// The parent sequence id. /// </param> /// <param name="filters"> /// Textual search filters for subsequences products. /// </param> /// <returns> /// The <see cref="T:SubsequenceData[]"/> . /// </returns> public static SubsequenceData[] CalculateSubsequencesCharacteristics( short[] characteristicIds, Feature[] features, long parentSequenceId, string[] filters = null) { Dictionary <long, Chain> sequences; long[] subsequenceIds; SubsequenceData[] subsequenceData; Dictionary <long, Dictionary <short, double> > characteristics; var calculators = new IFullCalculator[characteristicIds.Length]; var links = new Link[characteristicIds.Length]; var newCharacteristics = new List <CharacteristicValue>(); // creating local context to avoid memory overflow due to possibly big cache of characteristics using (var db = new LibiadaWebEntities()) { var subsequenceExtractor = new SubsequenceExtractor(db); Subsequence[] subsequences = filters == null? subsequenceExtractor.GetSubsequences(parentSequenceId, features) : subsequenceExtractor.GetSubsequences(parentSequenceId, features, filters); subsequenceData = subsequences.Select(s => new SubsequenceData(s)).ToArray(); // converting to libiada sequences subsequenceIds = subsequences.Select(s => s.Id).ToArray(); characteristics = db.CharacteristicValue .Where(c => characteristicIds.Contains(c.CharacteristicLinkId) && subsequenceIds.Contains(c.SequenceId)) .ToArray() .GroupBy(c => c.SequenceId) .ToDictionary(c => c.Key, c => c.ToDictionary(ct => ct.CharacteristicLinkId, ct => ct.Value)); if (characteristics.Count == subsequences.Length && characteristics.All(c => c.Value.Count == characteristicIds.Length)) { sequences = new Dictionary <long, Chain>(); } else { sequences = subsequenceExtractor.GetSubsequencesSequences(subsequences); } } var characteristicTypeLinkRepository = FullCharacteristicRepository.Instance; for (int k = 0; k < characteristicIds.Length; k++) { short characteristicLinkId = characteristicIds[k]; FullCharacteristic characteristic = characteristicTypeLinkRepository.GetCharacteristic(characteristicLinkId); calculators[k] = FullCalculatorsFactory.CreateCalculator(characteristic); links[k] = characteristicTypeLinkRepository.GetLinkForCharacteristic(characteristicLinkId); } // cycle through subsequences for (int i = 0; i < subsequenceIds.Length; i++) { characteristics.TryGetValue(subsequenceIds[i], out Dictionary <short, double> sequenceDbCharacteristics); sequenceDbCharacteristics = sequenceDbCharacteristics ?? new Dictionary <short, double>(); var values = new double[calculators.Length]; // cycle through characteristics and notations for (int j = 0; j < calculators.Length; j++) { short characteristicLinkId = characteristicIds[j]; if (!sequenceDbCharacteristics.TryGetValue(characteristicLinkId, out values[j])) { values[j] = calculators[j].Calculate(sequences[subsequenceIds[i]], links[j]); var currentCharacteristic = new CharacteristicValue { SequenceId = subsequenceIds[i], CharacteristicLinkId = characteristicLinkId, Value = values[j] }; newCharacteristics.Add(currentCharacteristic); } } subsequenceData[i].CharacteristicsValues = values; } using (var db = new LibiadaWebEntities()) { // trying to save calculated characteristics to database var characteristicRepository = new CharacteristicRepository(db); characteristicRepository.TrySaveCharacteristicsToDatabase(newCharacteristics); } return(subsequenceData); }
public ActionResult Index( long[] matterIds, short characteristicLinkId, Notation notation, Feature[] features, string maxDifference, string excludeType) { return(CreateTask(() => { if (matterIds.Length != 2) { throw new ArgumentException("Count of selected matters must be 2.", nameof(matterIds)); } long firstMatterId = matterIds[0]; long firstParentSequenceId = db.CommonSequence.Single(c => c.MatterId == firstMatterId && c.Notation == notation).Id; Subsequence[] firstSequenceSubsequences = subsequenceExtractor.GetSubsequences(firstParentSequenceId, features); List <double> firstSequenceCharacteristics = CalculateCharacteristic(characteristicLinkId, firstSequenceSubsequences); Dictionary <long, AttributeValue[]> firstDbSubsequencesAttributes = sequenceAttributeRepository.GetAttributes(firstSequenceSubsequences.Select(s => s.Id)); var firstSequenceAttributes = new List <AttributeValue[]>(); foreach (Subsequence subsequence in firstSequenceSubsequences) { firstDbSubsequencesAttributes.TryGetValue(subsequence.Id, out AttributeValue[] attributes); attributes = attributes ?? new AttributeValue[0]; firstSequenceAttributes.Add(attributes); } long secondMatterId = matterIds[1]; long secondParentSequenceId = db.CommonSequence.Single(c => c.MatterId == secondMatterId && c.Notation == notation).Id; Subsequence[] secondSequenceSubsequences = subsequenceExtractor.GetSubsequences(secondParentSequenceId, features); List <double> secondSequenceCharacteristics = CalculateCharacteristic(characteristicLinkId, secondSequenceSubsequences); Dictionary <long, AttributeValue[]> secondDbSubsequencesAttributes = sequenceAttributeRepository.GetAttributes(secondSequenceSubsequences.Select(s => s.Id)); var secondSequenceAttributes = new List <AttributeValue[]>(); foreach (Subsequence subsequence in secondSequenceSubsequences) { secondDbSubsequencesAttributes.TryGetValue(subsequence.Id, out AttributeValue[] attributes); attributes = attributes ?? new AttributeValue[0]; secondSequenceAttributes.Add(attributes); } double difference = double.Parse(maxDifference, CultureInfo.InvariantCulture); var similarSubsequences = new List <IntPair>(); for (int i = 0; i < firstSequenceCharacteristics.Count; i++) { for (int j = 0; j < secondSequenceCharacteristics.Count; j++) { if (Math.Abs(firstSequenceCharacteristics[i] - secondSequenceCharacteristics[j]) <= difference) { similarSubsequences.Add(new IntPair(i, j)); if (excludeType == "Exclude") { firstSequenceCharacteristics[i] = double.NaN; secondSequenceCharacteristics[j] = double.NaN; } } } } var characteristicName = characteristicTypeLinkRepository.GetCharacteristicName(characteristicLinkId, notation); var similarity = similarSubsequences.Count * 200d / (firstSequenceSubsequences.Length + secondSequenceSubsequences.Length); var firstSequenceSimilarity = similarSubsequences.Count * 100d / firstSequenceSubsequences.Length; var secondSequenceSimilarity = similarSubsequences.Count * 100d / secondSequenceSubsequences.Length; return new Dictionary <string, object> { { "firstSequenceName", db.Matter.Single(m => m.Id == firstMatterId).Name }, { "secondSequenceName", db.Matter.Single(m => m.Id == secondMatterId).Name }, { "characteristicName", characteristicName }, { "similarSubsequences", similarSubsequences }, { "similarity", similarity }, { "firstSequenceSimilarity", firstSequenceSimilarity }, { "secondSequenceSimilarity", secondSequenceSimilarity }, { "firstSequenceSubsequences", firstSequenceSubsequences }, { "secondSequenceSubsequences", secondSequenceSubsequences }, { "firstSequenceAttributes", firstSequenceAttributes }, { "secondSequenceAttributes", secondSequenceAttributes } }; })); }