Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semester project: corpus based synthesis #220

Open
wants to merge 79 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
18c2335
initial clean state
jmuth Mar 14, 2016
3ab5823
installation instruction for intelliJ
jmuth Mar 14, 2016
98d4f54
spell correction
jmuth Mar 14, 2016
e9ea369
delete compile of smt-lib and bonsai in doc
jmuth Mar 15, 2016
fb9a35c
lots of println to understand
jmuth Mar 23, 2016
a6d418b
comparison phase squeletton
jmuth Mar 23, 2016
24c3a1a
installation doc sbt wizard
jmuth Mar 23, 2016
d47b34f
fetFunDef function
jmuth Mar 23, 2016
9df3aad
create report directly in ComparisonPhase
jmuth Mar 24, 2016
ad44cb6
correctly extract an other program to compare it
jmuth Mar 30, 2016
55a31b5
add a BinaryTree2.scala exactly same as BinaryTree.scala in order to …
jmuth Mar 30, 2016
48dcf91
some debug log
jmuth Apr 2, 2016
29d4192
comparison works through ExprOps.normalize
jmuth Apr 5, 2016
736d9fc
refine the repporter and the ComparisonBase class, prepare body to re…
jmuth Apr 14, 2016
4a51056
try to separate pattern and value matching, problem with CaseClass id…
jmuth Apr 21, 2016
e11d0b7
move comparison by list in ComparatorByList in order to create new co…
jmuth Apr 25, 2016
9e174ba
initiate comparator by tree and try to set a comparator for class
jmuth Apr 26, 2016
8af14f2
compareClassDef but now... compare Type
jmuth Apr 28, 2016
f5885ac
try to set two proper method: by list and by recursion in tree
jmuth May 2, 2016
d6d10c3
complete all possible Case for treeToList function
jmuth May 2, 2016
8625371
more flexible Phase, to add different comparator. Comparator trait. B…
jmuth May 4, 2016
b61bca6
getChildren function, which will help to traverse tree
jmuth May 5, 2016
81ce224
all brand new TRAVERSE function, allowing to deal easily with tree
jmuth May 6, 2016
cc51959
use Utils function in program
jmuth May 6, 2016
a370fa3
similarClassTree function which traverse both tree parrallely to find…
jmuth May 6, 2016
e6a7788
try to recompose the tree
jmuth May 8, 2016
af0a79a
Tree class
jmuth May 12, 2016
3f5123b
traverse two tree parallelely and create a list of all possible simil…
jmuth May 12, 2016
3cb5ac9
correction of a bug in ClassTree, now working for two identical progr…
jmuth May 13, 2016
4beb597
--debug option
jmuth May 18, 2016
e0a098e
refine the ClassTree to extract not only the biggest tree, but all th…
jmuth May 19, 2016
d6cf899
compute score with Geometric Means. Begin with scoreMatchExpr
jmuth May 19, 2016
c96d8f4
begin new comparator handeling holes
jmuth Jun 2, 2016
3873369
comparator ScoreTreeWithHoles, all function to traverse and compute s…
jmuth Jun 5, 2016
a70ae8e
new branch ScoreTree and clean project
jmuth Jun 6, 2016
c2dce29
add place for extra information in report
jmuth Jun 6, 2016
a7e4df1
extra info in render table
jmuth Jun 6, 2016
21bf24c
size of function in report
jmuth Jun 6, 2016
9faaf79
no news
jmuth Jun 6, 2016
35a3664
minor typo in doc
jmuth Jun 7, 2016
3df1716
fix merge conflict
jmuth Jun 8, 2016
dc9218a
corrections due to changed in ExprOps.normalizeStructure and to Share…
jmuth Jun 8, 2016
3481965
clear some println debug messages
jmuth Jun 8, 2016
8aa1250
fix the new way to produce report after update master
jmuth Jun 8, 2016
56dd58e
clean some comments put during dev phase
jmuth Jun 8, 2016
67ec9ac
clean import in main
jmuth Jun 8, 2016
874182b
Merge remote-tracking branch 'upstream/master'
jmuth Jun 8, 2016
f40d4dd
refact with better name and check comments
jmuth Jun 8, 2016
99663a7
refact with better name and check comments part 2
jmuth Jun 8, 2016
47f0543
create Completor object
jmuth Jun 8, 2016
00d23d5
implement Completor who find a suggestion for a Hole.. code compile b…
jmuth Jun 8, 2016
3613b5a
autocompletion compile and run, but do not find the pair
jmuth Jun 9, 2016
770d168
autocompletion works, now testing to fill the hole, safety backup
jmuth Jun 9, 2016
024de48
finish to fill the hole and print the result in Reporter
jmuth Jun 9, 2016
63851ec
prettier Report and comments in Comparator
jmuth Jun 9, 2016
0d68fd9
back up before trying to reuse DirectScore method in Completor
jmuth Jun 9, 2016
e2dc98d
Comparator is entirely based on ComparisonDirectScore to compute score
jmuth Jun 9, 2016
444f176
clean useless idea file, add precision in documentation
jmuth Jun 9, 2016
1d9de49
Merge remote-tracking branch 'upstream/master'
jmuth Jun 9, 2016
71644f2
clean dummy changes made in wrong files
jmuth Jun 9, 2016
18a80e1
delete test.sc, add comment in Comparator
jmuth Jun 9, 2016
64ebde2
Finally a better way to score tree
jmuth Jun 9, 2016
f4df253
backup before trying a last refact
jmuth Jun 9, 2016
fe0ce67
refact (Expr, Expr, Double) to Value case class for clarity
jmuth Jun 9, 2016
c6ae3d3
finish to merge DirectScore and Comparator
jmuth Jun 9, 2016
c333f04
rename classes and delete old files
jmuth Jun 10, 2016
7ecfbbe
Merge remote-tracking branch 'upstream/master'
jmuth Jun 10, 2016
ce519d6
corpus modifications
jmuth Jun 12, 2016
094dcb5
refact to camelcase
jmuth Jun 14, 2016
101df6a
implicit context and debug option
jmuth Jun 14, 2016
d5de9f3
List.intesect to define number of matching pairs
jmuth Jun 14, 2016
5bd3557
change println to reporter.debug
jmuth Jun 14, 2016
6349eb2
add DebugSectionComparison
jmuth Jun 14, 2016
0b6cae7
indentation
jmuth Jun 14, 2016
9544be2
remove useless import
jmuth Jun 14, 2016
5ee5af2
myTree renamed FuncTree
jmuth Jun 14, 2016
2ad2671
use pre-existing GenTreeOps.preMap to fill the hole
jmuth Jun 14, 2016
7e0069c
use GenTreeOps.fold to collect Expr and Class
jmuth Jun 14, 2016
eeaa8c5
comment why no use of GenTreeOps.collect
jmuth Jun 14, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/main/scala/leon/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ object Main {
invariant.engine.InferInvariantsPhase,
laziness.LazinessEliminationPhase,
genc.GenerateCPhase,
genc.CFileOutputPhase
genc.CFileOutputPhase,
comparison.ComparisonPhase
)
}

