@@ -18,7 +18,10 @@ under the License.
1818* */
1919package io .github .mandar2812 .dynaml .optimization
2020
21+ import breeze .linalg .DenseVector
2122import breeze .stats .distributions .CauchyDistribution
23+ import io .github .mandar2812 .dynaml .utils
24+
2225import scala .util .Random
2326
2427/**
@@ -32,7 +35,12 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
3235
3336 protected var MAX_ITERATIONS : Int = 10
3437
35- var variant = CoupledSimulatedAnnealing .MuSA
38+ protected var variant = CoupledSimulatedAnnealing .MuSA
39+
40+ def setVariant (v : String ) = {
41+ variant = v
42+ this
43+ }
3644
3745 def setMaxIterations (m : Int ) = {
3846 MAX_ITERATIONS = m
@@ -56,8 +64,7 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
5664
5765 var iTemp = 1.0
5866
59- protected def acceptance (energy : Double , oldEnergy : Double , coupling : Double , temperature : Double ) =
60- CoupledSimulatedAnnealing .acceptanceProbability(variant)(energy, oldEnergy, coupling, temperature)
67+ var alpha = 0.05
6168
6269 protected val mutate = (config : Map [String , Double ], temperature : Double ) => {
6370 logger.info(" Mutating configuration: " + GlobalOptimizer .prettyPrint(config))
@@ -74,19 +81,27 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
7481 def mutationTemperature (initialTemp : Double )(k : Int ): Double =
7582 initialTemp/ k.toDouble
7683
77- def gamma (landscape : Seq [Double ])(accTemp : Double ): Double =
78- CoupledSimulatedAnnealing .couplingFactor(variant)(landscape, accTemp)
79-
8084 override def optimize (initialConfig : Map [String , Double ],
8185 options : Map [String , String ] = Map ()) = {
8286
83- // create grid
87+ logger.info(" -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" )
88+ logger.info(" Coupled Simulated Annealing: " + CoupledSimulatedAnnealing .algorithm(variant))
89+ logger.info(" -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" )
8490
8591 var accTemp = iTemp
8692 var mutTemp = iTemp
8793
94+ // Calculate desired variance
95+ val sigmaD = CoupledSimulatedAnnealing .varianceDesired(variant)(math.pow(gridsize, initialConfig.size).toInt)
96+
8897 val initialEnergyLandscape = getEnergyLandscape(initialConfig, options)
8998
99+
100+ val gamma_init = CoupledSimulatedAnnealing .couplingFactor(variant)(initialEnergyLandscape.map(_._1), accTemp)
101+ var acceptanceProbs : List [Double ] = initialEnergyLandscape.map(c => {
102+ CoupledSimulatedAnnealing .acceptanceProbability(variant)(c._1, c._1, gamma_init, accTemp)
103+ })
104+
90105 def CSATRec (eLandscape : List [(Double , Map [String , Double ])], it : Int ): List [(Double , Map [String , Double ])] =
91106 it match {
92107 case 0 => eLandscape
@@ -97,60 +112,47 @@ class CoupledSimulatedAnnealing[M <: GloballyOptimizable](model: M)
97112 // the generating distribution
98113 // and accept using the acceptance distribution
99114 mutTemp = mutationTemperature(iTemp)(it)
100- accTemp = acceptanceTemperature(iTemp)(it)
115+ accTemp = variant match {
116+ case CoupledSimulatedAnnealing .MwVC =>
117+ val (_,variance) = utils.getStats(acceptanceProbs.map(DenseVector (_)))
118+
119+ if (variance(0 ) < sigmaD)
120+ accTemp * (1 - alpha)
121+ else accTemp * (1 + alpha)
122+ case _ =>
123+ acceptanceTemperature(iTemp)(it)
124+ }
101125
102126 val maxEnergy = eLandscape.map(_._1).max
103127
104- val couplingFactor = gamma(eLandscape.map(t => t._1 - maxEnergy))(accTemp)
128+ val couplingFactor = CoupledSimulatedAnnealing .couplingFactor(variant)(
129+ eLandscape.map(t => t._1 - maxEnergy),
130+ accTemp)
131+
105132 // Now mutate each solution and accept/reject
106133 // according to the acceptance probability
107- val newEnergyLandscape = eLandscape.map((config) => {
134+ val ( newEnergyLandscape,probabilities) = eLandscape.map((config) => {
108135 // mutate this config
109136 val new_config = mutate(config._2, mutTemp)
110137 val new_energy = system.energy(new_config, options)
138+
139+ // Calculate the acceptance probability
140+ val acceptanceProbability = CoupledSimulatedAnnealing .acceptanceProbability(variant)(
141+ new_energy - maxEnergy, config._1,
142+ couplingFactor, accTemp)
143+
111144 val ans = if (new_energy < config._1) {
112- (new_energy, new_config)
145+ (( new_energy, new_config), acceptanceProbability )
113146 } else {
114- val acc = acceptance( new_energy - maxEnergy, config._1, couplingFactor, accTemp )
115- if ( Random .nextDouble <= acc) (new_energy, new_config) else config
147+ if ( Random .nextDouble <= acceptanceProbability) (( new_energy, new_config), acceptanceProbability )
148+ else (config, acceptanceProbability)
116149 }
117150 ans
118- })
151+ }).unzip
152+ acceptanceProbs = probabilities
119153 CSATRec (newEnergyLandscape, it- 1 )
120154 }
121155
122-
123- /* cfor(1)(iteration => iteration <= MAX_ITERATIONS, iteration => iteration + 1)( iteration => {
124- logger.info("**************************")
125- logger.info("CSA Iteration: "+iteration)
126- //mutate each element of the grid with
127- //the generating distribution
128- //and accept using the acceptance distribution
129- mutTemp = mutationTemperature(iTemp)(iteration)
130- accTemp = acceptanceTemperature(iTemp)(iteration)
131-
132- val maxEnergy = currentEnergyLandscape.map(_._1).max
133-
134- val couplingFactor = gamma(currentEnergyLandscape.map(t => t._1 - maxEnergy))(accTemp)
135- //Now mutate each solution and accept/reject
136- //according to the acceptance probability
137- val newEnergyLandscape = currentEnergyLandscape.map((config) => {
138- //mutate this config
139- val new_config = mutate(config._2, mutTemp)
140- val new_energy = system.energy(new_config, options)
141- val ans = if(new_energy < config._1) {
142- (new_energy, new_config)
143- } else {
144- val acc = acceptance(new_energy - maxEnergy, config._1, couplingFactor, accTemp)
145- if(Random.nextDouble <= acc) (new_energy, new_config) else config
146- }
147- ans
148- })
149-
150- currentEnergyLandscape = newEnergyLandscape
151-
152- })*/
153-
154156 val landscape = CSATRec (initialEnergyLandscape, MAX_ITERATIONS ).toMap
155157 val optimum = landscape.keys.min
156158
@@ -171,6 +173,13 @@ object CoupledSimulatedAnnealing {
171173 val MwVC = " CSA-MwVC"
172174 val SA = " SA"
173175
176+ def algorithm (variant : String ): String = variant match {
177+ case MuSA => " Multi-state Simulated Annealing"
178+ case BA => " Blind Acceptance"
179+ case M => " Modified"
180+ case MwVC => " Modified with Variance Control"
181+ }
182+
174183 def couplingFactor (variant : String )(landscape : Seq [Double ], Tacc : Double ): Double = {
175184 if (variant == MuSA || variant == BA )
176185 landscape.map(energy => math.exp(- 1.0 * energy/ Tacc )).sum
@@ -189,5 +198,13 @@ object CoupledSimulatedAnnealing {
189198 else gamma/ (1.0 + math.exp((energy - oldEnergy)/ temperature))
190199 }
191200
201+ def varianceDesired (variant : String )(m : Int ): Double = {
202+ if (variant == MuSA || variant == BA )
203+ 0.99
204+ else
205+ 0.99 * (m- 1 )/ math.pow(m, 2.0 )
206+
207+ }
208+
192209
193210}
0 commit comments