Files
secondo/bin/Scripts/ContractionN.sec
2026-01-23 17:03:45 +08:00

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