ProblemSolving
From J Wiki
Jump to navigation
Jump to search
I cleaned the code considerably, and posted at rosettacode.
NB. verbs and adverb
parse_table=: ;:@:(LF&= [;._2 -.&CR)
mp=: $:~ :(+/ .*) NB. matrix product
min=: <./ NB. minimum
Index=: (i.`)(`:6) NB. Index adverb
dijkstra=: dyad define
'LINK WEIGHT'=. , (0 _ ,. 2) <;.3 y
'SOURCE SINK'=. |: LINK
FRONTIER=. , < {. x
GOAL=. {: x
enumerate=. 2&([\)&.>
while. FRONTIER do.
PATH_MASK=. FRONTIER (+./@:(-:"1/)&:>"0 _~ enumerate)~ LINK
I=. PATH_MASK min Index@:mp WEIGHTS
PATH=. I >@{ FRONTIER
STATE=. {: PATH
if. STATE -: GOAL do. PATH return. end.
FRONTIER=. (<<< I) { FRONTIER NB. elision
ADJACENCIES=. (STATE = SOURCE) # SINK
FRONTIER=. FRONTIER , PATH <@,"1 0 ADJACENCIES
end.
EMPTY
)
NB. The specific problem
INPUT=: noun define
a b 7
a c 9
a f 14
b c 10
b d 15
c d 11
c f 2
d e 6
e f 9
)
T=: parse_table INPUT
NAMED_LINKS=: _ 2 {. T
NODES=: ~. , NAMED_LINKS NB. vector of boxed names
NUMBERED_LINKS=: NODES i. NAMED_LINKS
WEIGHTS=: _ ".&> _ _1 {. T
GRAPH=: NUMBERED_LINKS ,. WEIGHTS NB. GRAPH is the numerical representation
TERMINALS=: NODES (i. ;:) 'a e'
NODES {~ TERMINALS dijkstra GRAPH
Note 'Output'
┌─┬─┬─┬─┐
│a│c│d│e│
└─┴─┴─┴─┘
)
NB. to do: store frontier both as priority queue and as a set.
Note 'tree_search'
Dyadic adverbs "treeSearch" and "graphSearch" are the essence of this code.
The dyads are designed to take the universe as y and
as x, whatever may be appropriate.
The adverbs construct a verb from a gerund.
The verbs of the gerund need to be self consistent
with the universe. I haven't tried other variations.
comments lie, this note isn't current
(initialState;goal) gerund treeSearch problemSpace
gerund m shall be
isEmpty`isGoal`removeChoice`followPath
isEmpty problemSpace Boolean determines if the problem space is empty
isGoal
removeChoice frontier returns a (carefully selected) choice from the frontier and removes it from the frontier.
)
RomanianCities=: ;:'Arad Zerind Oradea Sibiu Fagaras Timisoara Lugoj Mehadia Drobeta Craiova RimnicuVilcea Pitesti Bucharest Giurgiu Urziceni Hirsova Eforie Vaslui Iasi Neamt'
NB. node node road_length
RomanianRoads=: ".;._2]0 :0
0 1 75
0 3 140
0 5 118
1 2 71
2 3 151
5 6 111
6 7 70
7 8 75
8 9 120
9 10 146
9 11 138
3 10 80
3 4 99
4 12 211
10 11 97
11 9 138
11 12 101
12 13 90
12 14 85
14 15 98
15 16 86
14 17 142
17 18 92
18 19 87
)
RomanianRoads=: ~.(, 1 0 2 {"1 ])RomanianRoads
Universe=: RomanianCities;RomanianRoads
NB. An admissible heuristic does not overestimate the distance to the goal.
h=: 0 : 0 NB. crow's distance heuristic from named city to Bucharest.
Arad 366
Zerind 374
Oradea 380
Sibiu 253
Fagaras 176
Timisoara 329
Lugoj 244
Mehadia 241
Drobeta 242
Craiova 160
RimnicuVilcea 193
Pitesti 100
Bucharest 0
Giurgiu 77
Urziceni 80
Hirsova 151
Eforie 161
Vaslui 199
Iasi 226
Neamt 234
)
Crow=: _2({.,".&.>@{:)\;:(LF=h)}h,:' ' NB. noun, n by string;integer
NB. city Crow Heuristic Universe
NB. node heuristic_noun heuristically Universe
heuristically=: 1 : '(((] >@{:@{~ (i.~ _ 1&(,@{.)))&m)@<@toString) :: 0:'
extractCities=: 0&{::
extractPaths=: 1&{::
links=: 2&(]\>) NB. nodes 0 3 4 12
NB. cost function
weigh=: [: +/ links@:>@[ ((i.~ _ 2&{.) { 2&{"1@]) extractPaths@] NB. path weigh Universe
steps=: #@>@[ NB. path steps Universe
AStar=: weigh + Crow heuristically
Choice=:2 : '{.@I.@(= u)@:(v"0 _)' NB. frontier (<./)Cost steps Universe
IndexShortest=: <./ Choice steps NB. frontier IndexShortest Universe
IndexLongest=: >./ Choice steps NB. needs all paths, works not
IndexCheapest=: <./ Choice weigh
IndexAStar=: <./ Choice (weigh + AStar)
NB. conversions to index from index or string
toString=: >@(({~ 0&+)~ :: [) extractCities NB. 1 toString Universe
toIndex=: (0+[) :: (]i.<@:>@[) extractCities NB. 1 toIndex Universe
Display=: smoutput@toString
ExtractFrontier=: toIndex ((I.@e.~ _ 1 ,@{. ]) { ]) extractPaths@] NB. 'Arad'ExtractFrontier Universe
Transition=: 1&{"1@ExtractFrontier
NB. frontier is a list of boxed paths
NB. frontier Choose universe returns index of next path to follow
IsEmpty=: 0 = #
IsGoal=: 1 : (':'; 'x m&-:@toString y')
treeSearch=: adverb define
:
'`display isEmpty choose isGoal transition'=. m
'initial goal'=. x
universe=. y
frontier=. ,<initial toIndex universe
while. 0=isEmpty frontier do.
i=. frontier choose universe
path=. i >@{ frontier
state=. {: path
if. state isGoal universe do. path return. end.
frontier=. (<<<i){frontier NB. elision
adjacencies=. state transition universe
frontier=. frontier , path <@,"1 0 adjacencies
end.
EMPTY
)
g=: Display`IsEmpty`0:`('Bucharest'IsGoal)`Transition
(;:'Arad Bucharest')g treeSearch Universe
graphSearch=: adverb define
:
'`display isEmpty choose isGoal transition'=. m
'initial goal'=. x
universe=. y
explored=. ''
frontier=. ,<initial toIndex universe
while. 0=isEmpty frontier do.
i=. frontier choose universe
path=. i >@{ frontier
state=. {: path
if. state isGoal universe do. path return. end.
frontier=. (<<<i){frontier NB. elision
explored=. explored , state
adjacencies=. state transition universe
unseenAdjacencies=. adjacencies -. explored NB. , {:@>frontier
frontier=. frontier , path <@,"1 0 unseenAdjacencies
end.
EMPTY
)
(;:'Arad Bucharest')g graphSearch Universe
Note 'Examples'
NB. Choose cheapest from the frontier
Universe toString~ (;:'Arad Bucharest')(Display`IsEmpty`IndexCheapest`('Bucharest'IsGoal)`Transition) graphSearch Universe
Arad
Sibiu
RimnicuVilcea
Pitesti
Bucharest
NB. Choose longest from the frontier
Universe toString~ (;:'Arad Bucharest')(Display`IsEmpty`IndexLongest`('Bucharest'IsGoal)`Transition) graphSearch Universe
Arad
Zerind
Oradea
Sibiu
RimnicuVilcea
Pitesti
Bucharest
NB. Choose shortest from the frontier
Universe toString~ (;:'Arad Bucharest')(Display`IsEmpty`IndexShortest`('Bucharest'IsGoal)`Transition) graphSearch Universe
Arad
Sibiu
Fagaras
Bucharest
NB. A* search, choose minimal estimated distance to goal + distance covered so far
Universe toString~ (;:'Arad Bucharest')(Display`IsEmpty`IndexAStar`('Bucharest'IsGoal)`Transition) graphSearch Universe
Arad
Sibiu
RimnicuVilcea
Pitesti
Bucharest
)