# Iterating using Channel

i have some problems in replacing the deprecated function `produce()`with `Channel()`in this code:

``````function scan_maker(A)
m = JuMP.Model(solver=ClpSolver(PrimalTolerance=1e-3, DualTolerance=1e-3, InfeasibleReturn=1, PresolveType=1))
# m = Model(solver=GurobiSolver())
level = size(A, 2)
v = zeros(Int, level)
ub = zeros(Int, level)
lb = zeros(Int, level)

@variable(m, x[1:level])
@constraint(m, con, A*x.>=0)

function setc(c)
for i = 1:size(A, 1)
m.linconstr[i].lb = float(c[i])
end
end

function scan()
i = 1
init = 1
while i > 0
if i >= init
@objective(m, Max, x[i])
res = JuMP.solve(m, suppress_warnings=true)
if res==:Optimal || res==:Unbounded
ub[i] = round(Int, getvalue(x[i]))
setobjectivesense(m, :Min)
res = JuMP.solve(m, suppress_warnings=true)
@assert res==:Optimal || res==:Unbounded
lb[i] = round(Int, getvalue(x[i]))

v[i] = lb[i]
init += 1
else
@assert res==:Infeasible
i -= 1
continue
end
elseif v[i] < ub[i]
v[i] += 1
else
setupperbound(x[i], Inf)
setlowerbound(x[i], -Inf)
init -= 1
i -= 1
continue
end

if i >= level
produce(v)
continue
else
setupperbound(x[i], v[i])
setlowerbound(x[i], v[i])
i += 1
end
end
end

return setc, scan
end
``````

i have tried to put `c::Channel` as an argument of the function `scan()`and change `produce(v)`with `put!(c,v)` the function was compiled but when i want to call the functions for example:

``````julia> A=[2 2;1 1;4 3]
3×2 Array{Int64,2}:
2  2
1  1
4  3
julia> B=[2;3;7]
3-element Array{Int64,1}:
2
3
7
julia> a,b=scan_maker(A)
(getfield(Main, Symbol("#setc#3")){Array{Int64,2},Model}([2 2; 1 1; 4 3], Feasibility problem with:
* 3 linear constraints
* 2 variables
Solver is Clp), getfield(Main, Symbol("#scan#4")){Model,Int64,Array{Int64,1},Array{Int64,1},Array{Int64,1},Array{Variable,1}}(Feasibility problem with:
* 3 linear constraints
* 2 variables
Solver is Clp, 2, [0, 0], [0, 0], [0, 0], x[i] ∀ i ∈ {1,2}))

julia> a(B)            # i'm calling the new function which is supposed to return nothing and it's working

julia> mychannel=Channel((channel_arg) -> b( pwd(), channel_arg))          # defining a Channel
Channel{Any}(sz_max:0,sz_curr:0)

julia> b(mychannel)
ERROR: MethodError: no method matching (::getfield(Main, Symbol("#scan#4")){Model,Int64,Array{Int64,1},Array{Int64,1},Array{Int64,1},Array{Variable,1}})(::String, ::Channel{Any})
Stacktrace:
[1] check_channel_state at ./channels.jl:117 [inlined]
[2] put! at ./channels.jl:273 [inlined]
[3] push! at ./channels.jl:312 [inlined]
[4] (::getfield(Main, Symbol("#scan#4")){Model,Int64,Array{Int64,1},Array{Int64,1},Array{Int64,1},Array{Variable,1}})(::Channel{Any}) at ./REPL[3]:50
[5] top-level scope at REPL[20]:1
``````

when i call the function `scan` i get that error above, i don’t know how to deal with this.
The output should be something like this:

``````v = [-1, 6]
v = [0, 4]
v = [1, 2]
``````

(Hello and welcome!)

It is not really clear what you did exactly, but your approach should work. Here is a minimal example demonstrating it:

``````function scan_maker(n)
function scan(c::Channel)
for i in 1:n
put!(c, i)
end

close(c)
end
return scan
end
``````
``````julia> scan = scan_maker(5)
scan (generic function with 1 method)

julia> chan = Channel(scan)
Channel{Any}(sz_max:0,sz_curr:1)

julia> for i in chan
@show i
end
i = 1
i = 2
i = 3
i = 4
i = 5
``````

Judging from the error message that you get, your first problem comes from the creation of the channel:

``````mychannel=Channel((channel_arg) -> b( pwd(), channel_arg))
``````

should be something else, perhaps simply

``````mychannel=Channel(b)
``````

but it’s difficult to be sure without seeing the modified `scan_maker` code that you actually used to produce `b`

2 Likes

the modification was in `scan` function like this

``````function scan(c::Channel)
i = 1
init = 1
while i > 0
if i >= init
@objective(m, Max, x[i])
res = JuMP.solve(m, suppress_warnings=true)
if res==:Optimal || res==:Unbounded
ub[i] = round(Int, getvalue(x[i]))
setobjectivesense(m, :Min)
res = JuMP.solve(m, suppress_warnings=true)
@assert res==:Optimal || res==:Unbounded
lb[i] = round(Int, getvalue(x[i]))

v[i] = lb[i]
init += 1
else
@assert res==:Infeasible
i -= 1
continue
end
elseif v[i] < ub[i]
v[i] += 1
else
setupperbound(x[i], Inf)
setlowerbound(x[i], -Inf)
init -= 1
i -= 1
continue
end

if i >= level
put!(c, v)
close(c)
continue
else
setupperbound(x[i], v[i])
setlowerbound(x[i], v[i])
i += 1
end
end
end
``````

an now i have tried to create a `Channel` by simply doing the same thing : `mychannel=Channel(b)` i get this one : `Channel{Any}(sz_max:0,sz_curr:1)` and when i call the function after by `b(mychannel)`the code compiles non stop without giving me anything :
`julia> b(mychannel)`

Could you please post a complete example of what you did? And if you can, reduce you problem to something minimal like I did in my earlier post: for example, Jump probably has nothing to do with you problem, and you could just keep the logic of your code, but not actually call Jump.

There is a relatively complete list of advice that you might find useful to express your problem in a way that will help us help you more effectively: Please read: make it easier to help you

By the way, did you try the example I gave you? Did it work?

1 Like

in general i put `c::Channel` as an argument of function `scan` and changed `produce(v)` with `take!(c,v)` and the i closed using `close(c)` .
your entire approach works now except one problem is that i don’t get all the outputs, when i do :

``````julia> chnl=Channel(b)
Channel{Any}(sz_max:0,sz_curr:1)

julia> for i in chnl
@show i
end
i = [-2, 6]
``````

as you can see i get only one output at the time i’m supposed to get 5 outputs like this :

``````v = [-2, 6]
v = [-1, 6]
v = [0, 4]
v = [1, 4]
v = [2, 2]
``````

Again, please post runnable code exhibiting the bad behavior you encounter: it is often not particularly easy to debug code, but it gets very hard when you don’t even know what code you’re debugging

That being said, if the code with which you obtain only one result (instead of 5) is the one you posted above, one mistake in it is that you close the channel as soon as you write in it

``````            if i >= level
put!(c, v)
close(c)
continue
else
# ...
``````

You should `put` all results in the channel, and only `close` it at the end of the calculation

2 Likes

yes you are right, i didn’t know that i was cloing the channel right after the calculation i should’ve close it after the end of the loop , i have compared the outputs that i get using `Channel`and the ones when i use `@show`, they are similar.