/// <summary> /// a<=>b into (a=>b)&(b=>a) into ((~a||b)&(a||~b)) (Prioritize CNF over DNF) /// Warning: This method is one directional, do not use this to convert a logic block into <=> /// </summary> /// <param name="logicBlock"></param> /// <returns>The block passed to this method</returns> public override Block Translate() { if (FirstBlock == null || SecondBlock == null) { ThrowErrorOnFirstCheck(); } if (!Logic.IsBiconditional) { return(ConcatStoredBlocks()); } Block cloneFirstBlock = new Block(FirstBlock.GetContent(true).ToString(), FirstBlock.IsNegated), cloneSecondBlock = new Block(SecondBlock.GetContent(true).ToString(), SecondBlock.IsNegated); // (~a||b) FirstBlock.SetNegation(!FirstBlock.IsNegated) .InsertBack(new Block(PropositionalLogic.Disjunction)) .InsertBack(SecondBlock); // (a||~b) cloneFirstBlock .InsertBack(new Block(PropositionalLogic.Disjunction)) .InsertBack(cloneSecondBlock.SetNegation(!cloneFirstBlock.IsNegated)); // ((~a||b)&(a||~b)) var nested = new Block(FirstBlock); nested.InsertBack(new Block(PropositionalLogic.Conjunction)) .InsertBack(new Block(cloneFirstBlock)); return(nested); }
/// <summary> /// a->b <=> (~a||b) /// </summary> /// <param name="logicBlock"></param> /// <returns>The block passed to this method</returns> public override Block Translate() { if (FirstBlock == null || SecondBlock == null) { ThrowErrorOnFirstCheck(); } // elimination if (Logic.IsImplication) { FirstBlock.SetNegation(!FirstBlock.IsNegated) .InsertBack(new Block(PropositionalLogic.Disjunction)) .InsertBack(SecondBlock); return(FirstBlock); } // reverse elimination // ~a||b into a=>b and a||~b into b=>a // accepting either one of them is negated, not both true or both false => XOR is the best choice if (Logic.IsDisjunction && (FirstBlock.IsNegated ^ SecondBlock.IsNegated)) { FirstBlock = FirstBlock.IsNegated ? FirstBlock : SecondBlock; SecondBlock = FirstBlock.IsNegated ? SecondBlock : FirstBlock; FirstBlock.SetNegation(!FirstBlock.IsNegated) .InsertBack(new Block(PropositionalLogic.Implication)) .InsertBack(SecondBlock); return(FirstBlock); } return(ConcatStoredBlocks()); }
protected override void Layout() { Renderman renderer = Element.Document.Renderer; ComputedStyle computed = Element.Style.Computed; // Get the top left inner corner (inside margin and border): int width = computed.PaddedWidth; int height = computed.PaddedHeight; int top = computed.OffsetTop + computed.BorderTop; int left = computed.OffsetLeft + computed.BorderLeft; // Is it clipped? if (renderer.IsInvisible(left, top, width, height)) { // Totally not visible. return; } // Ensure we have a batch (doesn't change graphics or font thus both nulls): SetupBatch(null, null); Add(); // Using firstblock as our block here. // Set the UV to that of the solid block colour pixel: FirstBlock.SetSolidColourUV(); // Set the (overlay) colour: FirstBlock.SetColour(BackingColour); // And finally sort out the verts: FirstBlock.SetClipped(renderer.ClippingBoundary, new BoxRegion(left, top, width, height), renderer, computed.ZIndex - 0.006f); }
private Block RelatedTheorems() { string firstContent = FirstBlock.GetContent(true).ToString(), secondContent = SecondBlock.GetContent(true).ToString(); bool isConjunctive = Logic.IsConjunction; if (firstContent == secondContent) { return(FirstBlock.IsNegated != SecondBlock.IsNegated ? new Block(isConjunctive ? "false" : "true") : // complement FirstBlock); // idempotent } switch (firstContent) { case "true": return(isConjunctive ? SecondBlock : new Block("true")); // identity case "false": return(isConjunctive ? new Block("false") : SecondBlock); // annulment } return(secondContent switch { "true" => isConjunctive ? FirstBlock : new Block("true"), // identity "false" => isConjunctive ? new Block("false") : SecondBlock, // annulment _ => ConcatStoredBlocks(), });
public override void Paint() { if (FirstBlock == null) { // This can happen if an animation is requesting that a now offscreen element gets painted only. return; } FirstBlock.SetColour(BackingColour); FirstBlock.Paint(); }
/// <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()); }