on the simplicity of synthesizing linked data structure ...dkurilov/slides/gpce13slides.pdf · on...

Post on 05-Feb-2018

215 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

On the Simplicity of Synthesizing Linked Data Structure Operations

Darya Kurilova, Carnegie Mellon University Derek Rayside, University of Waterloo

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

1!

Ideal Code Generation Scenario

I want the program to...

...

...

...

*.java  *.exe  *.c  *.js  

...

Magic  Box  2!

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

@SpecField(…)  @Modifies(…)  

...

...

...

3!

*.java  *.class  *.exe  

Proposed Code Generation Scenario

SAT Solver © Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Our Approach •  Given: –  Prior work on code synthesis –  SAT-solver limits

•  Problem: –  Generating code for data structures that require heap

manipulations is believed to be hard •  Our solution: –  Use “divide-and-conquer” and a common pattern

for code generation –  Proof of concept: code generation via systematic

manual procedure

4!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Common Pattern 1   public  return-type method-name(arguments)  {  2         if  (condition1  &&  condition2  &&  ...  &&  conditionN1)  {  3             statement1;  4             statement2;  5               ...  6             statementM1;  7               return  object-of-the-return-type-or-nothing;  8         }  9         ...  10         if  (condition1  &&  condition2  &&  ...  &&  conditionNk)  {  11             statement1;  12             statement2;  13               ...  14             statementMk;  15               return  object-of-the-return-type-or-nothing;  16         }  17   }  

5!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

AVL Trees •  A self-balancing binary search tree •  Difference between height of the left

subtree and of the right subtree is at most 1

4

2

1 3

6

5 7

4

2

1 3

5

5

2

1 4

6

3

This is an AVL tree. This is not an AVL tree. This is an AVL tree.

6!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm

1.  Part I: Programmer’s Actions 2.  Part II: Automatic Actions

7!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part I(Programmer’s Actions)

1.  Define basic data structures. 2.  Write invariants. 3.  Declare and specify methods.

8!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part I(Programmer’s Actions)

1.  Define basic data structures. 2.  Write invariants. 3.  Declare and specify methods.

9!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Basic Data Structures  1   class  Node  {  2         int  value;  3         int  height;  4         Node  left;  5         Node  right;  6         Node  parent;  7   }  

8     class  AVLTree  {  9           Node  root;  10     }  

10!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part I(Programmer’s Actions)

1.  Define basic data structures. 2.  Write invariants. 3.  Declare and specify methods.

11!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Invariants for an AVL Tree 1   @Invariant({  2         //  root  has  no  parents  3         "no  (left  +  right).(this.root)",  4     5         //  acyclic  6         "no  this  in  this.^(left  +  right)",  7     8         //  ordered  9         "all  x  :  this.left.^(left  +  right)  +  this.left  -­‐  null  |  x.value  <  this.value",  10         "all  x  :  this.right.^(left  +  right)  +  this.right  -­‐  null  |  x.value  >  this.value",  11     12         //  height  of  a  leaf  node  is  1  13         "(this.left  =  null  and  this.right  =  null)  =>  this.height  =  1",  14     15         //  height  for  semi-­‐leaf  nodes  16         "(this.left  =  null  and  this.right  !=  null)  =>  this.height  =  this.right.height  +  1",  17         "(this.left  !=  null  and  this.right  =  null)  =>  this.height  =  this.left.height  +  1",  18     19         //  height  for  interior  nodes  20         "(this.left  !=  null  and  this.right  =  null)  =>  this.height  =  this.left.height  +  1",  21         "this.left  !=  null  =>  this.height  >  this.left.height",  22         "this.right  !=  null  =>  this.height  >  this.right.height",  23         "no  null  in  this.(left  +  right)  =>  this.left.height  -­‐  this.right.height  <=  1",    24         "no  null  in  this.(left  +  right)  =>  this.right.height  -­‐  this.left.height  <=  1",    25         "no  null  in  this.(left  +  right)  =>  (this.height  =  this.left.height  +  1)  26                                                                               or  (this.height  =  this.right.height  +  1)"  27   })   12!

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part I(Programmer’s Actions)

1.  Define basic data structures. 2.  Write invariants. 3.  Declare and specify methods.

13!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Methods and Their Specifications 1   @Pure  2   @Returns("x  in  this.values")  3   public  boolean  contains(int  x)  {  4         //  generated  code  goes  here  5   }  6     7   @Modifies("Node.value,  Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  8   @Ensures("x  in  this.values")  9   public  void  insert(int  x)  {  10         //  generated  code  goes  here  11   }  12       13   @Modifies("Node.value,  Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  14   @Ensures("no  x  in  this.values")  15   public  void  delete(int  x)  {  16         //  generated  code  goes  here  17   }    

14!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part II(Automatic Actions)

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specifications based on invariants.

3.  Determine the helper methods’ call order.

15!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part II(Automatic Actions)

1.  Generate helper methods and their specificationsbased on basic data structures definitions.

2.  Generate helper methods and their specifications based on invariants.

3.  Determine the helper methods’ call order.

16!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

swapChildren() Helper Method 1   @Ensures("this.right  =  @old(this.left)  2                     and  this.left  =  @old(this.right)")  3     4   private  void  swapChildren(Node  one)  {  5         Node  temp  =  one.right;  6         one.right  =  one.left;  7         one.left  =  temp;  8   }  

17!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part II(Automatic Actions)

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specificationsbased on invariants.

1)  Analyze invariants. 2)  Generate helper methods’ bodies. 3)  Clean up.

