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); }
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); }