dafny how to bound set comprehension resolver? - set

Trying to write an algorithm involving paths from a root of a binary tree to a leaf. I ran into the following error for the ghost var I was trying to define. I had intended to try to show that some other path was in this set. How do I resolve this error?
the result of a set comprehension must be finite, but Dafny's
heuristics can't figure out how to produce a bounded set of values for
'px'Resolver
datatype TreeNode = Nil | Cons(val: nat, left: TreeNode, right: TreeNode)
predicate isPath(paths: seq<TreeNode>, root: TreeNode)
requires root != Nil && root == paths[0] ==> root !in paths[1..]
{
if |paths| == 0 then false else match paths[0] {
case Nil => false
case Cons(val, left, right) => if |paths| == 1 then root == paths[0] else root == paths[0] && (isPath(paths[1..], left) || isPath(paths[1..], right))
}
}
method Test(root: TreeNode) {
ghost var ps := set px: seq<TreeNode> | isPath(px, root) ;
}
I thought that perhaps Dafny implied that there could be a loop in the tree which would result in infinite paths, so I wrote the following to try to assert it was not possible. However, it still did not resolve the issue. I believe there should be a finite albeit large number of paths.
function TreeSet(root: TreeNode): set<TreeNode> {
match root {
case Nil => {}
case Cons(val, left, right) => TreeSet(left)+{root}+TreeSet(right)
}
}
function ChildSet(root: TreeNode): set<TreeNode> {
match root {
case Nil => {}
case Cons(val, left, right) => {left}+ChildSet(left)+{right}+ChildSet(right)
}
}
method Test(root: TreeNode)
requires forall node :: node in TreeSet(root) ==> node !in ChildSet(node)
{
ghost var ps := set px: seq<TreeNode> | isPath(px, root) ;
}

Dafny enforces finiteness of set using syntactic scan and fixed set of heuristics, as a result it is not exhaustive. Following example give same error
predicate test(i: int)
{
i >= 10 && i <= 20
}
method Test(){
ghost var s := set i | test(i);
}
Also no language construct exists to convince dafny that set constructed using set comprehension is finite set.
[1] https://github.com/dafny-lang/dafny/issues/13#issuecomment-286909795
[2] https://github.com/dafny-lang/dafny/issues/1366#issuecomment-906785889

This is not the end of the story.
You can definitely use iset that don't have the constraint to check that they are finite.
The following code snippet works, modulo the fact that there are still unsatisfied preconditions in the recursive calls to isPath:
datatype TreeNode = Nil | Cons(val: nat, left: TreeNode, right: TreeNode)
predicate isPath(paths: seq<TreeNode>, root: TreeNode)
requires root != Nil && root == paths[0] ==> root !in paths[1..]
{
if |paths| == 0 then false else match paths[0] {
case Nil => false
case Cons(val, left, right) => if |paths| == 1 then root == paths[0] else root == paths[0] && (isPath(paths[1..], left) || isPath(paths[1..], right))
}
}
method Test(root: TreeNode) {
ghost var ps := iset px: seq<TreeNode> | |px| > 0 && root != Nil && root == px[0] ==> root !in px[1..] && isPath(px, root) ;
}

Related

Using recursion to get the sum of a tree, but the root node won't add in Kotlin

I'm doing a question to get the sum of an entire tree through recursion, but the root node wont add with the child node. Now I'm aware that the root node is just a value while the child nodes are Tree nodes, so there not the same type.
class TreeNode<T>(var key: T){
var left: TreeNode<T>? = null
var right: TreeNode<T>? = null
}
fun treeSumR(root: TreeNode<Int>): Int{
if (root == null) return 0
return root.key + root.left?.let { treeSumR(it) } + root.right?.let { treeSumR(it) }
}
fun buildTree2(): TreeNode<Int>{
val one = TreeNode(1)
val two = TreeNode(2)
val four = TreeNode(4)
val eleven = TreeNode(11)
val three = TreeNode(3)
val four2 = TreeNode(4)
three.left = eleven
three.right = four
eleven.left = four2
eleven.right = two
four.right = one
return three
}
Any help is appreciated. Thanks.
There is an error on the + operators because you are adding a non-nullable Int (root.key) and nullable Int?s (the sums of the subtrees) together. The sums of the subtrees are nullable because you wrote ?.. Its effect is that the whole expression of root.left?.let { ... } evaluates to null if root.left is null.
You can provide a default value for the expression when it is null by using the elvis operator:
return root.key +
(root.left?.let { treeSumR(it) } ?: 0) +
(root.right?.let { treeSumR(it) } ?: 0)
However, since you are already checking if root is null and returning 0, a better way is to make root actually nullable, and pass root.left and root.right directly into it treeSumR:
// notice the question mark here
// v
fun treeSumR(root: TreeNode<Int>?): Int{
if (root == null) return 0
return root.key +
treeSumR(root.left) + // since treeSumR now takes a nullable node, you can directly pass the subtrees in
treeSumR(root.right)
}

