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