This commit is contained in:
Anton Reinhard 2023-06-08 01:39:01 +02:00
parent 5bf660618d
commit 2a1b161462
13 changed files with 199 additions and 6 deletions

View File

@ -4,5 +4,6 @@ authors = ["Anton Reinhard <anton.reinhard@wandelbots.com>"]
version = "0.1.0"
[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

2
examples/AB->AB.txt Normal file
View File

@ -0,0 +1,2 @@
['A1', 'B1', 'A2', 'B2', 'C(A1,B1)', 'M(C(A1,B1),A2,B2)', 'C(A1,B2)', 'M(C(A1,B2),B1,A2)', '+']
[('A1', 'C(A1,B1)'), ('A1', 'C(A1,B2)'), ('B1', 'C(A1,B1)'), ('B1', 'M(C(A1,B2),B1,A2)'), ('A2', 'M(C(A1,B1),A2,B2)'), ('A2', 'M(C(A1,B2),B1,A2)'), ('B2', 'M(C(A1,B1),A2,B2)'), ('B2', 'C(A1,B2)'), ('C(A1,B1)', 'M(C(A1,B1),A2,B2)'), ('M(C(A1,B1),A2,B2)', '+'), ('C(A1,B2)', 'M(C(A1,B2),B1,A2)'), ('M(C(A1,B2),B1,A2)', '+')]

2
examples/AB->ABBB.txt Normal file

File diff suppressed because one or more lines are too long

2
examples/AB->ABBBBB.txt Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
examples/AB->ABBBBBBBBB.txt Normal file

Binary file not shown.

2
examples/ABAB->ABAB.txt Normal file

File diff suppressed because one or more lines are too long

2
examples/ABAB->ABC.txt Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,5 @@
using DataStructures
in(node::Node, graph::DAG) = node in graph.nodes
in(edge::Edge, graph::DAG) = edge in graph.edges
@ -44,8 +46,8 @@ function parents(graph::DAG, node::Node)
return result
end
is_entry_node(graph::DAG, node::Node) = size(children(graph, node)) == 0
is_exit_node(graph::DAG, node::Node) = size(parents(graph, node)) == 0
is_entry_node(graph::DAG, node::Node) = length(children(graph, node)) == 0
is_exit_node(graph::DAG, node::Node) = length(parents(graph, node)) == 0
function insert_node(graph::DAG, node::Node)
push!(graph.nodes, node)
@ -100,6 +102,25 @@ function get_exit_node(graph::DAG)
error("The given graph has no exit node! It is either empty or not acyclic!")
end
# check whether the given graph is connected
function is_valid(graph::DAG)
nodeQueue = Deque{Node}()
push!(nodeQueue, get_exit_node(graph))
seenNodes = Set{Node}()
while ! isempty(nodeQueue)
current = pop!(nodeQueue)
push!(seenNodes, current)
childrenNodes = children(graph, current)
for child in childrenNodes
push!(nodeQueue, child)
end
end
return length(seenNodes) == length(graph.nodes)
end
function show_nodes(io, graph::DAG)
print(io, "[")
first = true
@ -131,10 +152,34 @@ end
function show(io::IO, graph::DAG)
println(io, "Graph:")
print(io, " Nodes: ")
show_nodes(io, graph)
if length(graph.nodes) <= 20
show_nodes(io, graph)
else
nodeDict = Dict{Type, Int64}()
for node in graph.nodes
if haskey(nodeDict, typeof(node.task))
nodeDict[typeof(node.task)] = nodeDict[typeof(node.task)] + 1
else
nodeDict[typeof(node.task)] = 1
end
end
first = true
for (type, number) in zip(keys(nodeDict), values(nodeDict))
if first
first = false
else
print(", ")
end
print(type, ": ", number)
end
end
println(io)
print(io, " Edges: ")
show_edges(io, graph)
if length(graph.edges) <= 40
show_edges(io, graph)
else
print(length(graph.edges))
end
println(io)
println(io, " Total Compute Effort: ", compute_effort(graph))
println(io, " Total Data Transfer: ", data(graph))

127
src/import.jl Normal file
View File

@ -0,0 +1,127 @@
# functions for importing DAGs from a file
regex_a = r"^[A-C]\d+$" # Regex for the initial particles
regex_c = r"^[A-C]\(([^']*),([^']*)\)$" # Regex for the combinations of 2 particles
regex_m = r"^M\(([^']*),([^']*),([^']*)\)$" # Regex for the combinations of 3 particles
regex_plus = r"^\+$" # Regex for the sum
function parse_nodes(input::AbstractString)
regex = r"'([^']*)'"
matches = eachmatch(regex, input)
output = [match.captures[1] for match in matches]
return output
end
function parse_edges(input::AbstractString)
regex = r"\('([^']*)', '([^']*)'\)"
matches = eachmatch(regex, input)
output = [(match.captures[1], match.captures[2]) for match in matches]
return output
end
function importTxt(filename::String)
file = open(filename, "r")
nodes_string = readline(file)
nodes = parse_nodes(nodes_string)
close(file)
graph = DAG()
sum_node = insert_node(graph, make_node(ComputeTaskSum()))
global_data_out = insert_node(graph, make_node(DataTask(10)))
insert_edge(graph, make_edge(sum_node, global_data_out))
# remember the data out nodes for connection
dataOutNodes = Dict()
for node in nodes
if occursin(regex_a, node)
# add nodes and edges for the state reading to u(P(Particle))
data_in = insert_node(graph, make_node(DataTask(4))) # read particle data node
compute_P = insert_node(graph, make_node(ComputeTaskP())) # compute P node
data_Pu = insert_node(graph, make_node(DataTask(6))) # transfer data from P to u
compute_u = insert_node(graph, make_node(ComputeTaskU())) # compute U node
data_out = insert_node(graph, make_node(DataTask(3))) # transfer data out from u
insert_edge(graph, make_edge(data_in, compute_P))
insert_edge(graph, make_edge(compute_P, data_Pu))
insert_edge(graph, make_edge(data_Pu, compute_u))
insert_edge(graph, make_edge(compute_u, data_out))
# remember the data_out node for future edges
dataOutNodes[node] = data_out
elseif occursin(regex_c, node)
capt = match(regex_c, node)
in1 = capt.captures[1]
in2 = capt.captures[2]
compute_v = insert_node(graph, make_node(ComputeTaskV()))
data_out = insert_node(graph, make_node(DataTask(5)))
if (occursin(regex_c, capt.captures[1]))
# put an S node after this input
compute_S = insert_node(graph, make_node(ComputeTaskS1()))
data_S_v = insert_node(graph, make_node(DataTask(5)))
insert_edge(graph, make_edge(dataOutNodes[capt.captures[1]], compute_S))
insert_edge(graph, make_edge(compute_S, data_S_v))
insert_edge(graph, make_edge(data_S_v, compute_v))
else
insert_edge(graph, make_edge(dataOutNodes[capt.captures[1]], compute_v))
end
if (occursin(regex_c, capt.captures[2]))
# i think the current generator only puts the combined particles in the first space, so this case might never be entered
# put an S node after this input
compute_S = insert_node(graph, make_node(ComputeTaskS1()))
data_S_v = insert_node(graph, make_node(DataTask(5)))
insert_edge(graph, make_edge(dataOutNodes[capt.captures[2]], compute_S))
insert_edge(graph, make_edge(compute_S, data_S_v))
insert_edge(graph, make_edge(data_S_v, compute_v))
else
insert_edge(graph, make_edge(dataOutNodes[capt.captures[2]], compute_v))
end
insert_edge(graph, make_edge(compute_v, data_out))
dataOutNodes[node] = data_out
elseif occursin(regex_m, node)
# assume for now that only the first particle of the three is combined and the other two are "original" ones
capt = match(regex_m, node)
in1 = capt.captures[1]
in2 = capt.captures[2]
in3 = capt.captures[3]
# in2 + in3 with a v
compute_v = insert_node(graph, make_node(ComputeTaskV()))
data_v = insert_node(graph, make_node(DataTask(5)))
insert_edge(graph, make_edge(dataOutNodes[in2], compute_v))
insert_edge(graph, make_edge(dataOutNodes[in3], compute_v))
insert_edge(graph, make_edge(compute_v, data_v))
# combine with the v of the combined other input
compute_S2 = insert_node(graph, make_node(ComputeTaskS2()))
data_out = insert_node(graph, make_node(DataTask(10)))
insert_edge(graph, make_edge(data_v, compute_S2))
insert_edge(graph, make_edge(dataOutNodes[in1], compute_S2))
insert_edge(graph, make_edge(compute_S2, data_out))
insert_edge(graph, make_edge(data_out, sum_node))
elseif occursin(regex_plus, node)
println("Found sum node, end")
else
error("Unknown node '", node, "' while reading from file ", filename)
end
end
# don't actually need to read the edges
return graph
end

View File

@ -10,11 +10,13 @@ include("task_functions.jl")
include("node_functions.jl")
include("graph_functions.jl")
include("graph_optimizations.jl")
include("import.jl")
export Node, Edge, ComputeTaskNode, DataTaskNode, DAG
export AbstractTask, AbstractComputeTask, AbstractDataTask, DataTask, ComputeTaskP, ComputeTaskS1, ComputeTaskS2, ComputeTaskV, ComputeTaskU, FusedComputeTask
export make_node, make_edge, insert_node, insert_edge, is_entry_node, is_exit_node, parents, children, compute, data, compute_effort, compute_intensity, get_exit_node
export AbstractTask, AbstractComputeTask, AbstractDataTask, DataTask, ComputeTaskP, ComputeTaskS1, ComputeTaskS2, ComputeTaskV, ComputeTaskU, ComputeTaskSum, FusedComputeTask
export make_node, make_edge, insert_node, insert_edge, is_entry_node, is_exit_node, parents, children, compute, data, compute_effort, compute_intensity, get_exit_node, is_valid
export node_fusion, node_reduction, node_split, generate_options
export importTxt
export ==, in, show

View File

@ -24,6 +24,7 @@ compute_effort(t::ComputeTaskS2) = 10
compute_effort(t::ComputeTaskU) = 6
compute_effort(t::ComputeTaskV) = 20
compute_effort(t::ComputeTaskP) = 15
compute_effort(t::ComputeTaskSum) = 1
function compute_effort(t::FusedComputeTask)
(T1, T2) = collect(typeof(t).parameters)
return compute_effort(T1()) + compute_effort(T2())
@ -48,6 +49,7 @@ show(io::IO, t::ComputeTaskS2) = print("ComputeS2")
show(io::IO, t::ComputeTaskP) = print("ComputeP")
show(io::IO, t::ComputeTaskU) = print("ComputeU")
show(io::IO, t::ComputeTaskV) = print("ComputeV")
show(io::IO, t::ComputeTaskSum) = print("ComputeSum")
function show(io::IO, t::FusedComputeTask)
(T1, T2) = get_types(t)

View File

@ -27,6 +27,10 @@ end
struct ComputeTaskU <: AbstractComputeTask
end
# task that sums all its inputs, n children
struct ComputeTaskSum <: AbstractComputeTask
end
struct FusedComputeTask{T1<:AbstractComputeTask, T2<:AbstractComputeTask} <: AbstractComputeTask
end