Kotlin linked list: How to check if given list is sorted (descending)

I am trying to write a function, which determines if the given linked list is sorted (descending).
Given list 1: 8 -> 5 -> 3 -> null (true)
Given list2: 8 -> 6 -> 10 -> 3 -> null (false)
Given list3: 8 -> 8 -> 3 -> null (true)
Here is my current approach:
class Linkedlist {
var head: Node? = null
data class Node(val value: Int, var next: Node?)
// Current approach
fun isListSorted(): Boolean {
// If list is empty
if (head == null) return true
var curr = head
while(curr != null) {
curr = curr.next
if (curr?.value!! <= curr?.next?.value!!) return false else return true
}
return true
}
}
And here my main:
fun main() {
val list1 = Linkedlist()
list1.append(8)
list1.append(5)
list1.append(3)
val list2 = Linkedlist()
list2.append(8)
list2.append(6)
list2.append(10)
list2.append(3)
val list3 = Linkedlist()
list3.append(8)
list3.append(8)
list3.append(3)
}
I get a NullPointerException. What am I doing wrong? I appreciate every help!
One of Kotlin's most attractive features is null-safety. You don't get NullPointerExceptions unless you use the !! operator. The !! operator should only be used when you have checked your code and you logically know that at that point in code, the parameter cannot be null, but the logic to figure that out is too much for the compiler.
You use the !! operator in a place where the value of curr very well can be null. You set curr = curr.next, and next will be null at the tail of your list, so curr will be null when you use the !! operator on it.
This line of code wouldn't make sense anyway, because you return from both branches of your if/else here, so you cannot possibly ever check more than one node of your list.
A possible way to do this:
fun isListSorted(): Boolean {
var curr = head ?: return true
while(true) {
val next = curr.next ?: return true
if (curr.value < next.value)
return false
curr = next
}
}

Tree from balanced parenthesis

