Thanks, Raul. It's a good point. This hasn't been validated at all. I suppose 
the lazy way to validate would be to force a single path to be minimal:

modifydistance =: 3 : 0
'from to distance' =. y

if. to = >: from do.
distance =. 1
elseif. distance < 10 do.
distance =. 10
end.
from, to, distance
)

Then, before running the algorithm do

cities =. modifydistance"1 cities

so the minimal path is definitely 0->1->2->...->MAX_CITY

I ran my original algorithm with the modified distances, and it doesn't even 
come close to the optimal solution (after 500 iterations, which took about 2 
minutes to run, for 26 cities). One point to note is the algorithm searches for 
the minimum hamiltonian path, not cycle, so presumably if it gets stuck at a 
non-optimal start city (i.e. doesn't make "city 0" the start city) it could 
throw it all off. But for whatever reason, the algorithm does not converge 
anywhere near the correct result.
I don't know enough about genetic algorithms to know if this bad result is 
expected. e.g. it could be trapped in local minima or something. But anyway, 
it's a disappointing turn of events. 

Other points to note:
Number of chromosomes is pretty small (~40), I think in general this should be 
much bigger.
My original algorithm stops after a set number of iterations, not after 
convergence is found, which is not good.


--------------------------------------------
On Tue, 12/22/15, Devon McCormick <[email protected]> wrote:

 Subject: Re: [Jprogramming] Genetic algorithms?
 To: "J-programming forum" <[email protected]>
 Date: Tuesday, December 22, 2015, 11:11 AM
 
 Thanks, everyone, for
 your responses.  Hopefully I'll have some time over
 the holidays to look at this and compare it to
 some sources in C# I found
 online.
 
 On Mon, Dec 21, 2015 at 11:25
 AM, Raul Miller <[email protected]>
 wrote:
 
 > Typo - last
 minute name change - the unused reference to nextchild,
 at
 > the end, should have been
 >
 > nextchildren=.
 nextchildren + 2
 >
 >
 Thanks,
 >
 > --
 > Raul
 >
 >
 > On Mon, Dec 21, 2015
 at 8:13 AM, Raul Miller <[email protected]>
 > wrote:
 > > Here is a
 "slightly more j-like" re-implementation.
 > >
 > > I presume
 it's approximately a "work-alike". (I say
 approximately
 > > because of the
 random aspect of its implementation):
 >
 >
 > > NB. solution to the Traveling
 Salesman Problem using a genetic algorithm
 > > NB. to find the minimum cost path
 through all cities.
 > >
 > > require'stats'
 > >
 > >
 MUTATION_RATE=: 0.1 NB. rate of gene mutation after
 mating.
 > > POPULATION=: 40 NB.
 population of chromosomes
 > >
 MATING_POP=: <.POPULATION % 2
 > >
 SELECTED_POP=: <.MATING_POP % 2
 > >
 CITYCOUNT=: 26 NB. number of cities.
 >
 >
 > > list=: 2 comb CITYCOUNT
 > >
 > > NB. list of
 cities with random distances
 > >
 cities=: (list,.0)+1000*?0,.~1"0 list
 > > boxedcities=: <"1 list
 > >
 > > NB. create
 POPULATION chromsomes, each representing
 > > NB. a hamiltonian path on the city
 network.
 > > createChromosomes=: ]
 ?&.> POPULATION&$
 > >
 > > chromosomes=: createChromosomes
 CITYCOUNT
 > >
 >
 > NB. calculates the cost of a single chromosome,
 > > NB. i.e. the total distance along the
 path
 > > NB. represented by the
 chromosome.
 > > cost=: 3 : 0 @>
 > >   edges=. <"1
 /:~"1 (2]\ > y)
 >
 >   +/, 2{"1 ((edges ="0 _
 boxedcities) # cities)
 > >
 > > )
 > >
 > > NB. sort the paths, since we want the
 minimum cost.
 > > sortPaths=:
 chromosomes /: (cost"0 chromosomes)
 > >
 > >
 sortChromosomes=: ] /: cost"(0)
 >
 >
 > > smear1=:4 :0
 > >   have=. (e.~ i.@#) y
 > >   if. 0 e. have do.
 > >    (have i. 0) x} y
 > >   else.
 > >     y
 > >   end.
 > > )
 > >
 > > smear2=:4 :0
 >
 >   have=. (e.~ i.@-@#)
 y
 > >   if. 0 e. have
 do.
 > >    (have i. 0) x} y
 > >   else.
 > >     y
 > >   end.
 > > )
 > >
 > > mate=: 3 : 0
 >
 >   'mother father child1 child2'=:
 y
 > >   CUT=. 5
 > >
 >
 >   for_j. i. # mother do.
 > >     if. j < CUT do.
 > >       child1=. j smear1
 child1
 > >       child2=.
 j smear1 child2
 > > 
    elseif. j > CUT do.
 >
 >       child1=. j smear2 child1
 > >       child2=. j smear2
 child2
 > >     end.
 > >   end.
 > >
 >
 >   NB. handle mutations
 >
 >   mrate=. 100 * MUTATION_RATE
 > >   chance=. ? 100
 > >   if. mrate < chance
 do. NB. always succeeds because ? is rigged
 > >     mutated=. ~.? 2 #
 CITYCOUNT
 > >     child1=.
 (<mutated) C. child1
 >
 >   end.
 >
 >   chance=. ? 100
 >
 >   if. mrate < chance do.
 > >     mutated=. ~. ? 2 #
 CITYCOUNT
 > >     child2=.
 (<mutated) C. child2
 >
 >   end.
 > >
 > >  child1;child2
 >
 > )
 > >
 >
 >
 > > NB. iterate for x
 generations, where one
 > > NB.
 iteration is the mating of all
 > > NB.
 matable chromosomes, and the sorting
 >
 > NB. of the new chromosomes by the cost function.
 > > NB. y is boxed ordered paths through
 the cities
 > > iterate=: 4 : 0
 > >   NB. only perform set
 number of iterations. Ideally
 >
 >   NB. should only stop once the min cost
 stops changing
 > >   NB.
 for a set number of iterations.
 >
 >   c=. 0
 >
 >   for. i.#x  do.
 >
 >     c=. c + 1
 > > 
    nextchildren=. MATING_POP+0 1
 > >     for_j. i.
 SELECTED_POP do.
 > >   
    choice=. ?SELECTED_POP
 >
 >       newGeneration=. mate
 (j,choice,nextchildren) {  y
 > >   
    y=. newGeneration nextchildren } y
 > >       nextchild=.
 nextchildren + 2
 > > 
    end.
 > >
 > >     y=. sortChromosomes
 y
 > >   end.
 > >   y
 >
 > )
 > >
 > >
 Note that I have left sample data generation the way that it
 was in
 > > the original (for example,
 sortChromosomes depends on the distances
 > > between cities).
 >
 >
 > > But I am not sure how
 you'd test something like this for correctness.
 > > And I'd need a good test
 heuristic before I could take this any
 >
 > further.
 > >
 >
 > Any suggestions?
 > >
 > > Thanks,
 > >
 > > --
 > > Raul
 > >
 > >
 > > On Sun, Dec 20, 2015 at 1:54 AM,
 'Jon Hough' via Programming
 >
 > <[email protected]>
 wrote:
 > >> I created a toy genetic
 algorithm program to solve the traveling
 > salesman problem for a randomly generated
 graph (cities with distances).
 > It's
 not written in very J-like code unfortunately. It also seems
 pretty
 > slow, possibly due to lots of
 in-place assignments. Anyway, it might
 >
 interest you.
 > >>
 > >> NB. solution to the Traveling
 Salesman Problem using a genetic algorithm
 > >> NB. to find the minimum cost path
 through all cities.
 > >>
 > >> MUTATION_RATE=: 0.1 NB. rate of
 gene mutation after mating.
 > >>
 POPULATION=: 40 NB. population of chromosomes
 > >> MATING_POP=: <.POPULATION %
 2
 > >> SELECTED_POP=:
 <.MATING_POP % 2
 > >>
 CITYCOUNT=: 26 NB. number of cities.
 >
 >>
 > >> list=: (#~
 </"1)@(#: i.@:(*/)) 2 # CITYCOUNT
 > >>
 > >> NB.
 list of cities with random distances
 >
 >> cities=: list,"(1 1) (1,~ 2!CITYCOUNT) $ 1000
 * (? (2!CITYCOUNT) # 0)
 > >>
 boxedcities=: <"1 ( 0 1 {"1 cities)
 > >>
 > >> NB.
 create POPULATION chromsomes, each representing
 > >> NB. a hamiltonian path on the
 city network.
 > >>
 createChromosomes=: ] ?&.>
 (<"0@:(POPULATION&$))
 >
 >>
 > >> chromosomes=:
 createChromosomes CITYCOUNT
 > >>
 > >> NB. calculates the cost of a
 single chromosome,
 > >> NB. i.e.
 the total distance along the path
 >
 >> NB. represented by the chromosome.
 > >> cost=: 3 : 0
 >
 >> edges=. <"1 /:~"1 (2]\ > y)
 > >> +/, 2{"1 ((edges ="0 _
 boxedcities) # cities)
 > >>
 > >> )
 >
 >>
 > >> NB. sort the paths,
 since we want the minimum cost.
 >
 >> sortPaths=: chromosomes /: (cost"0
 chromosomes)
 > >>
 > >> sortChromosomes=: ] /:
 cost"(0)
 > >>
 > >> mate=: 3 : 0
 >
 >> mother=. >0{y
 > >>
 father=. >1{y
 > >> child1=.
 >2{y
 > >> child2=. >3{y
 > >> CUT=. 5
 >
 >>
 > >> for_j. i. # mother
 do.
 > >>   if. j <
 CUT do.
 > >>     for_k.
 i. CITYCOUNT do.
 > >>   
    if. -.(k e. child1) do.
 >
 >>         child1=. k (j}) child1
 > >>         break.
 > >>       end.
 > >>     end.
 > >>     for_k.
 i.CITYCOUNT do.
 > >>   
    if. -.(k e. child2) do.
 >
 >>         child2=. (k{father) j}
 child2
 > >>     
    break.
 > >>   
    end.
 > >> 
    end.
 >
 >>   elseif. j > CUT do.
 > >>     for_k. i.
 CITYCOUNT do.
 > >>   
    k=. <: CITYCOUNT - k
 >
 >>       if. -.(k e. child1) do.
 > >>         child1=.
 (k) j}child1
 > >>     
    break.
 > >>   
    end.
 > >> 
    end.
 > >> 
    for_k. i.CITYCOUNT do.
 >
 >>
 > >>   
    k=. <: CITYCOUNT - k
 >
 >>       if. -.((k{father) e. child2)
 do.
 > >>     
    child2=. (k{father) j}child2
 > >>         break.
 > >>       end.
 > >>     end.
 > >>
 > >>
 > >>   end.
 > >> end.
 >
 >>
 > >>
 >
 >> NB. handle mutations
 > >>
 mrate=. 100 * MUTATION_RATE
 > >>
 chance=. ?. 2 # 100
 > >> if. mrate
 < 0{chance do.
 >
 >>   mutated=. ? 2 # CITYCOUNT
 > >>   m1=.
 (0{mutated){child1
 >
 >>   m2=. (1{mutated){child1
 > >>   child1=. (m2, m1)
 mutated} child1
 > >> end.
 > >>
 > >>
 chance=. ?. 2 # 100
 > >> if. mrate
 < 0{chance do.
 >
 >>   mutated=. ? 2 # CITYCOUNT
 > >>   m1=.
 (0{mutated){child2
 >
 >>   m2=. (1{mutated){child2
 > >>   child2=. (m2, m1)
 mutated} child2
 > >> end.
 > >>
 > >>
 child1;child2
 > >> )
 > >>
 > >>
 > >> NB. iterate for x generations,
 where one
 > >> NB. iteration is the
 mating of all
 > >> NB. matable
 chromosomes, and the sorting
 > >>
 NB. of the new chromosomes by the cost function.
 > >> iterate=: 4 : 0
 > >> generations=. x
 > >> orderedPaths=. y
 > >> op=. orderedPaths
 > >>
 > >> NB.
 only perform set number of iterations. Ideally
 > >> NB. should only stop once the min
 cost stops changing
 > >> NB. for a
 set number of iterations.
 > >> c=.
 0
 > >> while. c < generations
 do.
 > >>   c=. c + 1
 > >>   nextchild=.
 MATING_POP
 > >>   for_j.
 i. SELECTED_POP do.
 > >> 
    mother=. j { op
 >
 >>     father=. (? SELECTED_POP) { op
 > >>     child1=.
 nextchild { op
 > >> 
    child2=. (>: nextchild) { op
 > >>     newGeneration=.
 mate mother,father,child1,child2
 >
 >>
 > >>     op=.
 newGeneration (nextchild, (>: nextchild)) } op
 > >>     nextchild=.
 nextchild + 2
 > >>
 > >>   end.
 > >>
 >
 >>   op=. sortChromosomes op
 > >> end.
 >
 >> op
 > >> )
 > >>
 > >>
 > >>
 > >>
 > >> For example,
 >
 >>
 > >>   ]a=. 100
 iterate chromosomes
 > >>
 > >> will give a list of possible
 paths, the minimum cost path (found after
 > 100 iterations) is first.
 > >>
 > >>
 cost 0{ a
 > >>
 >
 >> gives the minimum cost.
 >
 >>
 > >>
 >
 >> --------------------------------------------
 > >> On Fri, 12/18/15, Devon McCormick
 <[email protected]>
 wrote:
 > >>
 >
 >>  Subject: [Jprogramming] Genetic algorithms?
 > >>  To: "J-programming
 forum" <[email protected]>
 > >>  Date: Friday, December 18,
 2015, 5:52 AM
 > >>
 > >>  Has anyone done work in J on
 genetic
 > >> 
 algorithms?   I'm thinking of coding
 > >>  up something along these lines
 as I don't find any relevant
 >
 >>  hits for this
 > >>  on
 the J wiki.
 > >>
 > >>  --
 >
 >>
 > >>  Devon McCormick,
 CFA
 > >>
 >
 >>  Quantitative Consultant
 >
 >> 
 ----------------------------------------------------------------------
 > >>  For information about J forums
 see http://www.jsoftware.com/forums.htm
 > >>
 ----------------------------------------------------------------------
 > >> For information about J forums
 see http://www.jsoftware.com/forums.htm
 >
 ----------------------------------------------------------------------
 > For information about J forums see http://www.jsoftware.com/forums.htm
 >
 
 
 
 -- 
 
 Devon McCormick, CFA
 
 Quantitative Consultant
 ----------------------------------------------------------------------
 For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to