3.  Determine the helper methods’ call order.

18!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Invariant Analysis

19!

1   @Invariant({  2         //  root  has  no  parents  3         "no  (left  +  right).(this.root)",  4     5         //  acyclic  6         "no  this  in  this.^(left  +  right)",  7     8         //  ordered  9         "all  x  :  this.left.^(left  +  right)  +  this.left  -­‐  null  |  x.value  <  this.value",  10         "all  x  :  this.right.^(left  +  right)  +  this.right  -­‐  null  |  x.value  >  this.value",  11     12         //  height  of  a  leaf  node  is  1  13         "(this.left  =  null  and  this.right  =  null)  =>  this.height  =  1",  14     15         //  height  for  semi-­‐leaf  nodes  16         "(this.left  =  null  and  this.right  !=  null)  =>  this.height  =  this.right.height  +  1",  17         "(this.left  !=  null  and  this.right  =  null)  =>  this.height  =  this.left.height  +  1",  18     19         //  height  for  interior  nodes  20         "(this.left  !=  null  and  this.right  =  null)  =>  this.height  =  this.left.height  +  1",  21         "this.left  !=  null  =>  this.height  >  this.left.height",  22         "this.right  !=  null  =>  this.height  >  this.right.height",  23         "no  null  in  this.(left  +  right)  =>  this.left.height  -­‐  this.right.height  <=  1",    24         "no  null  in  this.(left  +  right)  =>  this.right.height  -­‐  this.left.height  <=  1",    25         "no  null  in  this.(left  +  right)  =>  (this.height  =  this.left.height  +  1)  26                                                                               or  (this.height  =  this.right.height  +  1)"  27   })  

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Invariant Analysis Conclusion

20!

•  Invariants that mention the value field are related to ordering.

•  Invariants that mention the height field are related to balancing.

•  Therefore: –  two groups of invariants, –  two main properties, and –  two helper methods.

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Invariant Analysis Results 1   @Pure  2   @Returns("x  in  this.values")  3   public  boolean  contains(int  x)  {  4         @Pure  5         @Returns("x  in  this.values")  6         containsHelper(...);  7   }    8   @Modifies("Node.value,  Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  9   @Ensures("x  in  this.values")  10   public  void  insert(int  x)  {    11         @Modifies("Node.value,  Node.left,  Node.right,  Node.parent,  this.root")  12         @Ensures("x  in  this.values")  13         orderingInsertHelper(...);  14           15         @Modifies("Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  16         balancingInsertHelper(...);  17   }    18   @Modifies("Node.value,  Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  19   @Ensures("no  x  in  this.values")  20   public  void  delete(int  x)  {    21         @Modifies("Node.value,  Node.left,  Node.right,  Node.parent,  this.root")  22         @Ensures("no  x  in  this.values")  23         orderingDeleteHelper(...);  24           25         @Modifies("Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  26         balancingDeleteHelper(...);  27   }  

21!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part II(Automatic Actions)

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specificationsbased on invariants.

1)  Analyze invariants. 2)  Generate helper methods’ bodies. 3)  Clean up.

3.  Determine the helper methods’ call order.

22!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Common Pattern 1   public  return-type method-name(arguments)  {  2         if  (condition1  &&  condition2  &&  ...  &&  conditionN1)  {  3             statement1;  4             statement2;  5               ...  6             statementM1;  7               return  object-of-the-return-type-or-nothing;  8         }  9         ...  10         if  (condition1  &&  condition2  &&  ...  &&  conditionNk)  {  11             statement1;  12             statement2;  13               ...  14             statementMk;  15               return  object-of-the-return-type-or-nothing;  16         }  17   }  

23!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Pattern Fillers •  Conditions: –  Mathematical comparisons using ==, !=, <, <=, >, >=. –  Node fields, null, and numeric values from

specifications. •  Executable statements: –  a recursive call to the method itself, –  a call to another method, –  an assignment to an existing variable, –  a variable declaration, –  an assignment to the introduced variable.