I have to find height of tree and find protection number (or just to generate a tree) from balanced parentheses.
For example:
()()()() creates tree like a list with height 3.
I have no idea how to convert parentheses to tree. I found some 'answers':
http://www.cs.utsa.edu/~wagner/knuth/fasc4a.pdf (second page contains all examples for tree with 4 nodes)
paragraph - Binary Trees, Forests, Non-Crossing Pairs :
https://sahandsaba.com/interview-question-generating-all-balanced-parentheses.html
However, I still don't know how to create a tree from such defined parentheses. I have some impression that in Knuth, authors treat it as something obvious.
Do I miss something or it's not that simple?
Is it necessary to create a forest and then a binary tree?
A pair of parentheses represents a node. What appears within those parentheses represents its left child's subtree (according to the same rules). What appears at the right of those parentheses represents the node's right child's subtree (again, according to the same rules).
The conversion of this encoding into a binary tree can be done recursively like this:
function makeBinaryTree(input):
i = 0 # character index in input
function recur():
if i >= input.length or input[i] == ")":
i = i + 1
return NIL
i = i + 1
node = new Node
node.left = recur()
if i >= input.length or input[i] == ")":
i = i + 1
return node
node.right = recur()
return node
return recur()
Here is an implementation in JavaScript that performs the conversion for each of those 4-noded trees, and pretty prints the resulting trees:
function makeBinaryTree(input) {
let i = 0; // character index in input
return recur();
function recur() {
if (i >= input.length || input[i++] === ")") return null;
let node = { left: recur(), right: null };
if (i >= input.length || input[i] === ")") {
i++;
return node;
}
node.right = recur();
return node;
}
}
// Helper function to pretty print a tree
const disc = "\u2B24";
function treeAsLines(node) {
let left = [""], right = [""];
if (node.left) left = treeAsLines(node.left);
if (node.right) right = treeAsLines(node.right);
while (left.length < right.length) left.push(" ".repeat(left[0].length));
while (left.length > right.length) right.push(" ".repeat(left[0].length));
let topLeft = "", topRight = "";
let i = left[0].indexOf(disc);
if (i > -1) topLeft = "┌".padEnd(left[0].length-i+1, "─");
i = right[0].indexOf(disc);
if (i > -1) topRight = "┐".padStart(i+2, "─");
return [topLeft.padStart(left[0].length+1) + disc + topRight.padEnd(right[0].length+1)]
.concat(left.map((line, i) => line + " " + right[i]));
}
// The trees as listed in Table 1 of http://www.cs.utsa.edu/~wagner/knuth/fasc4a.pdf
let inputs = [
"()()()()",
"()()(())",
"()(())()",
"()(()())",
"()((()))",
"(())()()",
"(())(())",
"(()())()",
"(()()())",
"(()(()))",
"((()))()",
"((())())",
"((()()))",
"(((())))"
];
for (let input of inputs) {
let tree = makeBinaryTree(input);
console.log(input);
console.log(treeAsLines(tree).join("\n"));
}
If I understood Knuth correctly, the representation works as the following: A pair of matching parentheses represents a node, e.g. () = A. Two consecutive pairs of matching parentheses means that the second node is the right child of the first one, e.g. ()() = A -> B. And two pairs of embedded parentheses means the inside node is the left child of the outside node, i.e. (()) = B <- A. Therefore, ()()()() = A -> B -> C -> D.
A possible algorithm to convert parentheses to binary tree would be:
convert(parentheses):
if parentheses is empty:
return Nil
root = Node()
left_start = 1
left_end = Nil
open = 0
for p = 0 to |parentheses|-1:
if parentheses[p] == '(':
open += 1
else
open -= 1
if open == 0:
left_end = p
break
root.left = convert(parentheses[left_start:left_end] or empty if index out of bound)
root.right = convert(parentheses[left_end+1:] or empty if index out of bound)
return root
It works by converting parentheses (L)R in the binary tree L <- A -> R recursively.

Maximum element in a tree

