Beispiel #1
0
 public static void Log(List <ElementDefinition> profile1, List <ElementDefinition> profile2)
 {
     // elements (path) in profile 1 but not in profile 2 -> log
     foreach (ElementDefinition element in profile1)
     {
         if (!profile2.Where(p => PathComparison.ComparePath(p.Path, element.Path)).Any())
         {
             var cost = 0.0;
             if (element.Max != "0" && element.Min == 0)
             {
                 // one optional and two prohibited
                 cost = AspectWeights.PROHIBITED_OPTIONAL;
                 Program.LogDistance2(element.Path, "cost", cost, "1", "optional element");
             }
             if (element.Max != "0" && element.Min != 0)
             {
                 // one mandatory and two prohibited
                 cost = AspectWeights.MANDATORY_PROHIBITED;
                 Program.LogDistance2(element.Path, "cost", cost, "1", "mandatory element");
             }
         }
     }
     foreach (ElementDefinition element in profile2)
     {
         if (!profile1.Where(p => PathComparison.ComparePath(p.Path, element.Path)).Any())
         {
             var cost = 0.0;
             if (element.Max != "0" && element.Min == 0)
             {
                 // one optional and two prohibited
                 cost = AspectWeights.PROHIBITED_OPTIONAL;
                 Program.LogDistance2(element.Path, "cost", cost, "2", "optional element");
             }
             if (element.Max != "0" && element.Min != 0)
             {
                 // one mandatory and two prohibited
                 cost = AspectWeights.MANDATORY_PROHIBITED;
                 Program.LogDistance2(element.Path, "cost", cost, "2", "mandatory element");
             }
         }
     }
 }
        public static List <ElementDefinition> RemoveSlices(List <ElementDefinition> profileA)
        {
            var list1      = new List <ElementDefinition>();
            var slicepaths = new List <string>();

            slicepaths = profileA.Where(e => e.Slicing != null).Select(e => e.Path).ToList();
            var sliceInfoList = new List <SliceInfo>();

            foreach (var path in slicepaths)
            {
                var sliceInfo = new SliceInfo();
                sliceInfo.Path  = path;
                sliceInfo.Slice = false;
                sliceInfoList.Add(sliceInfo);
            }

            foreach (ElementDefinition element in profileA)
            {
                if (sliceInfoList.Where(i => i.Slice == false).Where(e => PathComparison.ComparePath(e.Path, element.Path)).Any())
                {
                    sliceInfoList.Where(i => PathComparison.ComparePath(i.Path, element.Path)).FirstOrDefault().Slice = true;
                }
                else if (sliceInfoList.Where(i => i.Slice == true).Where(e => PathComparison.ComparePath(e.Path, element.Path)).Any())
                {
                    var Index1Slice = sliceInfoList.Where(i => PathComparison.ComparePath(i.Path, element.Path)).FirstOrDefault().IndexFirstSlice = profileA.IndexOf(element);

                    var lijst = profileA.Where(p => p.Path.StartsWith(element.Path)).ToList();
                    foreach (ElementDefinition e in lijst)
                    {
                        var indexElement = profileA.IndexOf(e);
                        if (indexElement >= Index1Slice)
                        {
                            list1.Add(e);
                        }
                    }
                }
            }
            profileA = profileA.Except(list1).ToList();
            return(profileA);
        }
