/// <summary> /// From ~(a||b) to ~a&~b and ~(a&b) to ~a||~b (vice-versa) /// </summary> /// <param name="blockWithNestedContent"></param> /// <returns>The block passed to this method</returns> public override Block Translate() { if (FirstBlock == null && (FirstBlock = SecondBlock) == null) { ThrowErrorOnFirstCheck(); } Block blockWithNestedContent = FirstBlock; if (blockWithNestedContent.ContentType == ContentType.Nested) { blockWithNestedContent.SetNegation(!blockWithNestedContent.IsNegated); BlockIterator.ForEach(blockWithNestedContent.GetContent() as Block, (currentBlock) => { switch (currentBlock.ContentType) { case ContentType.Logic: (currentBlock.GetContent() as PropositionalLogic).Invert(); break; default: currentBlock.SetNegation(!currentBlock.IsNegated); break; } }); } return(blockWithNestedContent); }
private void IterateThroughBlockLists(Block block) { BlockIterator.ForEach(block, (currentBlock) => { // recursion for removal of deep nesting object content = currentBlock.GetContent(); if (content is Block) { IterateThroughBlockLists(content as Block); return; } // we do not want any logic in here if (content is PropositionalLogic) { return; } // definitely a string, containing a symbol string value = content as string; if (!UniqueValues.Contains(value)) { UniqueValues.Add(value); } }); }
/// <summary> /// Check clause (a&b) against one model (row) in truth table /// </summary> /// <param name="rootBlock"></param> /// <param name="model"></param> /// <returns></returns> private bool CheckClauseAgainstModel(Block rootBlock, Model model) { bool result = false; string logic = ""; bool firstValue = true; BlockIterator.ForEach(rootBlock, (block) => { switch (block.ContentType) { case ContentType.Normal: bool blockValue = model.GetTruthBlock(block.GetContent(true).ToString()); if (block.IsNegated) { blockValue = !blockValue; } // if else if (firstValue) { result = blockValue; firstValue = false; return; } result = Verify(result, logic, blockValue); break; case ContentType.Logic: logic = block.GetContent(true).ToString(); break; case ContentType.Nested: bool nestedBlockValue = CheckClauseAgainstModel(block.GetContent() as Block, model); if (block.IsNegated) { nestedBlockValue = !nestedBlockValue; } // if else if (firstValue) { result = nestedBlockValue; firstValue = false; return; } result = Verify(result, logic, nestedBlockValue); break; } }); return(result); }
/// <summary> /// Traverse through the list, regardless of parentheses /// </summary> protected int Traverse(Action <Block, int> action, Block rootBlock = null, int index = 0) { BlockIterator.ForEach(rootBlock ?? RootBlock, (currentBlock) => { if (currentBlock.ContentType == ContentType.Nested) { index = Traverse(action, currentBlock.GetContent() as Block, index); return; } action.Invoke(currentBlock, index++); }); return(index); }
/// <summary> /// Only a||(b&c) <=> (a||b)&(a||c) is available to prioritize CNF over DNF /// </summary> /// <param name="logicBlock"></param> /// <returns>A block containing nested contents, which are distributed from original one</returns> public override Block Translate() { if (FirstBlock == null || Logic == null || SecondBlock == null) { ThrowErrorOnFirstCheck(); } bool isFirstNormal = FirstBlock.ContentType == ContentType.Normal, isSecondNormal = SecondBlock.ContentType == ContentType.Normal; // from left to right instead of expanding from the least to the most symbols // no point in taking a&b or similars into consideration if (!isFirstNormal || !isSecondNormal) { var logic = Logic.ToString(); // swap places: (a&b)||c into c||(a&b) locally if (isSecondNormal) { (FirstBlock, SecondBlock) = (SecondBlock, FirstBlock); } // a&(b||c) like if (FirstBlock.ContentType == ContentType.Normal) { return(Distribute( FirstBlock.IsNegated, FirstBlock.GetContent(true).ToString(), SecondBlock.GetContent() as Block)); } // (a||b)&(c||d) like if (FirstBlock.ContentType == ContentType.Nested) { BlockIterator.ForEach(FirstBlock.GetContent() as Block, (currentBlock) => { if (currentBlock.ContentType == ContentType.Normal) { Distribute( currentBlock.IsNegated, currentBlock.GetContent(true).ToString(), SecondBlock.GetContent() as Block ); } }); return(FirstBlock.GetContent() as Block); } } return(ConcatStoredBlocks()); }
/// <summary> /// Distribute content to nested block using given logic (under assumption that nested block /// contains no more nested contents) /// <para>E.g: a&(b||c) <=> (a&b)||(a&c)</para> /// </summary> /// <param name="content"></param> /// <param name="logic"></param> /// <param name="nested"></param> /// <returns></returns> private Block Distribute(bool isNegated, string content, Block nested) { // with a||(b&c) // isNegated = false, content = a, logic = ||, nested = b&c BlockIterator.ForEach(nested, (currentBlock) => { if (currentBlock.ContentType != ContentType.Logic) { var block = new Block(content, isNegated); // a (or ~a) block.InsertBack(new Block(Logic)) // connective .InsertBack(new Block(currentBlock.GetContent(true).ToString())); // b or c in (b||c) currentBlock.SetContent(block); } }); return(nested); }
/// <summary> /// Represent the whole linked list as a string again /// </summary> /// <returns>A string in form of ~a& to represent a certain part of the list</returns> public override string ToString() { string result = ""; if (NextBlock == null && PreviousBlock == null) { return((IsNegated ? PropositionalLogic.NEGATION : "") + GetContent(true)); } // forward iterate through the list from this block onwards BlockIterator.ForEach(this, (currentBlock) => { // one block of content is pushed into the result (no whitespaces in between) result += (currentBlock.IsNegated ? PropositionalLogic.NEGATION : "") + currentBlock.GetContent(true); }); return(result); }
public void TestGuaranteeCNF() { Assert.DoesNotThrow(() => { foreach (var clause in StartingClauses) { var block = new ClauseRephraser().RephraseIntoBlock(clause); BlockIterator.ForEach(block, (currentBlock) => { // all normal clauses contain only disjunction // conjunction only appears when concatenating two or more clauses if (currentBlock.ContentType == ContentType.Logic) Assert.AreEqual( (currentBlock.GetContent() as PropositionalLogic).IsDisjunction, true ); }); } }); }