I have the following ADT implementation in Scala.
How to find the maximum element in the tree? Can I introduce some helper function, and if yes, then how?
abstract class MySet {
def max: Int
def contains(tweet: Tweet): Boolean = false
}
class Empty extends MySet {
def max: throw new NoSuchElementExeption("max called on empty tree")
def contains(x: Int): Boolean =
if (x < elem) left.contains(x)
else if (elem < x) right.contains(x)
else true
}
class Node(elem: Int, left: MySet, right: MySet) extends Set {
def max: { ... }
def contains(x: Int): Boolean =
if (x < elem) left.contains(x)
else if (elem < x) right.contains(x)
else true
}
I found a solution in Haskell which feels quite intuitive can I convert it to Scala somehow?
data Tree a = Nil | Node a (Tree a) (Tree a)
maxElement Nil = error "maxElement called on empty tree"
maxElement (Node x Nil Nil) = x
maxElement (Node x Nil r) = max x (maxElement r)
maxElement (Node x l Nil) = max x (maxElement l)
maxElement (Node x l r) = maximum [x, maxElement l, maxElement r]
Update
I am not interested in copying the Haskell code in Scala instead I think Haskell version is more intuitive but because of this keyword and other stuff in Object oriented language. How can I write the equivalent code in object oriented style without pattern matching?
Your tree is heterogeneous, which means that each node can be either a full node with a value, or an empty leaf. Hence you need to distinguish which is which, otherwise you can call max on an empty node. There are many ways:
Classic OOP:
abstract class MySet {
def isEmpty: Boolean
...
}
class Empty extends MySet {
def isEmpty = true
...
}
class Node(...) extends MySet {
def isEmpty = false
...
}
So you do something like this:
var maxElem = elem
if(!left.isEmpty)
maxElem = maxElem.max(left.max)
end
if(!right.isEmpty)
maxElem = maxElem.max(right.max)
end
Since JVM has class information at runtime you can skip the definition of isEmpty:
var maxElem = elem
if(left.isInstanceOf[Node])
maxElem = maxElem.max(left.asInstanceOf[Node].max)
end
if(left.isInstanceOf[Node])
maxElem = maxElem.max(right.asInstanceOf[Node].max)
end
(asInstanceOf is not required if you defined max in MySet, but this pattern covers the case when you didn't)
Well, Scala has a syntactic sugar for the latter, and not surprisingly it's the pattern matching:
var maxElem = elem
left match {
case node: Node =>
maxElem = maxElem.max(node.max)
case _ =>
}
right match {
case node: Node =>
maxElem = maxElem.max(node.max)
case _ =>
}
maxElem
You can take it slightly further and write something like this:
def max = (left, right) match {
case (_: Empty, _: Empty) => elem
case (_: Empty, node: Node) => elem.max(node.max)
case (node: Node, _: Empty) => elem.max(node.max)
case (leftNode: Node, rightNode: Node) =>
elem.max(leftNode.max).max(rightNode.max)
}
If you don't want to use pattern matching, you will need to implement an isEmpty operation or its equivalent, to avoid calling max on an empty set.
The important thing is how the tree is organized. Based on the implementation of contains, it looks like you have an ordered tree (a "binary search tree") where every element in the left part is less than or equal to every element in the right part. If that's the case, your problem is fairly simple. Either the right sub tree is empty and the current element is the max, or the max element of the tree is the max of the right sub tree. That should be a simple recursive implementation with nothing fancy required.
Full disclosure, still learning Scala myself, but here is two versions I came up with (which the pattern match looks like a fair translation of the Haskell code)
sealed trait Tree {
def max: Int
def maxMatch: Int
}
case object EmptyTree extends Tree {
def max = 0
def maxMatch = 0
}
case class Node(data:Int,
left:Tree = EmptyTree,
right:Tree = EmptyTree) extends Tree {
def max:Int = {
data
.max(left.max)
.max(right.max)
}
def maxMatch: Int = {
this match {
case Node(x,EmptyTree,EmptyTree) => x
case Node(x,l:Node,EmptyTree) => x max l.maxMatch
case Node(x,EmptyTree,r:Node) => x max r.maxMatch
case Node(x,l:Node,r:Node) => x max (l.maxMatch max r.maxMatch)
}
}
}
Tests (all passing)
val simpleNode = Node(3)
assert(simpleNode.max == 3)
assert(simpleNode.maxMatch == 3)
val leftLeaf = Node(1, Node(5))
assert(leftLeaf.max == 5)
assert(leftLeaf.maxMatch == 5)
val leftLeafMaxRoot = Node(5,
EmptyTree, Node(2))
assert(leftLeafMaxRoot.max == 5)
assert(leftLeafMaxRoot.maxMatch == 5)
val nestedRightTree = Node(1,
EmptyTree,
Node(2,
EmptyTree, Node(3)))
assert(nestedRightTree.max == 3)
assert(nestedRightTree.maxMatch == 3)
val partialFullTree = Node(1,
Node(2,
Node(4)),
Node(3,
Node(6, Node(7))))
assert(partialFullTree.max == 7)
assert(partialFullTree.maxMatch == 7)

Find Lowest Common Ancestor BST when one or both node(s) doesnt exist

We can easily use the code to find LCA in Binary Search Tree:-
public static Node FindLCA(Node root, Node a, Node b)
{
if (root == null)
return null;
if (root.IData == a.IData || root.IData == b.IData)
return root;
if (root.RightChild != null && (root.RightChild.IData == a || root.RightChild.IData == b))
return root;
if (root.LeftChild != null && (root.LeftChild.IData == a || root.LeftChild.IData == b))
return root;
if (root.IData > a.IData && root.IData > b.IData)
return FindLCA(root.LeftChild, a, b);
if (root.IData < a.IData && root.IData < b.IData)
return FindLCA(root.RightChild, a, b);
else
return root;
}
Was wondering how to handle in case one of the nodes doesn't exist? One easy possible option could be, find if the nodes exist in the BST - this can be done in O(LogN) time and then if necessary call FindLCA? Any other options without first finding if keys exist or not?
EDIT
I realized that I was missing some more conditions earlier, added them and also based on vvijay's answer below.
20
8 22
4 12
10 14
Questions:
But now it fails to find LCA for 8 , 22 and says 22 instead of 20.
Will the LCA(8, 12) be 8 or 20 - I think it should be 8 based on wiki's def of LCA (viz. where we allow a node to be a descendant of itself).
Any thoughts suggestions.?
I think you can separate out the bad cases.
if (root == null) return null;
if (root.Idata == a.Idata || root.Idata == b.Idata) return root;
or just change the return null to return root in your code. So null return value would mean you don't have atleast one of the query nodes in the tree.

Resources