Beispiel #3
0
        private static double DistanceTrees(StructureDefinition profileA, StructureDefinition profileB)
        {
            ED1 = 0;

            //  delete all prohibited elements and children-elements
            var profile1 = List_Element_Definitions.ExistingElements(profileA);
            var profile2 = List_Element_Definitions.ExistingElements(profileB);

            //  delete slices and extensions
            profile1 = List_Element_Definitions.RemoveSlices(profile1);
            profile2 = List_Element_Definitions.RemoveSlices(profile2);

            if (profile1.Count == 0 && profile2.Count == 0)
            {
                return(0.0);
            }

            //different concept
            if (profile1[0].Path != profile2[0].Path)
            {
                return(int.MaxValue);
            }

            //log elements that only exists in one profile
            LogElementsWithoutCounterPart.Log(profile1, profile2);

            // Wagner-Fischer algorithm applied to profiles
            var m = profile1.Count + 1;
            var n = profile2.Count + 1;
            var d = new double[m, n];

            for (int i = 0; i < m; i++)
            {
                d[i, 0] = i;
            }
            for (int j = 0; j < n; j++)
            {
                d[0, j] = j;
            }

            // first row of results matrix, which indicates the elements of profile 1
            var elementen = " " + ";";

            foreach (ElementDefinition element in profile1)
            {
                elementen += element.Path + ";";
            }
            lines3.Add(elementen);

            for (int j = 1; j < n; j++)
            {
                string content = profile2[j - 1].Path + ";";
                for (int i = 1; i < m; i++)
                {
                    double cost = 0.0;
                    // IF not equal, compute cost
                    var a = profile1[i - 1];
                    var b = profile2[j - 1];
                    cost = CompareAspects.Compare(a, b);
                    var MinCost = new List <double>();
                    // cost depends on cardinality of deleted element
                    var costdelete = 1.0;
                    if (a.Max != "0" && a.Min == 0)
                    {
                        costdelete = AspectWeights.PROHIBITED_OPTIONAL;
                    }
                    if (a.Max != "0" && a.Min != 0)
                    {
                        costdelete = AspectWeights.MANDATORY_PROHIBITED;
                    }
                    MinCost.Add(d[i - 1, j] + costdelete);
                    //cost depends on cardinality of inserted element
                    var costinsert = 1.0;
                    if (b.Max != "0" && b.Min == 0)
                    {
                        costinsert = AspectWeights.PROHIBITED_OPTIONAL;
                    }
                    if (b.Max != "0" && b.Min != 0)
                    {
                        costinsert = AspectWeights.MANDATORY_PROHIBITED;
                    }
                    MinCost.Add(d[i, j - 1] + costinsert);
                    //change or update
                    if (cost <= 1 && PathComparison.ComparePath(a.Path, b.Path))
                    {
                        MinCost.Add(d[i - 1, j - 1] + cost);
                    }
                    d[i, j] = MinCost.Min();

                    // log differences between elements
                    if (cost > 0 && PathComparison.ComparePath(a.Path, b.Path))
                    {
                        LogDistance2(a.Path, b.Path, cost, "", "");
                    }
                    content += d[i, j].ToString() + ";";
                }
                // save matrix
                lines3.Add(content);
            }
            ED1 = d[m - 1, n - 1];

            //additional semantic weight for the elements: value[x], code, status
            var c1 = CompareAspects.Compare(profile1.Where(p => p.Path == "Observation.status").FirstOrDefault(), profile2.Where(p => p.Path == "Observation.status").FirstOrDefault());

            if (c1 > 0)
            {
                ED1 += c1 * AspectWeights.ELEMENT_STATUS;
            }
            var c2 = CompareAspects.Compare(profile1.Where(p => p.Path == "Observation.code").FirstOrDefault(), profile2.Where(p => p.Path == "Observation.code").FirstOrDefault());

            if (c2 > 0)
            {
                ED1 += c2 * AspectWeights.ELEMENT_CODE;
            }
            var c3 = CompareAspects.Compare(profile1.Where(p => p.Path == "Observation.code.coding").FirstOrDefault(), profile2.Where(p => p.Path == "Observation.code.coding").FirstOrDefault());

            if (c3 > 0)
            {
                ED1 += c3 * AspectWeights.ELEMENT_CODE_CODING;
            }
            var c4 = CompareAspects.Compare(profile1.Where(p => p.Path == "Observation.code.coding.system").FirstOrDefault(), profile2.Where(p => p.Path == "Observation.code.coding.system").FirstOrDefault());

            if (c4 > 0)
            {
                ED1 += c4 * AspectWeights.ELEMENT_CODE_CODING_SYSTEM;
            }
            var c5 = CompareAspects.Compare(profile1.Where(p => p.Path == "Observation.code.coding.code").FirstOrDefault(), profile2.Where(p => p.Path == "Observation.code.coding.code").FirstOrDefault());

            if (c5 > 0)
            {
                ED1 += c5 * AspectWeights.ELEMENT_CODE_CODING_CODE;
            }
            var c6 = CompareAspects.Compare(profile1.Where(p => p.Path.StartsWith("Observation.value")).FirstOrDefault(), profile2.Where(p => p.Path.StartsWith("Observation.value")).FirstOrDefault());

            if (c6 > 0)
            {
                ED1 += c6 * AspectWeights.ELEMENT_CODE_CODING_SYSTEM;
            }
            return(ED1);
        }
        public static double Compare(ElementDefinition one, ElementDefinition two)
        {
            double difference = 0;

            // cost depends on difference in cardinality between elements
            if (two == null)
            {
                if (StringToInteger.MaxInt(one) == 0)
                {
                    // both prohibited
                    Program.LogAspectDifference(AspectWeights.BOTH_PROHIBITED, "Cardinality");
                    return(AspectWeights.BOTH_PROHIBITED);
                }
                if (StringToInteger.MaxInt(one) != 0 && one.Min == 0)
                {
                    // one optional and two prohibited
                    Program.LogAspectDifference(AspectWeights.PROHIBITED_OPTIONAL, "Cardinality");
                    return(AspectWeights.PROHIBITED_OPTIONAL);
                }
                if (StringToInteger.MaxInt(one) != 0 && one.Min != 0)
                {
                    // one mandatory and two prohibited
                    Program.LogAspectDifference(AspectWeights.MANDATORY_PROHIBITED, "Cardinality");
                    return(AspectWeights.MANDATORY_PROHIBITED);
                }
            }
            if (!PathComparison.ComparePath(one.Path, two.Path))
            {
                return(AspectWeights.PATH);
            }

            //if cardinality is not defined in one element -> max difference (same as no overlap not 1) and compare other aspects!
            if (one.Max == null && one.Min == null && two.Max != null && two.Min != null)
            {
                difference += AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
            }
            if (two.Max == null && two.Min == null && one.Max != null && one.Min != null)
            {
                difference += AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
            }
            if ((one.Max == null && one.Min != null && two.Max != null && two.Min != null) || (one.Max != null && one.Min != null && two.Max == null && two.Min != null))
            {
                if (one.Min == two.Min)
                {
                    difference += 0.5 * AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
                }
                else
                {
                    difference += AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
                }
            }
            if ((one.Max != null && one.Min == null && two.Max != null && two.Min != null) || (one.Max != null && one.Min != null && two.Max != null && two.Min == null))
            {
                if (one.Max == two.Max)
                {
                    difference += 0.5 * AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
                }
                else
                {
                    difference += AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
                }
            }
            if ((one.Max == null && one.Min != null && two.Max != null && two.Min == null) || (one.Max != null && one.Min == null && two.Max == null && two.Min != null))
            {
                difference += AspectWeights.BOTH_MANDATORY_NO_OVERLAP;
            }

            if (one.Max != null && one.Min != null && two.Max != null && two.Min != null)
            {
                // both prohibited -> skip other aspects, difference no meaning
                if (one.Min == 0 && two.Min == 0 && StringToInteger.MaxInt(one) == 0 && StringToInteger.MaxInt(two) == 0)
                {
                    Program.LogAspectDifference(AspectWeights.BOTH_PROHIBITED, "Cardinality");
                    return(AspectWeights.BOTH_PROHIBITED);
                }
                if ((StringToInteger.MaxInt(one) == 0 && two == null) || (StringToInteger.MaxInt(two) == 0 && one == null))
                {
                    Program.LogAspectDifference(AspectWeights.BOTH_PROHIBITED, "Cardinality");
                    return(AspectWeights.BOTH_PROHIBITED);
                }
                // 1 prohibited and 1 mandatory
                if ((one.Min == 0 && one.Max == "0" && two.Min != 0) || (two.Min == 0 && two.Max == "0" && one.Min != 0))
                {
                    Program.LogAspectDifference(AspectWeights.MANDATORY_PROHIBITED, "Cardinality");
                    return(AspectWeights.MANDATORY_PROHIBITED);
                }
                // 1 prohibited en 1 optional
                if ((one.Min == two.Min && one.Max == "0" && two.Max != "0") || (two.Min == one.Min && two.Max == "0" && one.Max != "0"))
                {
                    Program.LogAspectDifference(AspectWeights.PROHIBITED_OPTIONAL, "Cardinality");
                    return(AspectWeights.PROHIBITED_OPTIONAL);
                }

                // ranges cardinality, remaining options
                difference += CompareCardinality.CompareRangesCardinality(one, two);
            }
            // Note: API guarantees that list elements (such as ElementDefinition.Type) are never null !
            var distanceType = CompareType.DistanceType(one.Type, two.Type, AspectWeights.WEIGHT_TYPE);

            difference += distanceType;

            difference += SimpleCompare.CompareNameReference(one, two, AspectWeights.WEIGHT_NAMEREFERENCE);
            difference += SimpleCompare.CompareMustSupport(one, two, AspectWeights.WEIGHT_MUSTSUPPORT);
            difference += SimpleCompare.CompareIsModifier(one, two, AspectWeights.WEIGHT_ISMODIFIER);
            difference += SimpleCompare.CompareIsSummary(one, two, AspectWeights.WEIGHT_ISSUMMARY);
            difference += SimpleCompare.CompareRequirements(one, two, AspectWeights.WEIGHT_REQUIREMENTS);
            difference += SimpleCompare.CompareComments(one, two, AspectWeights.WEIGHT_COMMENTS);
            difference += SimpleCompare.CompareDefinition(one, two, AspectWeights.WEIGHT_DEFINITION);
            difference += SimpleCompare.CompareShort(one, two, AspectWeights.WEIGHT_SHORT);
            difference += SimpleCompare.CompareLabel(one, two, AspectWeights.WEIGHT_LABEL);
            difference += SimpleCompare.CompareName(one, two, AspectWeights.WEIGHT_NAME);
            difference += SimpleCompare.CompareMeaningWhenMissing(one, two, AspectWeights.WEIGHT_MEANINGWHENMISSING);
            difference += SimpleCompare.CompareMaxLength(one, two, AspectWeights.WEIGHT_MAXLENGTH);
            difference += CompareValueProperty.CompareExample(one, two, AspectWeights.WEIGHT_EXAMPLE);

            // only compare ValueRanges when type is the same & valueRange can only be set if type is a single type (no list)
            if (distanceType <= ((AspectWeights.WEIGHT_TYPE_AGGREGATION + AspectWeights.WEIGHT_TYPE_PROFILE) * AspectWeights.WEIGHT_TYPE) && one.Type.Count() == two.Type.Count() && one.Type.Count() == 1)
            {
                difference += CompareRangeValues.CompareRange(one, two);
                difference += CompareValueProperty.CompareDefaultValue(one, two, AspectWeights.WEIGHT_DEFAULTVALUE);
                difference += CompareValueProperty.CompareFixed(one, two, AspectWeights.WEIGHT_FIXED);
                difference += CompareValueProperty.ComparePattern(one, two, AspectWeights.WEIGHT_PATTERN);
            }

            difference += CompareBinding.DistanceBinding(one.Binding, two.Binding, AspectWeights.WEIGHT_BINDING);
            difference += CompareBase.DistanceBase(one.Base, two.Base, AspectWeights.WEIGHT_BASE);

            difference += CompareRepresentation.DistanceRepresentation(one.Representation, two.Representation, AspectWeights.WEIGHT_REPRESENTATION);
            difference += CompareCode.DistanceCode(one.Code, two.Code, AspectWeights.WEIGHT_CODE);
            difference += CompareAlias.DistanceAlias(one.Alias, two.Alias, AspectWeights.WEIGHT_ALIAS);
            difference += CompareMapping.DistanceMapping(one.Mapping, two.Mapping, AspectWeights.WEIGHT_MAPPING);
            difference += CompareCondition.DistanceCondition(one.Condition, two.Condition, AspectWeights.WEIGHT_CONDITION);
            difference += CompareConstraint.DistanceConstraint(one.Constraint, two.Constraint, AspectWeights.WEIGHT_CONSTRAINT);
            return(difference);
        }