protected List <ReteNode> Commonize(List <ReteNode> exist) { bool changed = true; //на каждой итерации цикла множество уменьшается на 1 элемент, либо остаётся неизменным //если множество осталось неизменным, то алгоритм заканчивает работу while (changed) { changed = false; // на каждой итерации проверяем обновилось ли множество for (int i = 0; i < exist.Count; i++) { for (int j = i + 1; j < exist.Count; j++) //для каждой пары [i, j] { ReteNode commonOutput = null; //пытаемся найти общего наследника if (exist[i].HasCommonOutputWith(exist[j], out commonOutput)) //если наследник существует { exist.RemoveAt(j); //удаляем кандидатов из множества exist.RemoveAt(i); exist.Add(commonOutput); //вставляем найденного наследника changed = true; break; } } if (changed == true) { break; //если множество изменилось, то переходим к следующей итерации } } } return(exist); }
/// <summary> /// Удаляет факт из сети с корнем к текущем ноде. /// </summary> /// <param name="fact">Удаляемый факт.</param> /// <param name="parent">Текущий родитель.</param> public virtual void RemoveFact(IData fact, ReteNode parent) { foreach (var output in outputs) { output.RemoveFact(fact, this); } }
/// <summary> /// Добавляет новое правило в сеть. /// </summary> /// <param name="statement">Новое правило.</param> /// <param name="parent">Текущий родитель.</param> /// <param name="end">Конечный нод сети.</param> public virtual void AddStatement(ProductionRule statement, ReteNode parent, AgendaNode end) { foreach (var output in outputs) { output.AddStatement(statement, this, end); } }
/// <summary> /// Удаляет факт из сети с корнем к текущем ноде. /// </summary> /// <param name="fact">Удаляемый факт.</param> /// <param name="parent">Текущий родитель.</param> public override void RemoveFact(IData fact, ReteNode parent) { alphaMemory.Remove(fact); if (alphaMemory.Count == 0) //выполнимых фактов не осталось { base.RemoveFact(fact, this); } }
/// <summary> /// Сливает текущий нод с заданным. /// </summary> /// <param name="node">Второй нод.</param> /// <returns>Возвращает новый экземпляр <see cref="ExpertSystemShell.KnowledgeBases.ProductionModel.ReteNode"/>, /// который является наследником двух заданных нодов.</returns> public virtual ReteNode Merge(ReteNode node) { BetaNode result = new BetaNode(); result.inputs[0] = this; result.inputs[1] = node; return(result); }
/// <summary> /// Добавляет новое правило в сеть. /// </summary> /// <param name="statement">Новое правило.</param> /// <param name="parent">Текущий родитель.</param> /// <param name="end">Конечный нод сети.</param> public override void AddStatement(ProductionRule statement, ReteNode parent, AgendaNode end) { if (this.outputs.Count == 0) { this.outputs.Add(new BetaMemoryNode()); this.outputs[0].Inputs.Add(this); } base.AddStatement(statement, parent, end); }
/// <summary> /// Добавляет новое правило в сеть. /// </summary> /// <param name="statement">Новое правило.</param> /// <param name="parent">Текущий родитель.</param> /// <param name="end">Конечный нод сети.</param> public override void AddStatement(ProductionRule statement, ReteNode parent, AgendaNode end) { if (!this.outputs.Any((a) => { return(a is BetaMemoryNode); })) { this.outputs.Add(new BetaMemoryNode()); this.outputs.Last().Inputs.Add(this); } base.AddStatement(statement, this, end); }
/// <summary> /// Пропускает факт через сеть с корнем в текущем ноде. /// </summary> /// <param name="fact">Факт.</param> /// <param name="parent">Текущий родитель.</param> public override void AddFact(IData fact, ReteNode parent) { var clonedPred = predicate.Copy(); clonedPred.SetVariable(fact.Name, fact); if (clonedPred.Calculate().Equals(true)) { alphaMemory.Add(fact); base.AddFact(fact, this); } }
/// <summary> /// Изменяет значение заданного факта в текущей сети. /// </summary> /// <param name="oldValue">Старое значение факта.</param> /// <param name="newValue">Новое значение факта.</param> /// <param name="parent">Текущий родитель.</param> public virtual void ChangeFact(IData oldValue, IData newValue, ReteNode parent) { foreach (var output in outputs) { output.RemoveFact(oldValue, this); } foreach (var output in outputs) { output.AddFact(newValue, this); } }
/// <summary> /// Удаляет факт из сети с корнем к текущем ноде. /// </summary> /// <param name="fact">Удаляемый факт.</param> /// <param name="parent">Текущий родитель.</param> public override void RemoveFact(IData fact, ReteNode parent) { BetaMemoryNode bmn = (BetaMemoryNode)parent; foreach (var item in bmn.BetaMemory) { if (!ready.Contains(item)) { ready.Remove(item); } } }
/// <summary> /// Добавляет новое правило в сеть. /// </summary> /// <param name="statement">Новое правило.</param> /// <param name="parent">Текущий родитель.</param> /// <param name="end">Конечный нод сети.</param> public override void AddStatement(ProductionRule statement, ReteNode parent, AgendaNode end) { if (outputs[0] == null) { outputs[0] = end; end.Inputs.Add(this); } if (!betaMemory.Contains(statement.Name)) { betaMemory.Add(statement.Name); } base.AddStatement(statement, parent, end); }
protected void AddAndMerge(IEnumerable <Expression> conditions, ProductionRule statement, AgendaNode end) { List <ReteNode> exist = new List <ReteNode>(); //список уже существующих нодов List <ReteNode> add = new List <ReteNode>(); // список новых нодов foreach (var c in conditions) //находим уже сущеcтвующие Alpha ноды { AlphaNode n = null; if (FindNode(c, out n)) // если нод существует, то добавляем его к списку существующих { exist.Add(n); } else { AlphaNode n1 = new AlphaNode(); //иначе создаём новый n1.Predicate = c; n1.Inputs[0] = this; //связываем его с корнем this.outputs.Add(n1); add.Add(n1); //добавляем его в список новых нодов } } exist = Commonize(exist); //находим наиболее общих наследников foreach (var n in add) //теперь всё в одном списке { exist.Add(n); } while (exist.Count > 1) //объединяем всё, что осталось { ReteNode n1 = exist[0]; ReteNode n2 = exist[1]; exist.RemoveAt(0); exist.RemoveAt(0); ReteNode unuion = n1.Merge(n2); exist.Add(unuion); } BetaMemoryNode bm = (BetaMemoryNode)exist[0].Outputs.FirstOrDefault((a) => { return(a is BetaMemoryNode); }); if (bm == null) { bm = new BetaMemoryNode(); bm.Outputs[0] = end; bm.Inputs.Add(exist[0]); exist[0].Outputs.Add(bm); } if (!bm.BetaMemory.Contains(statement.Name)) { bm.BetaMemory.Add(statement.Name); } }
/// <summary> /// Сливает текущий нод с заданным. /// </summary> /// <param name="node">Второй нод.</param> /// <returns> /// Возвращает новый экземпляр <see cref="ExpertSystemShell.KnowledgeBases.ProductionModel.ReteNode" />, /// который является наследником двух заданных нодов. /// </returns> public override ReteNode Merge(ReteNode node) { ReteNode result = base.Merge(node); this.outputs.Add(result); if (node is AlphaNode) { node.Outputs.Add(result); } else { node.Outputs.Add(result); } return(result); }
/// <summary> /// Определяет, есть ли у текущего и заданного нода общий потомок. /// </summary> /// <param name="node">Второй нод.</param> /// <param name="ouput">Наследник.</param> /// <returns>Возвращает <c>true</c>, если найден наследник, иначе - <c>false</c>.</returns> public bool HasCommonOutputWith(ReteNode node, out ReteNode ouput) { foreach (var n1 in this.outputs) { foreach (var n2 in node.outputs) { if (n1 == n2) { ouput = n1; return(true); } } } ouput = null; return(false); }
/// <summary> /// Пропускает факт через сеть с корнем в текущем ноде. /// </summary> /// <param name="fact">Факт.</param> /// <param name="parent">Текущий родитель.</param> public override void AddFact(IData fact, ReteNode parent) { var other = inputs[0] == parent ? inputs[1] : inputs[0]; var otherAlpha = other as AlphaNode; if (otherAlpha != null && otherAlpha.AlphaMemory.Any()) { IsActive = true; base.AddFact(fact, parent); } var otherBeta = other as BetaNode; if (otherBeta != null && otherBeta.IsActive) { IsActive = true; base.AddFact(fact, parent); } }
public override void AddStatement(ProductionRule statement, ReteNode parent, AgendaNode end) { AddStatement(statement.Condition, statement, end); }