Expand Down Expand Up @@ -59,9 +60,11 @@ object Main {
val optInferInv = LeonFlagOptionDef("inferInv", "Infer invariants from (instrumented) the code", false)
val optLazyEval = LeonFlagOptionDef("lazy", "Handles programs that may use the 'lazy' construct", false)
val optGenc = LeonFlagOptionDef("genc", "Generate C code", false)
val optComparison = LeonFlagOptionDef("compare", "Compare the targeted program to the Leon exemple suit", false)


override val definedOptions: Set[LeonOptionDef[Any]] =
Set(optTermination, optRepair, optSynthesis, optIsabelle, optNoop, optHelp, optEval, optVerify, optInstrument, optInferInv, optLazyEval, optGenc)
Set(optTermination, optRepair, optSynthesis, optIsabelle, optNoop, optHelp, optEval, optVerify, optInstrument, optInferInv, optLazyEval, optGenc, optComparison)
}

lazy val allOptions: Set[LeonOptionDef[Any]] = allComponents.flatMap(_.definedOptions)
Expand Down Expand Up @@ -177,6 +180,8 @@ object Main {
val instrumentF = ctx.findOptionOrDefault(optInstrument)
val lazyevalF = ctx.findOptionOrDefault(optLazyEval)
val analysisF = verifyF && terminationF
val comparisonF = ctx.findOptionOrDefault(optComparison)

// Check consistency in options

if (helpF) {
Expand Down Expand Up @@ -206,6 +211,7 @@ object Main {
else if (instrumentF) InstrumentationPhase andThen FileOutputPhase
else if (gencF) GenerateCPhase andThen CFileOutputPhase
else if (lazyevalF) LazinessEliminationPhase
else if (comparisonF) comparison.ComparisonPhase andThen PrintReportPhase
else verification
}

Expand All @@ -217,6 +223,7 @@ object Main {
private var hasFatal = false

def main(args: Array[String]) {

val argsl = args.toList

// Process options
Expand Down
12 changes: 12 additions & 0 deletions src/main/scala/leon/comparison/Comparator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package leon.comparison

import leon.purescala.Expressions.Expr

/**
* Created by joachimmuth on 04.05.16.
*/
trait Comparator {
val name: String
def compare(expr_base: Expr, expr: Expr): (Double, String)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should consistently use camelcase in Scala code


}
63 changes: 63 additions & 0 deletions src/main/scala/leon/comparison/ComparatorClassList.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package leon.comparison

import leon.comparison.Utils._
import leon.purescala.Expressions._

/**
* Created by joachimmuth on 02.05.16.
*
* This method shares similarities with the ComparatorByList.
* We keep the idea of comparing a list of expressions (disregarding their order), but now, instead of comparing
* two expressions (i.e. tree) we will extract the type of each expression.
*
* x match {
* case 1 => 'a'
* case 2 => 'b'
* }
*
* ComparatorByList -> {complete match, leaf(a), leaf(b)}
* ComparatorByListType -> {node(match), leaf(a), leaf(b)}
*
* x match {
* case 1 => 'a'
* case 2 => 'c'
* }
*
* ComparatorByList -> similarity 33%
* ComparatorByListType -> similarity 66%
*/
object ComparatorClassList extends Comparator {
val name = "ClassList"

def compare(expr_corpus: Expr, expr: Expr) = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Camelcase here too perhaps?

val listClassesA = collectClass(expr_corpus)
val listClassesB = collectClass(expr)

val similarExpr: Int = pairsOfSimilarExp(listClassesA, listClassesB)

val score = Utils.matchScore(similarExpr, listClassesA.size, listClassesB.size)

if (score > 0.0 && ComparisonPhase.debug){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have infrastructure to debug in Leon, you would have to pass an implicit LeonContext and use reporter.debug

Copy link
Author

@jmuth jmuth Jun 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please look at my commits 101df6a and 5bd3557 and 6349eb2

I'm not sure if I use correctly the Leon debug especially:

  • Is it correct to pass implicit context to function "combinationOfFunDef" ? (the function that call the comparators)
  • Is it okay to declare the implicite DebugSection in each comparator or do I must declare it in the main phase?

println("-----------")
println("COMPARATOR " + name)
println("Expressions: ", expr, expr_corpus)
println("List of classes: ", listClassesB, listClassesA)
println("-----------")
}

(score, "")
}


def pairsOfSimilarExp(listExpr_corpus: List[Class[_ <: Expr]], listExpr: List[Class[_ <: Expr]]): Int = {
def helper(listExpr_corpus: List[Class[_ <: Expr]], listExpr: List[Class[_ <: Expr]], acc: Int): Int =
listExpr match {
case Nil => acc
case x::xs if listExpr_corpus.contains(x) => helper(listExpr_corpus diff List(x), xs, acc + 1)
case x::xs => helper(listExpr_corpus, xs, acc)
}

helper(listExpr_corpus, listExpr, 0)
}

}
180 changes: 180 additions & 0 deletions src/main/scala/leon/comparison/ComparatorClassTree.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package leon.comparison

import leon.comparison.Utils._
import leon.purescala.Expressions._


/**
* Created by joachimmuth on 12.05.16.
*
* Go through both trees in parallel and compare each expression based on its class. Try to find the biggest
* common tree.
*
* Procedure:
* - Find all possible pair of roots. Then consider all children of both roots, and check which are
* similar.
* - Consider all possible combinations of children and repeat the same operation on them.
* - Pick the biggest tree in the list of all possible similar tree
* - Remove the tree overlapping the one chosen, and search if it exists an other common tree. Repeat.
* - End with all common and exclusive common tree shared by trees A and B
*
* The MatchScore is calculated with the size of the common tree, compared with the sizes of trees A and B.
*/
object ComparatorClassTree extends Comparator{
val name: String = "ClassTree"


def compare(expr_corpus: Expr, expr: Expr) = {
val roots = possibleRoots(expr_corpus, expr)

val trees = roots.flatMap(possibleTrees(_))
val exclusives = exclusivesTrees(trees)
val sum = exclusives.foldLeft(0)( (acc, tree) => acc + tree.size)

val listClassesA = collectClass(expr_corpus)
val listClassesB = collectClass(expr)

val score = matchScore(sum, listClassesA.size, listClassesB.size)

if (score > 0.0 && ComparisonPhase.debug){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug with LeonContext here?

println("---------------------")
println("COMPARATOR " + name)
println("Expressions: ", expr_corpus, expr)
println("Common Tree: ", exclusives)
println("---------------------")
}

(score, "")
}

/**
* Extract all non-overlapping trees, in size order
* @param trees
* @return
*/
def exclusivesTrees(trees: List[myTree[(Expr, Expr)]]): List[myTree[(Expr, Expr)]] = trees match {
case Nil => Nil
case x :: xs =>
val biggest = trees.sortBy(-_.size).head
val rest = trees.filter(tree => flatList(tree).intersect( flatList(biggest) ).isEmpty)
List(biggest) ++ exclusivesTrees(rest)
}

def flatList(tree: myTree[(Expr, Expr)]): List[Expr] = tree.toList.flatMap(p => List(p._1, p._2))

/**
* list of all similar pair of expressions, based on classes.
*
* @param expr_corpus
* @param expr
* @return
*/
def possibleRoots(expr_corpus: Expr, expr: Expr): List[(Expr, Expr)] = {
val expressionsA = collectExpr(expr_corpus)
val expressionsB = collectExpr(expr)

val pairOfPossibleRoots = for {
exprA <- expressionsA
exprB <- expressionsB
if areSimilar(exprA.getClass, exprB.getClass)
} yield {
(exprA, exprB)
}

pairOfPossibleRoots
}


/**
* With a pair of roots, find all children and find all combination of matching children in order to create a list
* of all possible matching tree. Then recursively call itself on each pair of children.
*
* @param pair of matching root
* @return ether a Leaf or a List of all possible similar trees starting with this pair of roots
*/
def possibleTrees(pair: (Expr, Expr)): List[myTree[(Expr, Expr)]] = {
val exprA = pair._1
val exprB = pair._2
val childrenA = getChildren(exprA)
val childrenB = getChildren(exprB)


val pairOfMatchingChildren = findPairOfMatchingChildren(childrenA, childrenB)
val combinationOfChildren = combineChildren(pairOfMatchingChildren)


if(pairOfMatchingChildren.isEmpty) {
List(myTree(pair, List()))
} else {
combinationOfChildren.foldLeft(List(): List[myTree[(Expr, Expr)]])(
(listOfTree, children) => listOfTree ++ treesWithChildCombination(pair, children.map(p => possibleTrees(p)))
)
}
}

def findPairOfMatchingChildren(childrenA: List[Expr], childrenB: List[Expr]): List[(Expr, Expr)] = {
for{
childA <- childrenA
childB <- childrenB
if areSimilar(childA.getClass, childB.getClass)
} yield {
(childA, childB)
}
}

/** All possible combination of pairs of children, given the condition that one child can only be used once.
*
* IMPROVEMENT: Here, it would be possible to already filter some cases.
* When we do the combination, we try all cases, using one pair of matching, two, three, ... we could only keep the
* ones using maximum of possible children, as we only want the biggest tree.
*
* @param pairs
* @return
*/
def combineChildren(pairs: List[(Expr, Expr)]): List[List[(Expr, Expr)]] = {
combine(pairs).filterNot(p => isSameChildUsedTwice(p)).toList
}

def isSameChildUsedTwice(list: List[(Expr, Expr)]): Boolean = {
list.map(_._1).distinct.size != list.size ||
list.map(_._2).distinct.size != list.size
}

def combine(in: List[(Expr, Expr)]): Seq[List[(Expr, Expr)]] = {
for {
len <- 1 to in.length
combinations <- in combinations len
} yield combinations
}

/**
* As we recursively call the method, children will create list of possibilities, as the root does. All this possible
* combination need to be transformed into a list of complete tree.
*
* Technically, we have a combination of Children that return each a list of possible trees. So the upper-level tree
* (whom root is named pair) can have all possible combination of theses lists as children.
*
* @param pair
* @param listChildren
* @return
*/
def treesWithChildCombination(pair: (Expr, Expr), listChildren: List[List[myTree[(Expr, Expr)]]]): List[myTree[(Expr, Expr)]] = {
def combine(list: List[List[myTree[(Expr, Expr)]]]): List[List[myTree[(Expr, Expr)]]] = list match {
case Nil => List(Nil)
case x :: xs =>
for {
j <- combine(xs)
i <- x
} yield i :: j
}

combine(listChildren).map(children => myTree(pair, children))
}



def areSimilar(getClass: Class[_ <: Expr], getClass1: Class[_ <: Expr]) = {
getClass == getClass1
}

}
Loading