Skip to content

Instantly share code, notes, and snippets.

@ewnd9
Created October 7, 2013 08:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ewnd9/6864356 to your computer and use it in GitHub Desktop.
Save ewnd9/6864356 to your computer and use it in GitHub Desktop.
Genetic Algorithm for finding boolean equations system's solution
!x0&!x4&!x7&!x9+x1&x4&x5+x2&!x5&!x6&x7=1
x1&x2&!x6&x8+x2&x7&!x8&x9=1
x2&x3&x4+x2&x4&x7&x8+x1&!x6&!x8&!x9+!x0&!x2&x4&!x6+x0&x6&!x9=1
!x3&!x4&!x6+!x1&x4&x8&!x9+x1&x2&x8&!x9=0
!x0&x3&x6&!x7+x0&x2&!x7&!x9=0
x1&!x5&x6&!x7+!x0&!x1&x4+x1&x7+!x3&x5&!x9=1
import scala.util.Random
/**
* User: ewnd9
* Date: 10/7/13 : 3:25 PM
*/
object Main {
abstract class Term {
def solve(vars: List[Int]): Int = {
this match {
case Var(n, sign) => if (sign == 1) vars(n) else (vars(n) + 1) % 2
case Op("+", l, r) => l.solve(vars) ^ r.solve(vars)
case Op("&", l, r) => l.solve(vars) & r.solve(vars)
}
}
override def toString = {
this match {
case Var(n, sign) => (if (sign == 1) "" else "!") + "x" + n
case Op(s, l, r) => s"$l$s$r"
}
}
}
object Term {
def apply(source: String): Term = {
def h(op: String, source: String): Term = {
val xs = source.split("\\" + op)
if (xs.size == 1) {
val sign = if (xs(0).contains("!")) 0 else 1
val n = xs(0).filter(_.isDigit).toInt
Var(n, sign)
} else {
xs.drop(2).foldLeft(Op(op, h("&", xs(0)), h("&", xs(1))))((t: Term, c: String) => Op(op, t, h("&", c)))
}
}
h("+", source)
}
}
case class Var(n: Int, sign: Int) extends Term
case class Op(operator: String, left: Term, right: Term) extends Term
case class Equation(term: Term, result: Int) {
def solve(vars: List[Int]): Boolean = term.solve(vars) == result
}
object Equation {
def apply(source: String): Equation = {
val data = source.split("=")
new Equation(Term(data(0)), data(1).toInt)
}
}
case class System(equations: List[Equation]) {
def solve(vars: List[Int]) = equations.filter(_.solve(vars))
}
object System {
def apply(list: String*): System = System(list.map(Equation(_)).toList)
}
def main(args: Array[String]) = {
val zipped = args.zipWithIndex
def param(key: String, default: String) = {
zipped.find(_._1 == key)
.flatMap(i => if ((i._2 + 1) > (args.size - 1)) None else Some(args(i._2 + 1)))
.getOrElse(default)
}
val input = scala.io.Source.fromFile(param("-file", "input.in")).mkString("").split("\n")
val regex = "-?\\d+".r
val max = input.foldLeft(0) { (sum: Int, c: String) =>
Math.max(sum, regex.findAllIn(c).foldLeft(0)((sum: Int, c: String) => Math.max(sum, c.toInt)))
}
val system = System(input:_*)
val rand = new Random()
var spreading =
(1 to param("-population", "3").toInt).map { _ =>
(0 to max).map(_ => rand.nextInt(2)).toList
}.toList
val result = scala.collection.mutable.Set[(List[Int], Int)]()
def crossover(xs: List[List[Int]]) =
xs :+ (xs(0).take(xs(0).size / 2) ::: xs(1).drop(xs(0).size / 2))
def mutation(xs: List[List[Int]]) = {
val pos1 = rand.nextInt(xs.size)
val pos2 = rand.nextInt(xs(0).size)
val center = (xs(pos1).take(pos2) :+ (((xs(pos1)(pos2)) + 1) % 2)) ::: xs(pos1).drop(pos2 + 1)
(xs.take(pos1) :+ center) ::: xs.drop(pos1 + 1)
}
for (_ <- 1 to param("-n", "20").toInt) {
val top = spreading.map(xs => (xs, system.solve(xs).size)).sortBy(_._2).reverse
top.takeWhile(_._2 == top(0)._2).foreach { xs =>
if (result.size > 0 && result.toList(0)._2 != xs._2) result.clear
result += xs
}
var next = top.map(_._1)
next = crossover(next)
next = mutation(next)
spreading = next
}
println(result.toList)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment