/// <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);
        }
Example #3
0
        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 }
                };
            }));
        }