Created
October 7, 2013 08:24
-
-
Save ewnd9/6864356 to your computer and use it in GitHub Desktop.
Genetic Algorithm for finding boolean equations system's solution
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
!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 |
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
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