Skip to content

Instantly share code, notes, and snippets.

@Groostav
Created July 24, 2017 17:35
Show Gist options
  • Save Groostav/01fadaf725b995531b69b799ba91530c to your computer and use it in GitHub Desktop.
Save Groostav/01fadaf725b995531b69b799ba91530c to your computer and use it in GitHub Desktop.
initial rewrite of the rewriting walker
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