\$\begingroup\$
\$\endgroup\$
I decided to try and implement (a version of) the simulated annealing algorithm using just LINQ, just to see if I could.
I'd love it if anybody could see any ways to improve it, or give advice on any cool tricks for doing this kind of thing.
var result = (from res in Enumerable.Range(0, 1)
let R = new Random()
let initial = Enumerable.Range(0, 10).Select(i => R.Next(-10, 10))
let iterations = Enumerable.Range(0, 100)
let Schedule = (Func<int, float>)
(X => 4 + (float)Math.Sin(X))
from iteration in iterations
let temperature = Schedule(iteration)
let state = Enumerable.Range(0, 10).Select(i => R.Next(-10, 10))
let DeltaE = state.Sum() - initial.Sum()
where DeltaE > 0 ||
Math.Pow(Math.E, DeltaE / temperature) > R.NextDouble()
select state.ToList()
).OrderBy(S => S.Sum()).First();
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Oct 29, 2011 at 3:15
1 Answer 1
\$\begingroup\$
\$\endgroup\$
You have a lot of small errors here.
- What is the purpose of
from res in Enumerable.Range(0, 1)
? It looks like you did it to force some local variables into 'let' queries, which makes no sense to me. - Instead of using
OrderBy(X).First()
you should useMinBy(X)
(write it yourself if it doesn't exist). There's a significant performance difference. - The value of
initial
changes every time it is enumerated. Confusing. (You can cache the results withToArray
orToList
to prevent re-enumerating from running moreRandom.Next
calls) - Ensure
new Random()
is only performed once (do it outside the query). The default seed is the current time, which is highly correlated between calls. You're likely to end up with two instances ofRandom
with the exact same seed. Random.Next(-10, 10)
returns values in[-10, +9]
. You probably wanted[-10, +10]
.
palacsint
30.3k9 gold badges82 silver badges157 bronze badges
answered Nov 1, 2011 at 16:11
lang-cs