我有一个复杂的问题,我必须从之前构建的图形中评估边缘的总和。 朱莉娅似乎没有用边缘处理条件求和。
这是一个类似于我想要解决的问题的简单问题:
module EssaiModule
using LightGraphs, MetaGraphs
g = DiGraph(6)
mg = MetaDiGraph(g, 1.0)
add_vertex!(mg)
add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)
set_props!(mg,3,Dict(:port=>1,:vessel=>2))
set_props!(mg,1,Dict(:port=>1,:vessel=>0))
set_props!(mg,2,Dict(:port=>1,:vessel=>0))
set_props!(mg,4,Dict(:port=>1,:vessel=>2))
set_props!(mg,5,Dict(:port=>0,:vessel=>2))
set_props!(mg,6,Dict(:port=>0,:vessel=>0))
SI = sum(1 for e in edges(mg);get_prop(g,dst(e),:vessel)==2 && get_prop(g,dst(e),:port)==1)
println(SI)
end
当我测试时,我得到了错误
#LoadError: MethodError: no method matching dst(::Irrational{:e})
我真的需要弄清楚如何与条件求和,因为在我的实际问题中,我将此总和放在一个约束中,就像这样,边上的总和ed
和x
变量:< / p>
@constraint(model, cM[e in edges(g)], x[e] + sum(x[ed] for ed in edges(g) ; fn1(ed) == 2 && fn2(ed) == 1) <= 1 + y)
我收到错误消息
#LoadError: UndefVarError: ed not defined
所以我的问题如下:
为什么第一个代码不起作用,因为e
的类型是Int
?
我是否以不好的方式写约束?
对不起,我无法上传真正的问题,内容和数据不会上线,而且太大了。
答案 0 :(得分:5)
对于问题的第一部分,您需要更改函数调用
SI = sum(1 for e in edges(mg);get_prop(g,dst(e),:vessel)==2 && get_prop(g,dst(e),:port)==1)
# ^ you end the statement with a semicolon
# after the semicolon, keyword arguments of a function, in this case `sum`,
# begins. then, the compiler checks the function `dst` and cannot find a proper
# method that is implemented for e, that is, the irrational number e.
如下所示:
SI = length([e for e in edges(mg) if get_prop(mg, dst(e), :vessel) == 2 &&
get_prop(mg, dst(e), :port ) == 1 ])
println(SI) # prints 3
还请注意代码中的拼写错误。 get_prop
需要来检查mg
,而不是g
。您还应该查看文档的comprehensions部分。
对于问题的第二部分,您应该为我们提供宏定义,以便更好地帮助您。最有可能的是,你不是interpolating宏内的表达式/变量。请参阅my answer以查看其他问题并说明是否有帮助。
编辑1。实际上,您的第二部分也存在相同的问题。在sum
内,您使用分号结束位置参数并启动keyword arguments。
编辑2。根据下面的DNF评论,您甚至应该使用count
来表达更具表现力(源代码)和高效版本:
SI = count(e->(get_prop(mg, dst(e), :vessel) == 2 &&
get_prop(mg, dst(e), :port ) == 1 ), edges(mg))
# or,
SI = count(get_prop(mg, dst(e), :vessel) == 2 &&
get_prop(mg, dst(e), :port ) == 1 for e in edges(mg))
编辑3。效果比较如下:
Pkg.add("BenchmarkTools")
using BenchmarkTools
@benchmark count(e->(get_prop(mg, dst(e), :vessel) == 2 &&
get_prop(mg, dst(e), :port ) == 1 ), edges(mg))
BenchmarkTools.Trial:
memory estimate: 7.73 KiB
allocs estimate: 53
--------------
minimum time: 2.201 μs (0.00% GC)
median time: 2.494 μs (0.00% GC)
mean time: 3.191 μs (15.69% GC)
maximum time: 198.515 μs (95.69% GC)
--------------
samples: 10000
evals/sample: 9
@benchmark count(get_prop(mg, dst(e), :vessel) == 2 &&
get_prop(mg, dst(e), :port ) == 1 for e in edges(mg))
BenchmarkTools.Trial:
memory estimate: 7.75 KiB
allocs estimate: 54
--------------
minimum time: 2.352 μs (0.00% GC)
median time: 2.661 μs (0.00% GC)
mean time: 3.712 μs (15.10% GC)
maximum time: 236.440 μs (95.06% GC)
--------------
samples: 10000
evals/sample: 9
@benchmark length([e for e in edges(mg) if get_prop(mg, dst(e), :vessel) == 2 &&
get_prop(mg, dst(e), :port ) == 1])
BenchmarkTools.Trial:
memory estimate: 8.13 KiB
allocs estimate: 60
--------------
minimum time: 2.642 μs (0.00% GC)
median time: 2.789 μs (0.00% GC)
mean time: 3.553 μs (14.54% GC)
maximum time: 231.424 μs (94.73% GC)
--------------
samples: 10000
evals/sample: 9
count
版本的效率似乎比length
提高了10%,这可能会对您实际的更大问题产生影响。
编辑4。由于DNF,再次进行基准测试的正确方法如下:
@benchmark count(e->(get_prop($mg, dst(e), :vessel) == 2 &&
get_prop($mg, dst(e), :port ) == 1 ), edges($mg))
BenchmarkTools.Trial:
memory estimate: 7.72 KiB
allocs estimate: 52
--------------
minimum time: 2.320 μs (0.00% GC)
median time: 2.478 μs (0.00% GC)
mean time: 2.952 μs (10.33% GC)
maximum time: 117.306 μs (93.38% GC)
--------------
samples: 10000
evals/sample: 9
@benchmark count(get_prop($mg, dst(e), :vessel) == 2 &&
get_prop($mg, dst(e), :port ) == 1 for e in edges($mg))
BenchmarkTools.Trial:
memory estimate: 7.73 KiB
allocs estimate: 53
--------------
minimum time: 2.340 μs (0.00% GC)
median time: 2.524 μs (0.00% GC)
mean time: 3.030 μs (11.17% GC)
maximum time: 197.018 μs (94.35% GC)
--------------
samples: 10000
evals/sample: 9