/// <summary> /// Calculează valoarea aplicării algoritmului de decizii multicriteriu pe un anumit serviciu. /// </summary> /// <param name="service">Serviciul pe care se aplică algoritmul</param> /// <returns>Media ponderată a intersecțiilor cererilor cu proprietățile serviciului. Ponderile sunt importanțele cererilor.</returns> private double calculateValue(Service service) { double sum = 0.0; double weightSum = 0.0; foreach (Term term in this.requestImportances.Keys) { Property property = service.functionality.getProperty(term.name); if (property != null) { double intersection = InferenceMachine.intersect(service, property, term) * this.requestImportances[term]; if (!double.IsNaN(intersection)) { sum += intersection; weightSum += this.requestImportances[term]; } } } return sum / weightSum; }
/// <summary> /// Adaugă ontologia unei funcţionalităţi pentru care momentan se cunoaşte doar numele. /// </summary> /// <param name="ontology">Ontologia care sa fie adaugată</param> /// <returns>Un serviciu cu ontologia adăugată</returns> public Service addActualOntology(Functionality ontology) { if (this.functionality != null) { return this; } Service result = new Service(this.name,this.accessPoint, ontology); foreach (Property property in ontology.properties) { if (this.values.ContainsKey(property.name)) { if (this.values[property.name] is double) { result.values[property] = this.values[property.name]; } else { if (this.values[property.name] is string) { Term term = property.getTerm(this.values[property.name] as string); if (term != null) { result.values[property] = term; } } } } } return result; }
/// <summary> /// Găsește valoarea intersecției unui termen fuzzy cu valoarea unei proprietăți a unui serviciu (ce poate fi fuzzy sau crisp). /// </summary> /// <param name="service">Serviciul de care aparține proprietatea</param> /// <param name="property">Proprietatea a cărei valoare se va folosi pentru intersecție</param> /// <param name="shape">Termenul care se intersectează cu valoarea proprietății</param> /// <returns>Valoarea intersecției celor 2 termeni</returns> public static double intersect(Service service, Property property, Term shape) { try { bool isLowerBetter = shape.start > shape.end || property.start > property.end; double start2 = isLowerBetter ? shape.end : shape.start; double left2 = isLowerBetter ? shape.right : shape.left; double right2 = isLowerBetter ? shape.left : shape.right; double end2 = isLowerBetter ? shape.start : shape.end; if (service.isFuzzy(property)) { Term term = service.getFuzzyValue(property); if (term == null) { return double.NaN; } double result = intersectLinesY(term.start, term.left, 0.0, 1.0, start2, left2, 0.0, 1.0); result = Math.Max(result, intersectLinesY(term.left, term.right, 1.0, 1.0, start2, left2, 0.0, 1.0)); result = Math.Max(result, intersectLinesY(term.right, term.end, 1.0, 0.0, start2, left2, 0.0, 1.0)); result = Math.Max(result, intersectLinesY(term.start, term.left, 0.0, 1.0, left2, right2, 1.0, 1.0)); result = Math.Max(result, intersectLinesY(term.left, term.right, 1.0, 1.0, left2, right2, 1.0, 1.0)); result = Math.Max(result, intersectLinesY(term.right, term.end, 1.0, 0.0, left2, right2, 1.0, 1.0)); result = Math.Max(result, intersectLinesY(term.start, term.left, 0.0, 1.0, right2, end2, 1.0, 0.0)); result = Math.Max(result, intersectLinesY(term.left, term.right, 1.0, 1.0, right2, end2, 1.0, 0.0)); return Math.Max(result, intersectLinesY(term.right, term.end, 1.0, 0.0, right2, end2, 1.0, 0.0)); } else { double crispValue = service.getCrispValue(property); if (double.IsNaN(crispValue)) { return double.NaN; } if (crispValue > start2 && crispValue < left2) { return (crispValue - start2) / (left2 - start2); } else { if (crispValue >= left2 && crispValue <= right2) { return 1.0; } else { if (crispValue > right2 && crispValue < end2) { return (crispValue - end2) / (right2 - end2); } else { return 0.0; } } } } } catch (Exception) { return double.NaN; } }
/// <summary> /// Aplică inferența pe un anumit serviciu și returnează răspunsul în format CSV. /// </summary> /// <param name="service">Serviciul pentru care se aplică inferența</param> /// <returns>Rezultatul inferenței în format CSV - un singur rând ce ar trebui să conțină măcar o coloană cu o valoare numerică pentru sortarea serviciilor</returns> public abstract string applyToServiceInCSVFormat(Service service);
/// <summary> /// Aplică inferența pe un anumit serviciu și returnează răspunsul în format CSV. /// </summary> /// <param name="service">Serviciul pentru care se aplică inferența</param> /// <returns>Rezultatul inferenței în format CSV - fiecare rând conține valoarea finală dar și valorile și numărul de activari a tuturor deciziilor</returns> public override string applyToServiceInCSVFormat(Service service) { return service.name + this.applyToService(service).toCSVFormat() + service.accessPoint; }
/// <summary> /// Aplică inferența pe un anumit serviciu și returnează numărul și intensitatea activării regulilor și a concluziilor. /// </summary> /// <param name="service">Serviciul pentru care se aplică inferența</param> /// <returns>Rezultatul inferenței în sub forma unei subclase RuleActivations</returns> public RuleActivations applyToService(Service service) { RuleActivations result; switch (ClientSettings.Default.RULE_GENERATION_DECISION_ACTIVATION_ALGORITHM) { case (int)DecisionActivationAlgorithms.maximumDecisionActivationLevel: result = new MaxRuleActivations(this._decisionOntology); break; default: result = new MedRuleActivations(this._decisionOntology); break; } Property[] providedProperties = new Property[_requirementOntologies.Count]; for (int i = 0; i < this._requirementOntologies.Count; ++i) { providedProperties[i] = service.functionality.getProperty(this._requirementOntologies[i].name); } foreach (Rule rule in this.rules) { double activationLevel = 0; double minActivationLevel = double.PositiveInfinity; for (int i = 0; i < this._requirementOntologies.Count; ++i) { double intersection = providedProperties[i] == null ? 1 : InferenceMachine.intersect(service, providedProperties[i], this._requirementOntologies[i].terms[rule.requirements[i]]); if (intersection <= 0) { activationLevel = -1; break; } else { if (!double.IsNaN(intersection)) { activationLevel += intersection; minActivationLevel = Math.Min(intersection, minActivationLevel); } } } if (activationLevel > 0 && this._requirementOntologies.Count > 0) { result.activate(rule.decision, ClientSettings.Default.RULE_GENERATION_RULE_ACTIVATION_ALGORITHM == (int)RuleActivationAlgorithms.minimumPropertyActivationLevel ? minActivationLevel : activationLevel / this._requirementOntologies.Count); } } return result; }
/// <summary> /// Aplică inferența pe un anumit serviciu și returnează răspunsul în format CSV. /// </summary> /// <param name="service">Serviciul pentru care se aplică inferența</param> /// <returns>Rezultatul inferenței în format CSV - fiecare rând conține valoarea finală</returns> public override string applyToServiceInCSVFormat(Service service) { return service.name + "," + Math.Round(this.calculateValue(service), 12).ToString("0.############") + "," + service.accessPoint; }
/// <summary> /// Returnează toate proprietățile unui serviciu într-o formă afișabilă. /// </summary> /// <param name="service">Serviciul a cărui proprietăți se caută</param> /// <returns>Proprietățile, fiecare sub formă de string lizibil</returns> public string[] getPrintableProperties(Service service) { try { if (service.functionality != null) { Property[] properties = service.functionality.properties; string[] result = new string[properties.Length]; for (int i = 0; i < result.Length; ++i) { result[i] = properties[i].name + " [" + (service.isFuzzy(properties[i]) ? "fuzzy:" + service.getFuzzyValue(properties[i]).name : "crisp:" + service.getCrispValue(properties[i])) + "]"; } return result; } else { return service.getAllNamesAndValues(); } } catch (Exception) { return new string[0]; } }