Created
July 24, 2017 17:35
-
-
Save Groostav/01fadaf725b995531b69b799ba91530c to your computer and use it in GitHub Desktop.
initial rewrite of the rewriting walker
This file contains hidden or 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
package com.empowerops.problem_definition.babel | |
import com.empowerops.problem_definition.parser.BabelParser.* | |
import com.empowerops.problem_definition.parser.BabelParserBaseListener | |
import org.antlr.v4.runtime.CommonToken | |
import org.antlr.v4.runtime.misc.NotNull | |
import org.antlr.v4.runtime.tree.ParseTree | |
import org.antlr.v4.runtime.tree.TerminalNode | |
import org.antlr.v4.runtime.tree.TerminalNodeImpl | |
import com.empowerops.problem_definition.parser.BabelLexer.FLOAT | |
/** | |
* Rewrites boolean expressions into scalar expressions as per constraint formulation. | |
* | |
* This class changes a boolean expression into an expression that returns a scalar value | |
* according to the simple scheme: | |
* - negative values are _true_ | |
* - zero is _true_ | |
* - positive values are _false_ | |
* | |
* This is how many seminal works on optimization traditionally treat constraints, and it has | |
* the added advantage of keeping meta-data around about failed constraints, such that we | |
* can determine which values fail constraints worse than others. | |
* | |
* For example: | |
* ``` | |
* x1 + x2 > x3 | |
* ``` | |
* | |
* will be rewritten as | |
* | |
* ``` | |
* x3 - (x1 + x2) < 0 //I think? | |
* ``` | |
* | |
* | |
* Created by Justin Casol on 1/19/2015 | |
* Updated by Geoff Groos on 07/24/2017 | |
*/ | |
class BooleanRewritingWalker() : BabelParserBaseListener() { | |
var isBooleanExpression = false | |
private set | |
override fun exitExpr(ctx: ExprContext) { | |
if (ctx.children == null) { throw IllegalArgumentException() } | |
val operation = ctx.children.filter { isOperation(it) }.firstOrNull() | |
when (operation) { | |
is EqContext -> throw UnsupportedOperationException("OASIS does not support equality constraints") | |
is LteqContext -> { | |
swapInequalityWithSubtraction(ctx, "AST_REWRITE<=") | |
isBooleanExpression = true | |
} | |
is GteqContext -> { | |
swapLiteralChildren(ctx) | |
swapInequalityWithSubtraction(ctx, "AST_REWRITE>=") | |
isBooleanExpression = true | |
} | |
is LtContext -> { | |
swapInequalityWithSubtraction(ctx, "AST_REWRITE<") | |
addEpsilonAdditionASTLayer(ctx) | |
isBooleanExpression = true | |
} | |
is GtContext -> { | |
swapLiteralChildren(ctx) | |
swapInequalityWithSubtraction(ctx, "AST_REWRITE<") | |
addEpsilonAdditionASTLayer(ctx) | |
isBooleanExpression = true | |
} | |
else -> isBooleanExpression = false | |
} | |
} | |
private fun addEpsilonAdditionASTLayer(ctx: ExprContext) { | |
val parent = ctx.getParent() | |
val superExpression = ExprContext(parent, 20) | |
parent.children.add(parent.children.indexOf(ctx), superExpression) | |
parent.children.remove(ctx) | |
superExpression.addChild(ctx) | |
ctx.parent = superExpression | |
val plusContext = PlusContext(superExpression, 20) | |
val terminalNode = TerminalNodeImpl(CommonToken(20, "ADDFOREPSILON")) | |
plusContext.addChild(terminalNode) | |
superExpression.addChild(plusContext) | |
addValue(superExpression, Epsilon) | |
} | |
private fun addValue(superExpression: ExprContext, value: Double) { | |
val valueExpr = ExprContext(superExpression, 1) | |
val valueContext = LiteralContext(valueExpr, 1) | |
val valueTerminalNode = TerminalNodeImpl(CommonToken(FLOAT, java.lang.Double.toString(value))) | |
superExpression.addChild(valueExpr) | |
valueExpr.addChild(valueContext) | |
valueContext.addChild(valueTerminalNode) | |
} | |
private fun swapInequalityWithSubtraction(ctx: ExprContext, literalNodeMessage: String) { | |
ctx.children.removeAt(1) | |
val minusContext = MinusContext(ctx, 21) | |
val terminalNode = TerminalNodeImpl(CommonToken(FLOAT, literalNodeMessage)) | |
minusContext.addChild(terminalNode) | |
ctx.children.add(1, minusContext) | |
} | |
private fun swapLiteralChildren(ctx: ExprContext) { | |
val firstChild = ctx.children.removeAt(0) | |
val lastChild = ctx.children.removeAt(1) | |
ctx.children.add(0, lastChild) | |
ctx.children.add(firstChild) | |
} | |
override fun exitLt(@NotNull ctx: LtContext) { | |
super.exitLt(ctx) | |
} | |
private fun isOperation(parseTree: ParseTree): Boolean { | |
return parseTree.childCount == 1 && parseTree.getChild(0) is TerminalNode | |
} | |
companion object { | |
@JvmField val Epsilon: Double = java.lang.Double.MIN_NORMAL | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment