// NOTE: Maybe should REMOVE this method // because the formulas that are And // will eventually be expanded by ExpandToAnd(Symbol). // It will also make the Tableau more easy to look. /// <summary> /// Expand all the Ands formula /// </summary> /// <param name="formulas"></param> /// <returns>A set of formulas with all the And expanded</returns> public static HashSet <Symbol> ExpandAllAnds( TableauNode curNode, bool alphaRules, bool deltaRules) { List <Symbol> delList = new List <Symbol>(); List <Symbol> addList = new List <Symbol>(); HashSet <Symbol> formulas = curNode.SetFormulas; // Subformula that is expanded to And foreach (Symbol subformula in formulas) { List <Symbol> expansion = new List <Symbol>(); if (alphaRules) { expansion = ExpandToAnd(subformula); } // Delta rules - Expand !x and ~@x if (deltaRules) { expansion = DeltaRules(subformula, curNode); } if (!(expansion is null)) { foreach (Symbol term in expansion) { addList.Add(term); } delList.Add(subformula); } } foreach (Symbol subformula in delList) { formulas.Remove(subformula); } foreach (Symbol subformula in addList) { formulas.Add(subformula); } delList.Clear(); addList.Clear(); return(formulas); }
public void Build() { // Root of Tableau Root = new TableauNode(new HashSet <Symbol>(new SymbolComparer()) { new Not(Formula) }); Root.RuleApplied = TableauRule.NONE; bool unsatis = BuildUtil(Root); State = 0; if (unsatis) { State = 1; } }
public static List <Symbol> DeltaRules(Symbol formula, TableauNode currentNode) { char newVar = '#'; for (char c = 'a'; c <= 'z'; c++) { if (!currentNode.CurrentVariables[c]) { newVar = c; break; } } if (formula is Existential) { char boundedVar = ((Existential)formula).BoundVariables[0]; // extend later formula = formula.ChangeVariableName(boundedVar, newVar, true).Childs[0]; currentNode.CurrentVariables[newVar] = true; } else if (formula is Not && formula.Childs[0] is Universal) { formula = formula.Childs[0]; char boundedVar = ((Universal)formula).BoundVariables[0]; // extend later formula = new Not(formula.ChangeVariableName(boundedVar, newVar, true).Childs[0]); currentNode.CurrentVariables[newVar] = true; } else { return(null); } return(new List <Symbol>() { formula }); }
public static List <Symbol> GammaRules(Symbol formula, TableauNode currentNode) { List <Symbol> returnList = new List <Symbol>(); if (formula is Universal) { foreach (char c in currentNode.ListVariables) { if (formula.GammaApplied[c]) { continue; } char boundVariable = ((Universal)formula).BoundVariables[0]; returnList.Add(formula.ChangeVariableName(boundVariable, c, true).Childs[0]); formula.GammaApplied[c] = true; } } else if (formula is Not && formula.Childs[0] is Existential) { char boundVariable = ((Existential)formula.Childs[0]).BoundVariables[0]; foreach (char c in currentNode.ListVariables) { if (formula.GammaApplied[c]) { continue; } returnList.Add(new Not(formula.ChangeVariableName(boundVariable, c, true).Childs[0].Childs[0])); formula.GammaApplied[c] = true; } } return(returnList.Count == 0 ? null : returnList); }
/* * 1) Check contradiction * 2) Alpha rules * 3) Delta rules * 4) Beta rules * 5) Gamma rules */ /// <summary> /// Build the Semantic Tableau /// </summary> /// <returns>True if the formula is Unsatifiable (has contradiction)</returns> public bool BuildUtil(TableauNode curNode) // return true if contradiction { TableauNode newNode = new TableauNode(curNode.SetFormulas, curNode.CurrentVariables); if (CheckContradiction(newNode.SetFormulas)) { newNode.SetFormulas = new HashSet <Symbol>() { new Constant('0') }; curNode.Childs.Add(newNode); return(true); } HashSet <Symbol> formulas = newNode.SetFormulas; ////////////////////////////////////////////////////////////// // Alpha Rules ////////////////////////////////////////////////////////////// formulas = ExpandAllAnds(newNode, true, false); if (!TableauNode.EqualSet(formulas, curNode.SetFormulas)) // successful { newNode.RuleApplied = TableauRule.ALPHA; curNode.Childs.Add(newNode); return(BuildUtil(newNode)); } // Haven't applied Alpha rules // Continue with ////////////////////////////////////////////////////////////// // Delta rules ////////////////////////////////////////////////////////////// formulas = ExpandAllAnds(newNode, false, true); if (!TableauNode.EqualSet(formulas, curNode.SetFormulas)) // successful { newNode.RuleApplied = TableauRule.DELTA; curNode.Childs.Add(newNode); return(BuildUtil(newNode)); } ////////////////////////////////////////////////////////////// // Beta Rules ////////////////////////////////////////////////////////////// bool CurrentlyContradicted = true; Symbol chosenFormula = null; // The formula that can be applied beta rules List <Symbol> expansion = new List <Symbol>(); // expanded version of the chosen formula // Find a subformula that can be applied beta rules foreach (Symbol subformula in formulas) { expansion = ExpandToOr(subformula); if (expansion is null) { continue; } chosenFormula = subformula; break; } // There exist a formula expanded. if (!(chosenFormula == null)) { formulas.Remove(chosenFormula); // remove the formula foreach (Symbol term in expansion) { formulas.Add(term); // Add an expanded subformula var newSet = new HashSet <Symbol>(new SymbolComparer()); foreach (var item in formulas) { newSet.Add(ObjectExtensions.Copy(item)); } TableauNode tmpNode = new TableauNode(newSet, curNode.CurrentVariables); tmpNode.RuleApplied = TableauRule.BETA; curNode.Childs.Add(tmpNode); if (!BuildUtil(tmpNode)) { CurrentlyContradicted = false; } formulas.Remove(term); } return(CurrentlyContradicted); // both childs must be contradition } ////////////////////////////////////////////////////////////// // Gamma rules ////////////////////////////////////////////////////////////// var expansionStorage = new HashSet <Symbol>(new SymbolComparer()); expansion = new List <Symbol>(); foreach (var subformula in formulas) { expansion = GammaRules(subformula, newNode); if (expansion is null) { continue; } foreach (var expansionTerm in expansion) { expansionStorage.Add(expansionTerm); } } if (expansionStorage.Count > 0) { foreach (var expansionTerm in expansionStorage) { formulas.Add(expansionTerm); } curNode.Childs.Add(newNode); newNode.RuleApplied = TableauRule.GAMMA; return(BuildUtil(newNode)); } return(false); }
public int GenerateGraphUtil(StreamWriter sw, TableauNode u) { string content = ""; // text of the Tableau Node (the set of formulas at the current node) // Add all formulas to the content foreach (var formula in u.SetFormulas) { content += formula.ToString() + "\n"; } //content = content.Remove(content.Length - 1); // remove last ',' //content = content.Remove(1, 1); // remove first space //content += "]"; // List active variables content += " ["; foreach (char c in u.ListVariables) { content += c + ","; } if (content[content.Length - 1] == ',') { content = content.Remove(content.Length - 1); // remove last ',' } content += "]"; int uNum = Counter; // ID of current node string fillColor = (u.RuleApplied == TableauRule.ALPHA ? "yellow" : u.RuleApplied == TableauRule.BETA ? "palegreen" : u.RuleApplied == TableauRule.DELTA ? "skyblue" : u.RuleApplied == TableauRule.GAMMA ? "brown1" : "gray88"); // content of the node string graphvizContent = $"\tnode{uNum} [shape=rectangle; style = filled;" + $"label = \"{content}\"; color = black; fillcolor={fillColor}];"; // if this node is a contradiction (a node containing only false) // then color it red if (TableauNode.EqualSet(u.SetFormulas, new HashSet <Symbol>() { new Constant('0') })) { graphvizContent = $"\tnode{uNum} [shape=rectangle; style=filled;" + $"label = \"{content}\"; color=crimson fillcolor={fillColor}];"; } // draw current node sw.WriteLine(graphvizContent); foreach (TableauNode v in u.Childs) { Counter++; int vNum = GenerateGraphUtil(sw, v); sw.WriteLine("\tnode{0} -- node{1};", uNum, vNum); // draw edge to child node } return(uNum); // return ID of current node }