286 lines
9.8 KiB
Plaintext
286 lines
9.8 KiB
Plaintext
# there must be an relation edges
|
|
# and a file Speeds2
|
|
|
|
if not(isDBObject("Speeds2")) then restore Speeds2 from Speeds2 endif
|
|
|
|
query meminit(20000)
|
|
|
|
query memclear()
|
|
|
|
# in a first step, we sssign speeds to the edges of the relation
|
|
|
|
if not(isDBObject("EdgesB")) then
|
|
let EdgesB =
|
|
Speeds2 feed {s}
|
|
Edges feed filter[isdefined(.Curve)]
|
|
itHashJoin[RoadType_s, RoadType]
|
|
extend[Cost: size(.Curve,[const geoid value WGS1984]) / (.Speed_s / 3.6),
|
|
Middle: 0,
|
|
NEdges: 1.0]
|
|
project[Source, Target, SourcePos, TargetPos, Cost, Middle, NEdges]
|
|
filter[isdefined(.Cost)]
|
|
consume
|
|
endif
|
|
|
|
# store the EdgesB relation into an ordered relation to be able to create a graph from it
|
|
|
|
if not(isDBObject("EdgesB2")) then
|
|
let EdgesB2 = EdgesB feed
|
|
sortbyh[Source, Target]
|
|
oconsume[Source, Target]
|
|
endif
|
|
|
|
# store the largest connected component into relation EdgesC
|
|
|
|
if not(isDBObject("EdgesC")) then
|
|
{ query memglet("EdgesB", EdgesB2)
|
|
| let maxcompno = "EdgesB" mgconnectedcomponents sortbyh[CompNo]
|
|
groupby[CompNo; Cnt: group count] kbiggest[1; Cnt] extract[CompNo]
|
|
| let EdgesC = "EdgesB" mgconnectedcomponents filter[.CompNo = maxcompno] remove[CompNo] consume
|
|
| query memdelete("EdgesB")
|
|
| delete maxcompno
|
|
}
|
|
endif
|
|
|
|
|
|
# release memory used by the graph "EdgesB"
|
|
|
|
query memclear()
|
|
|
|
|
|
# We renumber the nodes from 0 .. nodecount -1
|
|
# using an mgraph2
|
|
|
|
if not(isDBObject("EdgesD")) then
|
|
{ query EdgesC feed createmgraph2[Source,Target,.Cost,"EdgesD", TRUE] count
|
|
|
|
|
let EdgesD = "EdgesD" mg2feed projectextend[; Source : .MG_Source, SourcePos : .SourcePos,
|
|
Cost : .MG_Cost, Middle : .Middle, NEdges : .NEdges,
|
|
Target : .MG_Target, TargetPos : .TargetPos] consume
|
|
|
|
|
if isDBObject("NodeCount") then delete NodeCount endif
|
|
|
|
|
let NodeCount = mg2numvertices("EdgesD")
|
|
}
|
|
endif
|
|
|
|
# release old memory objects
|
|
|
|
query memclear()
|
|
|
|
# create an mgraph3 from the EdgesD relation
|
|
|
|
query EdgesD feed createmgraph3[Source, Target, Cost, NodeCount, "EdgesX"] count
|
|
|
|
# store the nodes into a relation NodesA
|
|
|
|
|
|
if not(isDBObject("NodesA")) then
|
|
let NodesA = "EdgesX" mg3feed project[Source, SourcePos]
|
|
renameattr[NodeIdNew: Source, Pos: SourcePos]
|
|
"EdgesX" mg3feed project[Target, TargetPos]
|
|
renameattr[NodeIdNew: Target, Pos: TargetPos]
|
|
concat sorth rdup consume
|
|
endif
|
|
|
|
|
|
# create an empty relation for the contraction edges
|
|
query "EdgesX" mg3feed head[0] letmconsume["ContractionX"]
|
|
|
|
|
|
# create a priority queue from the nodes
|
|
query NodesA feed projectextend[; Node: .NodeIdNew, Pos: .Pos, Prio: 0.0]
|
|
mcreatepqueue[Prio, "NodesX"] count
|
|
|
|
# create an empty relation for the deleted nodes
|
|
query NodesA feed projectextend[; Node: .NodeIdNew, Pos: .Pos, Prio: 0.0, In: 0, Out: 0, CEdges: 0, Deleted: 0] head[0]
|
|
letmconsume["DeletedNodes"];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# define a function for contraction
|
|
|
|
# basic idea
|
|
# for all nodes in the queue
|
|
# if the product of in and out edges is higher than the periority => reinsert the node with adopted prio
|
|
# else
|
|
# if contraction of the edge reduces the number of edges or
|
|
# the exact priority is better than the guessed one
|
|
# then contract the node
|
|
# else reinsert the node
|
|
#
|
|
# if the current priority overcomes the threshold maxprio
|
|
# and at least minBlockSize nodes has been contracted since the
|
|
# last reorganisation of the priority queue
|
|
# then set all priorities within the queue to 0.0
|
|
#
|
|
|
|
|
|
if isDBObject("contract") then delete contract endif
|
|
|
|
|
|
let contract = fun(maxprio: int, minBlockSize : int, maxHops : int, progress : int)
|
|
"NodesX" mfeedpq
|
|
extend[
|
|
In : pwrap("EdgesX") mg3numpredecessors[.Node],
|
|
Out: pwrap("EdgesX") mg3numsuccessors[.Node]
|
|
]
|
|
extend[CEdges: fun(t: TUPLE)
|
|
ifthenelse(
|
|
(attr(t, In) * attr(t, Out)) <= attr(t, Prio),
|
|
pwrap("EdgesX") mg3predecessors[attr(t,Node)] sortbyh[Source, Cost] krdup[Source] {i}
|
|
pwrap("EdgesX") mg3successors[attr(t,Node)] sortbyh[Target, Cost] krdup[Target] {o}
|
|
product
|
|
filter[.Source_i # .Target_o]
|
|
filter[ ( fun(node: int) pwrap("EdgesX") mg3successors[node] )
|
|
minPathCost1[Target, .Source_i, .Target_o, Cost, maxHops] >= (.Cost_i + .Cost_o)
|
|
]
|
|
groupby[; Added: fun(g: GROUP)
|
|
ifthenelse(
|
|
(((attr(t, In) * attr(t, Out)) + ((g count) - (attr(t, In) + attr(t, Out)))) <= attr(t, Prio))
|
|
or
|
|
( (g count) <= attr(t,In) + attr(t,Out)),
|
|
g feed
|
|
projectextend[; Source: .Source_i,
|
|
SourcePos: .SourcePos_i,
|
|
Cost: .Cost_i + .Cost_o,
|
|
Middle: attr(t, Node),
|
|
NEdges: .NEdges_i + .NEdges_o,
|
|
Target: .Target_o,
|
|
TargetPos: .TargetPos_o
|
|
]
|
|
mg3insert[pwrap("EdgesX")]
|
|
minsert[pwrap("ContractionX")] count,
|
|
bool2int(pwrap("NodesX") minserttuplepqprojectU[t,
|
|
((attr(t, In) * attr(t, Out)) +
|
|
((g count) - (attr(t, In) + attr(t, Out)))) * 1.0,
|
|
Prio; Node, Pos, Prio]) - 10
|
|
)]
|
|
extractDef[Added, 0]
|
|
,
|
|
bool2int(pwrap("NodesX") minserttuplepqprojectU[t,
|
|
(attr(t, In) * attr(t, Out)) * 1.0,
|
|
Prio; Node, Pos, Prio]) - 10
|
|
)
|
|
]
|
|
filter[.CEdges >= 0]
|
|
addModCounter[Num,1, (.Prio > maxprio) and (.. > minBlockSize), 0]
|
|
extend[ Dummy : ifthenelse(.Num = 0,pwrap("NodesX") mpqreorderupdate[ 0.0, Prio ],0)]
|
|
remove[Num,Dummy]
|
|
addcounter[Progress,1]
|
|
filter[ ifthenelse((.Progress mod progress)=0,
|
|
TRUE echo[num2string(.Progress)],
|
|
TRUE)]
|
|
remove[Progress]
|
|
extend[Deleted: bool2int(pwrap("EdgesX") mg3disconnect[.Node]) ]
|
|
minsert[pwrap("DeletedNodes")]
|
|
count
|
|
|
|
|
|
##################### multitarget version of this function
|
|
|
|
if isDBObject("mtcreationEdges") then delete mtcreationEdges endif
|
|
|
|
|
|
let mtcreationEdges = fun(node10 : int, maxHops : int)
|
|
pwrap("EdgesX") mg3predecessors[node10] sortbyh[Source,Cost] krdup[Source] {i}
|
|
loopjoin[
|
|
fun(t10 : TUPLE)
|
|
(fun(node11: int) pwrap("EdgesX") mg3successors[node11])
|
|
pwrap("EdgesX") mg3successors[node10] sortbyh[Target,Cost] krdup[Target] {o}
|
|
mtMinPathCosts1[Target,attr(t10,Source_i), Target_o, Cost, maxHops]
|
|
filter[attr(t10,Source_i) # .Target_o]
|
|
extend[Cost : attr(t10,Cost_i) + .Cost_o]
|
|
filter[.MinPC >= .Cost]
|
|
remove[MinPC]
|
|
]
|
|
|
|
|
|
|
|
if isDBObject("mtcontract") then delete mtcontract endif
|
|
|
|
let mtcontract = fun(maxprio: int, minBlockSize : int, maxHops : int, progress : int)
|
|
"NodesX" mfeedpq
|
|
extend[
|
|
In : pwrap("EdgesX") mg3numpredecessors[.Node],
|
|
Out: pwrap("EdgesX") mg3numsuccessors[.Node]
|
|
]
|
|
extend[CEdges: fun(t: TUPLE)
|
|
ifthenelse(
|
|
(attr(t, In) * attr(t, Out)) <= attr(t, Prio),
|
|
mtcreationEdges(attr(t,Node), maxHops)
|
|
groupby[; Added: fun(g: GROUP)
|
|
ifthenelse(
|
|
(((attr(t, In) * attr(t, Out)) + ((g count) - (attr(t, In) + attr(t, Out)))) <= attr(t, Prio))
|
|
or
|
|
( (g count) <= attr(t,In) + attr(t,Out)),
|
|
g feed
|
|
projectextend[; Source: .Source_i,
|
|
SourcePos: .SourcePos_i,
|
|
Cost: .Cost_i + .Cost_o,
|
|
Middle: attr(t, Node),
|
|
NEdges: .NEdges_i + .NEdges_o,
|
|
Target: .Target_o,
|
|
TargetPos: .TargetPos_o
|
|
]
|
|
mg3insert[pwrap("EdgesX")]
|
|
minsert[pwrap("ContractionX")] count,
|
|
bool2int(pwrap("NodesX") minserttuplepqprojectU[t,
|
|
((attr(t, In) * attr(t, Out)) +
|
|
((g count) - (attr(t, In) + attr(t, Out)))) * 1.0,
|
|
Prio; Node, Pos, Prio]) - 10
|
|
)]
|
|
extractDef[Added, 0]
|
|
,
|
|
bool2int(pwrap("NodesX") minserttuplepqprojectU[t,
|
|
(attr(t, In) * attr(t, Out)) * 1.0,
|
|
Prio; Node, Pos, Prio]) - 10
|
|
)
|
|
]
|
|
filter[.CEdges >= 0]
|
|
addModCounter[Num,1, (.Prio > maxprio) and (.. > minBlockSize), 0]
|
|
extend[ Dummy : ifthenelse(.Num = 0,pwrap("NodesX") mpqreorderupdate[ 0.0, Prio ],0)]
|
|
remove[Num,Dummy]
|
|
addcounter[Progress,1]
|
|
filter[ ifthenelse((.Progress mod progress)=0,
|
|
TRUE echo[num2string(.Progress)],
|
|
TRUE)]
|
|
remove[Progress]
|
|
extend[Deleted: bool2int(pwrap("EdgesX") mg3disconnect[.Node]) ]
|
|
minsert[pwrap("DeletedNodes")]
|
|
count
|
|
|
|
|
|
|
|
########## the actual Contraction, play with arguments
|
|
|
|
|
|
query mtcontract(30,300,8, NodeCount div 100)
|
|
|
|
|
|
|
|
####### make result persistent
|
|
|
|
if isDBObject("EdgesX") then delete EdgesX endif
|
|
|
|
let EdgesX = "EdgesX" mg3feed consume
|
|
|
|
if isDBObject("NodesX") then delete NodesX endif
|
|
|
|
let NodesX = "NodesX" mfeedpq consume
|
|
|
|
{query memdelete("NodesX") | query NodesX feed mcreatepqueue[Prio, "NodesX"] count}
|
|
|
|
|
|
if isDBObject("ContractionX") then delete ContractionX endif
|
|
|
|
let ContractionX = "ContractionX" mfeed consume
|
|
|
|
if isDBObject("NodeOrder") then delete NodeOrder endif
|
|
|
|
let NodeOrder = "DeletedNodes" mfeed addcounter[NewId, 1] consume
|
|
|