-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/HazyResearch/ddlog into d…
…dlog-query
- Loading branch information
Showing
21 changed files
with
1,108 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
src/main/scala/org/deepdive/ddlog/DeepDiveLogDesugarRewriter.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.deepdive.ddlog | ||
|
||
object DeepDiveLogDesugarRewriter { | ||
|
||
// Rewrite function call rules whose output coincides with normal rules. | ||
def desugarUnionsImpliedByFunctionCallRules(program: DeepDiveLog.Program) = { | ||
def indexByFirst[a,b](pairs: Seq[(a,b)]): Map[a,List[b]] = | ||
pairs groupBy { _._1 } mapValues { _ map (_._2) toList } | ||
|
||
val schemaByName = indexByFirst(program collect { | ||
case decl: SchemaDeclaration => decl.a.name -> decl | ||
}) mapValues (_ head) | ||
val rulesWithIndexByName = indexByFirst(program.zipWithIndex collect { | ||
case (fncall: FunctionCallRule, i) => fncall.output -> (fncall, i) | ||
case (rule : ExtractionRule , i) => rule.headName -> (rule , i) | ||
}) | ||
val relationNamesUsedInProgram = program collect { | ||
case decl: SchemaDeclaration => decl.a.name | ||
case fncall: FunctionCallRule => fncall.output | ||
case rule: ExtractionRule => rule.headName | ||
} toSet | ||
|
||
// find names that have multiple function calls or mixed type rules | ||
val relationsToDesugar = rulesWithIndexByName flatMap { | ||
case (name, allRules) => | ||
val (fncalls, rules) = allRules map {_._1} partition {_.isInstanceOf[FunctionCallRule]} | ||
if ((fncalls size) > 1 || ((fncalls size) > 0 && (rules size) > 0)) { | ||
Some(name) | ||
} else None | ||
} | ||
val rulesToRewrite = relationsToDesugar flatMap rulesWithIndexByName map { | ||
_._1} filter {_.isInstanceOf[FunctionCallRule]} toList | ||
|
||
// determine a separator that does not create name clashes with existing heads for each relation to rewrite | ||
val prefixForRelation: Map[String, String] = relationsToDesugar map { name => | ||
name -> ( | ||
Stream.from(1) map { n => s"${name}${"_" * n}" | ||
} dropWhile { prefix => | ||
relationNamesUsedInProgram exists {_ startsWith prefix} | ||
} head | ||
) | ||
} toMap | ||
|
||
// how to make names unique | ||
def makeUnique(name: String, ordLocal: Int, ordGlobal: Int): String = { | ||
s"${prefixForRelation(name)}${ordLocal}" | ||
} | ||
|
||
// plan the rewrite | ||
val rewritePlan : Map[Statement, List[Statement]] = | ||
program collect { | ||
// only function call rule needs to be rewritten | ||
case fncall: FunctionCallRule if rulesToRewrite contains fncall => | ||
val relationName: String = fncall.output | ||
val rulesForTheRelationToRewriteOrdered = rulesWithIndexByName(relationName | ||
) sortBy {_._2} filter {_._1.isInstanceOf[FunctionCallRule]} | ||
val orderAmongRulesToRewrite = rulesForTheRelationToRewriteOrdered map {_._1} indexOf(fncall) | ||
val orderInProgram = rulesForTheRelationToRewriteOrdered(orderAmongRulesToRewrite)._2 | ||
val nameUnique: String = makeUnique(relationName, orderAmongRulesToRewrite, orderInProgram) | ||
val schema = schemaByName(relationName) | ||
fncall -> List( | ||
schema.copy(a = schema.a.copy(name = nameUnique)), | ||
fncall.copy(output = nameUnique), | ||
ExtractionRule( | ||
headName = relationName, | ||
q = ConjunctiveQuery( | ||
headTerms = schema.a.terms map VarExpr, | ||
bodies = List(List(BodyAtom(name = nameUnique, terms = schema.a.terms map VarPattern))) | ||
) | ||
) | ||
) | ||
// TODO add union after the last or first or somewhere | ||
} toMap | ||
|
||
// apply rewrite plan | ||
program flatMap { case rule => rewritePlan getOrElse(rule, List(rule)) } | ||
} | ||
|
||
|
||
def derive(program: DeepDiveLog.Program): DeepDiveLog.Program = { | ||
(List( | ||
desugarUnionsImpliedByFunctionCallRules(_) | ||
) reduce (_.compose(_)) | ||
)(program) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.