@@ -19,6 +19,7 @@ under the License.
1919package io .github .mandar2812 .dynaml .optimization
2020
2121import breeze .stats .distributions .CauchyDistribution
22+ import spire .implicits ._
2223
2324import scala .util .Random
2425
@@ -33,6 +34,8 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
3334
3435 protected var MAX_ITERATIONS : Int = 10
3536
37+ var variant = CoupledSimulatedAnnealing .MuSA
38+
3639 def setMaxIterations (m : Int ) = {
3740 MAX_ITERATIONS = m
3841 this
@@ -53,9 +56,7 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
5356 this
5457 }
5558
56- protected val acceptance = (energy : Double ,
57- coupling : Double ,
58- temperature : Double ) => {
59+ protected def acceptance (energy : Double , oldEnergy : Double , coupling : Double , temperature : Double ) = {
5960 val prob = math.exp(- 1.0 * energy/ temperature)
6061 prob/ (prob+ coupling)
6162 }
@@ -74,6 +75,9 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
7475 def mutationTemperature (initialTemp : Double )(k : Int ): Double =
7576 initialTemp/ k.toDouble
7677
78+ def gamma (landscape : Seq [Double ])(accTemp : Double ): Double =
79+ CoupledSimulatedAnnealing .couplingFactor(variant)(landscape, accTemp)
80+
7781 override def optimize (initialConfig : Map [String , Double ],
7882 options : Map [String , String ] = Map ()) = {
7983
@@ -85,28 +89,29 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
8589 val energyLandscape = getEnergyLandscape(initialConfig, options)
8690
8791 var currentEnergyLandscape = energyLandscape
88- var newEnergyLandscape = energyLandscape
8992
90- ( 1 to MAX_ITERATIONS ).foreach(( iteration) => {
93+ cfor( 1 )(iteration => iteration < MAX_ITERATIONS , iteration => iteration + 1 )( iteration => {
9194 logger.info(" **************************" )
9295 logger.info(" CSA Iteration: " + iteration)
9396 // mutate each element of the grid with
9497 // the generating distribution
9598 // and accept using the acceptance distribution
9699 mutTemp = mutationTemperature(iTemp)(iteration)
97100 accTemp = acceptanceTemperature(iTemp)(iteration)
98- val couplingFactor = currentEnergyLandscape.map(c => math.exp(- 1.0 * c._1/ accTemp)).sum
101+
102+ val maxEnergy = currentEnergyLandscape.map(_._1).max
103+
104+ val couplingFactor = gamma(currentEnergyLandscape.map(t => t._1 - maxEnergy))(accTemp)
99105 // Now mutate each solution and accept/reject
100106 // according to the acceptance probability
101-
102- newEnergyLandscape = currentEnergyLandscape.map((config) => {
107+ val newEnergyLandscape = currentEnergyLandscape.map((config) => {
103108 // mutate this config
104109 val new_config = mutate(config._2, mutTemp)
105110 val new_energy = system.energy(new_config, options)
106111 val ans = if (new_energy < config._1) {
107112 (new_energy, new_config)
108113 } else {
109- val acc = acceptance(new_energy, couplingFactor, accTemp)
114+ val acc = acceptance(new_energy - maxEnergy, config._1 , couplingFactor, accTemp)
110115 if (Random .nextDouble <= acc) (new_energy, new_config) else config
111116 }
112117 ans
@@ -126,3 +131,33 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
126131 (system, landscape(optimum))
127132 }
128133}
134+
135+
136+ object CoupledSimulatedAnnealing {
137+
138+ val MuSA = " CSA-MuSA"
139+ val BA = " CSA-BA"
140+ val M = " CSA-M"
141+ val MwVC = " CSA-MwVC"
142+ val SA = " SA"
143+
144+ def couplingFactor (variant : String )(landscape : Seq [Double ], Tacc : Double ): Double = {
145+ if (variant == MuSA || variant == BA )
146+ landscape.map(energy => math.exp(- 1.0 * energy/ Tacc )).sum
147+ else if (variant == M || variant == MwVC )
148+ landscape.map(energy => math.exp(energy/ Tacc )).sum
149+ else 1.0
150+ }
151+
152+ def acceptanceProbability (variant : String )(energy : Double , oldEnergy : Double , gamma : Double , temperature : Double ) = {
153+ if (variant == MuSA )
154+ math.exp(- 1.0 * energy/ temperature)/ (math.exp(- 1.0 * energy/ temperature)+ gamma)
155+ else if (variant == BA )
156+ 1.0 - (math.exp(- 1.0 * oldEnergy/ temperature)/ gamma)
157+ else if (variant == M || variant == MwVC )
158+ math.exp(oldEnergy/ temperature)/ gamma
159+ else gamma/ (1.0 + math.exp((energy - oldEnergy)/ temperature))
160+ }
161+
162+
163+ }
0 commit comments