/// <param name="serialized">Un obiect RequestShape serializat</param> public RequestShape(string serialized) { string[] aux = serialized.Split(new char[] { '\n' }, 6, StringSplitOptions.None); this.shape = new Term(aux[0], aux[1], aux[2], aux[3], aux[4]); int.TryParse(aux[5], out this.importance); }
/// <summary> /// Constructor privat folosit pentru operații de clonare. /// </summary> private DecisionShape(Term shape, double activationLevel, int activationCount) { this.shape = shape.clone(); this._activationLevel = activationLevel; this._activationCount = activationCount; this.centerOfGravity = this.centerOfMass(); }
/// <param name="serialized">Un obiect de tip Property serializat</param> public Property(string serialized) { string[] aux = serialized.Split(new char[] { '\n' }, StringSplitOptions.None); if (aux == null) { return; } this.name = aux.Length > 0 ? aux[0] : null; try { this.start = double.Parse(aux[1]); } catch (Exception) { this.start = double.NegativeInfinity; } try { this.end = double.Parse(aux[2]); } catch (Exception) { this.end = double.PositiveInfinity; } this._terms = new List<Term>(); for (int i = 3; i < aux.Length; i += 5) { try { Term term = new Term(aux[i], aux[i + 1], aux[i + 2], aux[i + 3], aux[i + 4]); this._terms.Add(term); } catch (Exception) { } } }
/// <param name="term">Forma fuzzy a deciziei</param> /// <param name="scaleStart">Începutul scării de scalare a formei</param> /// <param name="scaleEnd">Sfârșitul scării de scalare a formei</param> public DecisionShape(Term term, double scaleStart, double scaleEnd) { double aux; if (scaleStart > scaleEnd) { aux = scaleStart; scaleStart = scaleEnd; scaleEnd = aux; } aux = scaleEnd > scaleStart ? scaleEnd - scaleStart : 1; this.shape = new Term(term.name, (term.start - scaleStart) / aux, (term.left - scaleStart) / aux, (term.right - scaleStart) / aux, (term.end - scaleStart) / aux); this._activationLevel = 0; this._activationCount = 0; this.centerOfGravity = this.centerOfMass(); }
/// <param name="shape">Forma cererii - termen fuzzy</param> /// <param name="importance">Importanţa acestei forme</param> public RequestShape(Term shape, int importance) { this.shape = shape.clone(); this.importance = importance; }
/// <summary> /// Indică o modificare a termenului cererii pentru proprietatea curentă produsă din fereastra de vizualizare a termenilor. /// Reîmprospătează interfaţa ferestrei. /// </summary> /// <param name="newTerm">Forma termenului dupa schimbare</param> private void visualUpdateShape(Term newTerm) { this.propertyTabPageStates[this.tcProperties.SelectedIndex].customTerm = newTerm; this.updateShape(); }
/// <summary> /// Reîmprospătează termenul cererii pentru proprietatea curentă în fereastră şi fereastra de vizualizare a termenilor. /// </summary> private void updateShape() { Term term = this.propertyTabPageStates[this.tcProperties.SelectedIndex].customTerm; if (term == null) { this.txtStart.Text = this.txtEnd.Text = this.txtLeft.Text = this.txtRight.Text = ""; } else { this.propertyTabPageStates[this.tcProperties.SelectedIndex].customTerm = term = term.getCompliant(this.currentFunctionality.properties[this.tcProperties.SelectedIndex]); if (term == null) { this.updateShape(); return; } this.txtStart.Text = term.start.ToString(); this.txtEnd.Text = term.end.ToString(); this.txtLeft.Text = term.left.ToString(); this.txtRight.Text = term.right.ToString(); } if (this.visualizer != null) { this.visualizer.removeTerm("Request"); if (term != null) { term = new Term("Request", term.start, term.left, term.right, term.end); this.visualizer.addTerm(term, System.Drawing.Color.FromArgb(200, System.Drawing.Color.Red), false, true, this.visualUpdateShape); } } }
/// <summary> /// Indică apăsarea butonului pentru vizualizarea grafică a formei termenului din cerere. /// Deschide o astfel de vizualizare. /// </summary> private void btnPreviewShape_Click(object sender, EventArgs e) { this.btnPreviewShape.Enabled = false; Property property = this.currentFunctionality.properties[this.tcProperties.SelectedIndex]; this.visualizer = new Visualizer(property.name, this.Width, -1, this.Left, this.Top + this.Height, new FormClosedEventHandler(this.graphicVisualizer_Close)); this.visualizer.addProperty(property, System.Drawing.Color.FromArgb(100, System.Drawing.Color.Green), System.Drawing.Color.FromArgb(50, System.Drawing.Color.Blue), true); Term term = this.propertyTabPageStates[this.tcProperties.SelectedIndex].customTerm; if (term != null) { term = new Term("Request", term.start, term.left, term.right, term.end); this.visualizer.addTerm(term, System.Drawing.Color.FromArgb(200, System.Drawing.Color.Red), false, true, this.visualUpdateShape); } }
/// <summary> /// Extrage funcţionalitatea dintr-un fişier xml şi o adaugă la cele cunoscute. /// </summary> /// <param name="key">Cheia functionalitatii pe serverul UDDI</param> /// <param name="url">URL-ul fiserului xml ce contine functionalitatea</param> public void addFunctionalityFromXml(string key, string url) { XMLElement root = XMLParser.parse(url); if (root != null) { if (root.containsElements("functionality")) { XMLElement functionality = root.getElements("functionality")[0]; if (functionality.containsAttribute("name")) { string functionalityName = functionality.getAttribute("name"); foreach (Functionality knownFunctionality in this._functionalities) { if (knownFunctionality.name == functionalityName) { return; } } if (functionality.containsElements("property")) { List<Property> functionalityProperties = new List<Property>(); List<XMLElement> properties = functionality.getElements("property"); foreach (XMLElement property in properties) { if (property.containsAttribute("name")) { string propertyName = property.getAttribute("name"); double propertyStart, propertyEnd; if (property.containsAttribute("start") && property.containsAttribute("end")) { if (double.TryParse(property.getAttribute("start"), out propertyStart) && double.TryParse(property.getAttribute("end"), out propertyEnd)) { if (property.containsElements("term")) { List<Term> propertyTerms = new List<Term>(); List<XMLElement> terms = property.getElements("term"); foreach (XMLElement term in terms) { if (term.containsAttribute("name") && term.containsAttribute("start") && term.containsAttribute("left") && term.containsAttribute("right") && term.containsAttribute("end")) { Term auxTerm = new Term(term.getAttribute("name"), term.getAttribute("start"), term.getAttribute("left"), term.getAttribute("right"), term.getAttribute("end")); if (!auxTerm.failedAParse) { propertyTerms.Add(auxTerm); } else { return; } } else { return; } } functionalityProperties.Add(new Property(propertyName, propertyStart, propertyEnd, propertyTerms)); } else { return; } } else { return; } } else { return; } } else { return; } } this._functionalities.Add(new Functionality(functionalityName, key, url, functionalityProperties)); } } } } }
/// <summary> /// Construiește ontologia unei premise a regulilor prin adăugarea de vecini formelor cererilor. /// </summary> /// <param name="requestedShape">Forma cererii pentru care se construiește ontologia</param> /// <param name="domainStart">Începutul intervalului în care proprietatea poate lua valori și deci până unde se pot întinde vecinii</param> /// <param name="domainEnd">Sfârșitul intervalului în care proprietatea poate lua valori și deci până unde se pot întinde vecinii</param> /// <param name="exactlyLocation">Parametru de ieșire - indică ce termen din proprietate este cel identic cu cererea inițială</param> /// <returns>Ontologia premisei</returns> private Property constructRequirementOntology(RequestShape requestedShape, double domainStart, double domainEnd, out int exactlyLocation) { int numberOfNeighborsGeneratedOnEachSide = ClientSettings.Default.RULE_GENERATION_NUMBER_OF_NEIGHBOURS_ON_EACH_SIDE; numberOfNeighborsGeneratedOnEachSide = numberOfNeighborsGeneratedOnEachSide <= 1 ? 1 : numberOfNeighborsGeneratedOnEachSide >= 6 ? 6 : numberOfNeighborsGeneratedOnEachSide; List<Term> resultTerms = new List<Term>(); double addLength = 0; if (ClientSettings.Default.RULE_GENERATION_FORCE_NEIGHBOURS) { addLength = (requestedShape.shape.start - domainStart) / numberOfNeighborsGeneratedOnEachSide; } else { addLength = (requestedShape.shape.end - requestedShape.shape.start) / 4; if (double.IsInfinity(addLength) || double.IsNaN(addLength)) { addLength = (requestedShape.shape.right - requestedShape.shape.left) / 2; addLength = double.IsInfinity(addLength) || double.IsNaN(addLength) ? requestedShape.shape.left - requestedShape.shape.start : addLength; addLength = double.IsInfinity(addLength) || double.IsNaN(addLength) ? requestedShape.shape.end - requestedShape.shape.right : addLength; } } double nowValue = requestedShape.shape.start - addLength; List<double> marginalValues = new List<double>(); for (int i = 0; i < numberOfNeighborsGeneratedOnEachSide - 1 && ((addLength > 0 && nowValue > domainStart) || (addLength < 0 && nowValue < domainStart)); ++i) { marginalValues.Add(nowValue); nowValue -= addLength; } if (requestedShape.shape.left != domainStart && (!ClientSettings.Default.RULE_GENERATION_FORCE_NEIGHBOURS || addLength != 0)) { marginalValues.Add(domainStart); } Term previewsTerm = requestedShape.shape; for (int i = 0; i < marginalValues.Count; ++i) { double auxStart = 0; double auxLeft = 0; double auxRight = 0; double auxEnd = 0; auxEnd = previewsTerm.left; auxRight = previewsTerm.start; auxStart = marginalValues[i]; auxLeft = auxStart + (auxEnd - auxRight) / 2; if ((addLength > 0 && auxLeft < auxStart) || (addLength < 0 && auxLeft > auxStart)) { auxLeft = auxStart; } else { if ((addLength > 0 && auxLeft > auxRight) || (addLength < 0 && auxLeft < auxRight)) { auxLeft = auxRight; } } Term auxTerm = new Term(this.resourceManager.GetString(prefixes[marginalValues.Count - 1][i]).Replace("*", "Left"), auxStart, auxLeft, auxRight, auxEnd); resultTerms.Insert(0, auxTerm); previewsTerm = auxTerm; } if (resultTerms.Count > 0) { Term auxTerm = resultTerms[0]; resultTerms[0] = new Term(auxTerm.name, auxTerm.start, auxTerm.start, auxTerm.right, auxTerm.end); } exactlyLocation = resultTerms.Count; resultTerms.Add(new Term("Exactly", requestedShape.shape.start, requestedShape.shape.left, requestedShape.shape.right, requestedShape.shape.end)); if (ClientSettings.Default.RULE_GENERATION_FORCE_NEIGHBOURS) { addLength = (domainEnd - requestedShape.shape.end) / numberOfNeighborsGeneratedOnEachSide; } nowValue = requestedShape.shape.end + addLength; marginalValues = new List<double>(); for (int i = 0; i < numberOfNeighborsGeneratedOnEachSide - 1 && ((addLength > 0 && nowValue < domainEnd) || (addLength < 0 && nowValue > domainEnd)); ++i) { marginalValues.Add(nowValue); nowValue += addLength; } if (requestedShape.shape.right != domainEnd && (!ClientSettings.Default.RULE_GENERATION_FORCE_NEIGHBOURS || addLength != 0)) { marginalValues.Add(domainEnd); } previewsTerm = requestedShape.shape; for (int i = 0; i < marginalValues.Count; ++i) { double auxStart = 0; double auxLeft = 0; double auxRight = 0; double auxEnd = 0; auxStart = previewsTerm.right; auxLeft = previewsTerm.end; auxEnd = marginalValues[i]; auxRight = auxEnd - (auxLeft - auxStart) / 2; if ((addLength > 0 && auxRight > auxEnd) || (addLength < 0 && auxRight < auxEnd)) { auxRight = auxEnd; } else { if ((addLength > 0 && auxRight < auxLeft) || (addLength < 0 && auxRight > auxLeft)) { auxRight = auxLeft; } } Term auxTerm = new Term(this.resourceManager.GetString(prefixes[marginalValues.Count - 1][i]).Replace("*", "Right"), auxStart, auxLeft, auxRight, auxEnd); resultTerms.Add(auxTerm); previewsTerm = auxTerm; } if (resultTerms.Count > 0) { Term auxTerm = resultTerms[resultTerms.Count - 1]; resultTerms[resultTerms.Count - 1] = new Term(auxTerm.name, auxTerm.start, auxTerm.left, auxTerm.end, auxTerm.end); } return new Property(requestedShape.shape.name, domainStart, domainEnd, resultTerms); }
/// <summary> /// Construiește ontologia deciziilor regulilor. /// </summary> private void constructDecisionOntology() { this._decisionOntology = new List<DecisionShape>(); int outcomes = (this.numberOfOutcomes + 1) / 2; List<Term> auxTerms = new List<Term>(); for (int i = 0; i < outcomes; ++i) { auxTerms.Insert(0, new Term(this.resourceManager.GetString(SelectionRules.outcomePrefixes[outcomes - 1][i]).Replace("*", "Reject"), 0, 0, 0, 0)); } outcomes = this.numberOfOutcomes / 2; for (int i = 0; i < outcomes; ++i) { auxTerms.Insert(i, new Term(this.resourceManager.GetString(SelectionRules.outcomePrefixes[outcomes - 1][i]).Replace("*", "Accept"), 0, 0, 0, 0)); } outcomes = auxTerms.Count; if (outcomes > 0) { double largeGap = (double)1 / (outcomes + 1); double smallGap = largeGap / (outcomes - 1); double location = 0; auxTerms[auxTerms.Count - 1] = new Term(auxTerms[auxTerms.Count - 1].name, 0, 0, auxTerms[auxTerms.Count - 1].right, auxTerms[auxTerms.Count - 1].end); for (int i = auxTerms.Count - 1; i > 0; --i) { location += largeGap; auxTerms[i - 1] = new Term(auxTerms[i - 1].name, location, location + smallGap, auxTerms[i - 1].right, auxTerms[i - 1].end); auxTerms[i] = new Term(auxTerms[i].name, auxTerms[i].start, auxTerms[i].left, location, location + smallGap); location += smallGap; this._decisionOntology.Insert(0, new DecisionShape(auxTerms[i], 0, 1)); } auxTerms[0] = new Term(auxTerms[0].name, auxTerms[0].start, auxTerms[0].left, 1, 1); this._decisionOntology.Insert(0, new DecisionShape(auxTerms[0], 0, 1)); } }
/// <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> /// Se asigură că valorile cererii se încadrează în restricţiile ontologiei pentru un termen fuzzy. /// </summary> /// <param name="property">Proprietatea din ontologie a cărei restricţii trebuiesc respectate.</param> private void reconstructFuzzyTerm(Property property) { bool isAtLeast = this.parent.cboFuzzyValuePrefix.SelectedIndex == (int)Constants.VALUE_PREFIXES.AT_LEAST || this.parent.cboFuzzyValuePrefix.SelectedIndex == (int)Constants.VALUE_PREFIXES.AT_LEAST_ABOUT; bool isAtMost = this.parent.cboFuzzyValuePrefix.SelectedIndex == (int)Constants.VALUE_PREFIXES.AT_MOST || this.parent.cboFuzzyValuePrefix.SelectedIndex == (int)Constants.VALUE_PREFIXES.AT_MOST_ABOUT; double aroundPercentage = this.parent.nudFuzzyPercent.Visible ? (double)this.parent.nudFuzzyPercent.Value / 100 : 0; double start = 0; double left = 0; double right = 0; double end = 0; Term fuzzyTerm = property.terms[this._fuzzyIndex]; aroundPercentage = aroundPercentage < 0 ? 0 : aroundPercentage > 1 ? 1 : aroundPercentage; double domainLength = Math.Abs(property.start - property.end); if (double.IsInfinity(domainLength)) { domainLength = 2 * Math.Min(Math.Abs(fuzzyTerm.start - property.start), Math.Abs(fuzzyTerm.end - property.end)); } if (double.IsInfinity(domainLength) || double.IsNaN(domainLength)) { domainLength = 0; } double distance = (property.start > property.end ? -1 : 1) * aroundPercentage * domainLength / 2; if (isAtMost) { start = left = property.start; } else { start = (property.start > property.end ? fuzzyTerm.end : fuzzyTerm.start) - distance; left = property.start > property.end ? fuzzyTerm.right : fuzzyTerm.left; } if (isAtLeast) { right = end = property.end; } else { right = property.start > property.end ? fuzzyTerm.left : fuzzyTerm.right; end = (property.start > property.end ? fuzzyTerm.start : fuzzyTerm.end) + distance; } this._customTerm = new Term(property.name, start, left, right, end); }
/// <summary> /// Schimbă axa de afişare a unui termen. /// </summary> /// <param name="term">Termenul pentru care se schimbă axa de afişare</param> /// <param name="secondAxis">True indică plasarea formelor pe axa Y2, False pe axa Y1</param> public void changeTermAxis(Term term, bool secondAxis) { if (term != null && this.termAssocGraphics.ContainsKey(term)) { this.termAssocGraphics[term].associatedCurve.IsY2Axis = secondAxis; this.zedGraph.GraphPane.AxisChange(); this.zedGraph.Invalidate(); } }
/// <summary> /// Adaugă un termen în graficul vizual. /// </summary> /// <param name="term">Termenul de adăugat</param> /// <param name="color">Culoarea termenului</param> /// <param name="secondAxis">True indică plasarea formelor pe axa Y2, False pe axa Y1</param> /// <param name="isEditable">Indică dacă se acceptă editarea termenului direct din interfaţa vizuală</param> /// <param name="eventHandler">Dacă este editabil ce callback este apelat după editare, null pentru nici o apelare</param> public void addTerm(Term term, Color color, bool secondAxis, bool isEditable, AfterEditEventHandler eventHandler) { if (term == null || this.termAssocGraphics.ContainsKey(term)) { return; } PointPairList ppList = new PointPairList(new double[] { term.start, term.left, term.right, term.end }, new double[] { 0, 1, 1, 0 }); LineItem curve = this.zedGraph.GraphPane.AddCurve(term.name, ppList, Color.FromArgb(255, color), ZedGraph.SymbolType.Circle); curve.Line.Width = lineWidth; curve.Line.Fill = new Fill(color, Color.FromArgb(color.A / 4, color), gradientAngle); curve.Symbol.Size = symbolSize; curve.Symbol.Fill = symbolFill; curve.IsY2Axis = secondAxis; this.termAssocGraphics.Add(term, new GraphicalTerm(isEditable, eventHandler, curve)); this.zedGraph.GraphPane.AxisChange(); this.zedGraph.Invalidate(); }