This little example puts together previously introduced ideas about Scala and tries to show a non-trivial algorithm. It is a basic implementation of an optimization algorithm called particle swarm optimization. See Wikipedia's page on the topic for details of what it is and what it is useful for.
Basically, it is a numerical optimization algorithms which finds minimal values of a continuous (i.e., real-valued) function. It has been applied to many different areas, such as training artificial neural networks. human tremor analysis, reactive power and voltage control, and many other areas in science, engineering, and machine learning.
Without further ado, the code.
// Basic particle swarm optimization // by Warren Henning (email: firstname period lastname at gmail) // Released under Apache License v2.0 // THIS. IS. SCALAAAA!!! /* Opportunities for improvement: 1. General refactoring, this code sucks my balls but whaddya gonna do? 2. Make the vector ops do calls out to a fast BLAS-type library or something - this example is just convenient because it's self-contained 3. Use better algorithms that are more resistant to local minima, such as: @inproceedings{DBLP:conf/epia/SilvaNC03, author = {Arlindo Silva and Ana Neves and Ernesto Costa}, title = {SAPPO: A Simple, Adaptable, Predator Prey Optimiser.}, booktitle = {EPIA}, year = {2003}, pages = {59-73}, ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=2902{\&}spage=59}, crossref = {DBLP:conf/epia/2003}, bibsource = {DBLP, http://dblp.uni-trier.de} } @proceedings{DBLP:conf/epia/2003, editor = {Fernando Moura-Pires and Salvador Abreu}, title = {Progress in Artificial Intelligence, 11th Protuguese Conference on Artificial Intelligence, EPIA 2003, Beja, Portugal, December 4-7, 2003, Proceedings}, booktitle = {EPIA}, publisher = {Springer}, series = {Lecture Notes in Computer Science}, volume = {2902}, year = {2003}, isbn = {3-540-20589-6}, bibsource = {DBLP, http://dblp.uni-trier.de} } For more information on swarm intelligence algorithms, the best introduction and reference as of May 2007 is: A. P. Engelbrecht. Fundamentals of Computational Swarm Intelligence. Wiley, 2005. */ import java.util.Random import Console._ object SimplePSO { def unit_rand_vec(n: Int) = Array.range(0,n) map (x => Math.random) def rand_dbl(a: Double, b: Double) = { val u = Math.random a*(1.0-u) + b*u } def rand_vec(n: Int, a: Double, b: Double) = Array.range(1,n+1) map (x => rand_dbl(a,b)) def dup(n: Int, value: Double) = Array.range(0,n) map (n => value) class PSOSystem(f: Array[Double] => Double, dim: Int, dimmax: Double, dimmin: Double, w: Double, c_1: Double, c_2: Double, swarm_size: Int, iter_cnt: Int) { var x = ((1 to swarm_size toList) toArray) map {n:Int => rand_vec(dim, dimmin, dimmax) } var pbest = new Array[Array[Double]](x.length) var v = ((1 to swarm_size toList) toArray) map {n:Int => dup(dim, 0.0)} var gbest = dup(dim, 0.0) def init { 0 until pbest.length foreach {i => pbest(i) = new Array[Double](dim) System.arraycopy(x, 0, pbest, 0, x.length) } val min = x reduceLeft {(w:Array[Double],v:Array[Double]) => if(f(w) < f(v)) w else v} System.arraycopy(min, 0, gbest, 0, min.length) } def updatePosAndVel(i: Int, j: Int) { val inertia = w*v(i)(j) val cog = c_1*Math.random*(pbest(i)(j)-x(i)(j)) val soc = c_2*Math.random*(gbest(j)-x(i)(j)) v(i)(j) = if(inertia + cog + soc > 5.0) 5.0 else inertia + cog + soc x(i)(j) = x(i)(j)+v(i)(j) } def updatePbest(i: Int) { if(f(x(i)) < f(pbest(i))) System.arraycopy(x(i), 0, pbest(i), 0, x.length) } def updateGbest(i: Int) { if(f(x(i)) < f(gbest)) { Console.println("New best found: " + f(x(i))) System.arraycopy(x(i), 0, gbest, 0, x(i).length) } } def oneIter { 0 until swarm_size foreach { i => 0 until dim foreach { j => updatePosAndVel(i,j) updatePbest(i) updateGbest(i) } } } def swarmData { println("\nPosition") x foreach { particle => println(particle deepMkString ", ") } println("\nVelocity") v foreach { particle => println(particle deepMkString ", ") } println("Gbest is: " + (gbest deepMkString ",")) } def doLearning { 1 to iter_cnt foreach {k => oneIter} } } def main(args: Array[String]) { val ps = new PSOSystem(v => v(0)*v(0)+v(1)*v(1)+v(2)*v(2)+v(3)*v(3)+v(4)*v(4), // hypersphere - global minimum at origin 5, // 5-dimensional -5.0, // in [-5,5]^n 5.0, 1.0-1.0e-5, // inertia 1.5, // c_1 1.5, // c_2 20, // swarm size of 15 1000) // 1000 iterations ps.init ps.doLearning ps.swarmData } }