24!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Generated  containsHelper()  1   public  boolean  containsHelper(int  x,  Node  node)  {  2         if  (node  !=  null  &&  node.left  ==  null  &&  node.right  ==  null  &&  node.value  >  x)  {  3               return  false;  4         }  5         if  (node  !=  null  &&  node.left  ==  null  &&  node.right  ==  null  &&  node.value  <  x)  {  6               return  false;  7         }  8         if  (node  !=  null  &&  node.left  ==  null  &&  node.right  ==  null  &&  node.value  ==  x)  {  9               return  true;  10         }  11         if  (node  !=  null  &&  node.left  ==  null  &&  node.right  !=  null  &&  node.value  >  x)  {  12               return  false;  13         }  14         if  (node  !=  null  &&  node.left  ==  null  &&  node.right  !=  null  &&  node.value  <  x)  {  15               return  containsHelper(x,  node.right);  16         }  17     18         ...  //  42  MORE  IF-­‐BLOCKS  19     20         if  (node  ==  null  &&  node.left  !=  null  &&  node.right  !=  null  &&  node.value  ==  x)  {  21               return  false;  22         }  23   }   25!

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part II(Automatic Actions)

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specificationsbased on invariants.

1)  Analyze invariants. 2)  Generate helper methods’ bodies. 3)  Clean up.

3.  Determine the helper methods’ call order.

26!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

containsHelper() After Clean Up 1   public  boolean  containsHelper(int  x,  Node  node)  {  2         if  (node  ==  null)  {  3               return  false;  4         }    5         if  (node.value  ==  x)  {  6               return  true;  7         }  8         if  (node.value  <  x)  {  9               if  (node.right  !=  null)  {  10                     return  containsHelper(x,  node.right);  11               }  else  {  12                     return  false;  13               }  14         }  15         if  (node.value  >  x)  {  16               if  (node.left  !=  null)  {  17                     return  containsHelper(x,  node.left);  18               }  else  {  19                     return  false;  20               }  21         }  22   }  

27!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm: Part II(Automatic Actions)

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specifications based on invariants.

1)  Analyze invariants. 2)  Generate helper methods’ bodies. 3)  Clean up.

3.  Determine the helper methods’ call order.

28!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Helper Methods’ Call Order 1   @Pure  2   @Returns("x  in  this.values")  3   public  boolean  contains(int  x)  {  4         @Pure  5         @Returns("x  in  this.values")  6         containsHelper(...);  7   }  8   @Modifies("Node.value,  Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  9   @Ensures("x  in  this.values")  10   public  void  insert(int  x)  {    11         @Modifies("Node.value,  Node.left,  Node.right,  Node.parent,  this.root")  12         @Ensures("x  in  this.values")  13         orderingInsertHelper(...);  14           15         @Modifies("Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  16         balancingInsertHelper(...);  17   }  18   @Modifies("Node.value,  Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  19   @Ensures("no  x  in  this.values")  20   public  void  delete(int  x)  {    21         @Modifies("Node.value,  Node.left,  Node.right,  Node.parent,  this.root")  22         @Ensures("no  x  in  this.values")  23         orderingDeleteHelper(...);  24           25         @Modifies("Node.height,  Node.left,  Node.right,  Node.parent,  this.root")  26         balancingDeleteHelper(...);  27   }   29!

© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm Summary Part I: Programmer’s Actions

1.  Define basic data structures. 2.  Write invariants. 3.  Declare and specify methods.

Part II: Automatic Actions

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specifications based on invariants. 1)  Analyze the invariants. 2)  Generate helper methods’

bodies. 3)  Clean up.

3.  Determine the helper methods’ call order.

30!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Code Generation Algorithm Summary Part I: Programmer’s Actions

1.  Define basic data structures. 2.  Write invariants. 3.  Declare and specify methods.

Part II: Automatic Actions

1.  Generate helper methods and their specifications based on basic data structures definitions.

2.  Generate helper methods and their specifications based on invariants. 1)  Analyze the invariants. 2)  Generate helper methods’

bodies. 3)  Clean up.

3.  Determine the helper methods’ call order.

31!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Search Space Analysis •  Usual case: –  6 statements + 2 levels of dereferencing = 230

– Can be handled by modern SAT solvers •  Exception: tree re-balance helper method –  12 statements + 3 levels of dereferencing = 284

– Mitigated by “smart” order in which types of statements are introduced

32!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

Conclusion •  Use “divide-and-conquer” and the common

pattern •  Search spaces manageable by current SAT-

solvers •  Problem might be not as difficult as previously

imagined •  Approach is applicable to recursive linked data

structures; possibly to others

33!© Darya Kurilova 2013!

[GPCE‘13, Indianapolis, IN, USA]!

top related