When I use the function f
with only the Module
f[a1_, a2_, a3_]:= Module[.....]
f[0,0,1200]
works fine but gives errors when I use compile
as follows.
demand[n_, k_, qr_] := Min[k Vf, n capacity - qr]; supply[n_, k_, qr_] := Min[(n Kj - k) w, n capacity - qr];
Nsupply[n_, k_, qsum_, qrsum_, qr_] := Min[(n Kj - k) Vf - qsum - qrsum, n capacity - qr];
floExct[n_, ku_, k_, qsum_, qrsum_, qr_] := Min[demand[n, ku, qr], Nsupply[n, k, qsum, qrsum, qr]];
gamma[ku_, kd_] := Min[1, supply[L, kd, 0]/(demand[L, ku, 0] + 0.001)];
inflow[phi_, qin_] := (phi - \[Beta] qin) dx;
density[qin_, qout_, qr_] := (qin - qout + qr)/Vf;
Kj = 150.; w = 20.; Vf = 100.; capacity = 2500.; n = 30; m = 100; p = 27; RML = 18; \[Alpha] = 1200.; \[Beta] = 0.; L = 1.; delta = 1.; dt =4./3600.; dx = 1./9.;
f= Compile[{{a1, _Integer}, {a2, _Integer}, {a3, _Integer}},
Module[{k0 = ConstantArray[0., n],
Fk = Table[Table[0., {i1, n}], {j, 5}],
kr = Table[Table[0., {i1, 1, p}], {i2, 1, n - 2}],
Rk = Table[Table[Table[0., {i1, 1, p}], {i2, 1, n - 2}], {i3, 4}], \[Phi],
Fq = Table[Table[0., {i1, n - 1}], {j, 4}], qin,
Fin = Table[Table[0., {i1, n - 2}], {j, 4}], qr,
Rq = Table[Table[Table[0., {i1, 1, p}], {i2, 1, n - 2}], {i3, 4}],
RMori = Table[0., {i1, 1, n - 2}],
RM = Table[0., {i1, 1, n - 2}], TT = 0., qf, qsum, qrsum},
RMori = Table[a1 (i1 dx)^2 + a2 (i1 dx) + a3, {i1, 1, n - 2}];
kr = ReplacePart[#, (\[Alpha] delta/Vf), 1] & /@ kr; AppendTo[Rk, kr];
\[Phi] = demand[1, #[[-1]], 0] & /@ kr MapThread[gamma, {Take[k0, {2, -2}], Take[k0, {3, -1}]}];
qsum = N[Plus @@ Fq];
qrsum = Join[Plus @@ Fin, {0}];
qf = MapThread[floExct[L, #1, #2, #3, #4, #5] &, {Most@k0, Rest@(Fk[[1]]), qsum,qrsum, Join[\[Phi], {0}]}];
qin = inflow[\[Phi], Most@qf];
k0 += Join[{0}, density[Most@qf, Rest@qf, qin], {0}];
qsum = MapThread[Plus, #] &@Rq;
RM = MapThread[Min[#1, #2] &, {RMori, MapThread[floExct[1, #1[[RML]], #2[[RML + 1]], #3[[RML]], 0, 0] &, {kr,Rk[[1]], qsum}]}];
qr = MapThread[Join[#1, {#2}, #3, {#4}] &, {
MapThread[floExct[1, #1, #2, #3, 0, 0] &, {Take[#, {1, RML - 1}] & /@ kr,Take[#, {2, RML}] & /@ Rk[[1]], Take[#, {1, RML - 1}] & /@ qsum}, 2], RM,
MapThread[floExct[1, #1, #2, #3, 0, 0] &, {Take[#, {RML + 1, -2}] & /@ kr, Take[#, {RML + 2, -1}] & /@ Rk[[1]], Take[#, {RML + 1, -2}] & /@ qsum}, 2], \[Phi]}];
kr = MapThread[(#1 + #2) &, {Join[{0}, #] & /@ (density[Most@#, Rest@#, 0] & /@ qr), kr}];
TT += Plus @@ k0; TT += Plus @@ (Plus @@ kr);
Fq = Delete[Fq, {1}]; Fin = Delete[Fin, {1}]; Rq = Delete[Rq, {1}]; Fk = Delete[Fk, {1}]; Rk = Delete[Rk, {1}];
AppendTo[Fq, qf]; AppendTo[Fin, qin]; AppendTo[Rq, qr]; AppendTo[Fk, k0]; AppendTo[Rk, kr];
TT]]
all the errors (as shown below) are related to the qsum
variable. Can someone tell me what I am missing?
MapThread::list: List expected at position 2 in MapThread[Plus,Compile`FunctionVariable$266]. >>
Compile::cprank: Compile cannot determine the rank of the result tensor. The length of CompileFunctionVariable$266 in MapThread[Plus,Compile`FunctionVariable$266] is unknown at compiling time; evaluation will use the uncompiled function. >>
Compile::cset: Variable qsum of type {_Real,1} encountered in assignment of type {_Integer,0}. >>
Compile::part: Part specification Compile
GetElement[qsum,CompileVariable$912][[18]] cannot be compiled since the argument is not a tensor of sufficient rank. Evaluation will use the uncompiled function. >>
Compile::part: Part specification Compile`GetElement[qsum,Compile`Variable$912][[18]] cannot be compiled since the argument is not a tensor of sufficient rank. Evaluation will use the uncompiled function. >>
Compile::part: Part specification Compile
GetElement[qsum,CompileVariable$1852][[18]] cannot be compiled since the argument is not a tensor of sufficient rank. Evaluation will use the uncompiled function. >>
General::stop: Further output of Compile::part will be suppressed during this calculation. >>
Compile::cplist: Compile`GetElement[qsum,System`Private`CompileSymbol[0]] should be a tensor of type Integer, Real, or Complex; evaluation will use the uncompiled function. >>
Compile::cplist: Compile`GetElement[qsum,System`Private`CompileSymbol[0]] should be a tensor of type Integer, Real, or Complex; evaluation will use the uncompiled function. >>
Compile::cplist: Compile`GetElement[qsum,System`Private`CompileSymbol[0]] should be a tensor of type Integer, Real, or Complex; evaluation will use the uncompiled function. >>
General::stop: Further output of Compile::cplist will be suppressed during this calculation. >>
MapThread::list: List expected at position 2 in MapThread[Plus,Compile`FunctionVariable$3193]. >>
Compile::cprank: Compile cannot determine the rank of the result tensor. The length of Compile
FunctionVariable$3193 in MapThread[Plus,Compile`FunctionVariable$3193] is unknown at compiling time; evaluation will use the uncompiled function. >>
Compile::cset: Variable qsum of type {_Real,1} encountered in assignment of type {_Integer,0}. >>
Edit:
Please note that the above code is a simplified/partial piece of a larger code. I presented this to show the problem area. The original code has several hundred iterations (till a condition is met) of the above critical steps and the compiled
function itself will be called several thousands of times (for direct search-based optimization).
Edit 2:
Thanks to xzczd, the following code compiles without any errors. However, it gives error/warnings during run-time. The code may look cumbersome, but the problem area is very specific.
f = With[{Kj = 150., w = 20., Vf = 100., capacity = 2500., n = 15, m = 30, p = 10, RML = 5, \[Alpha] = 1200., \[Beta] = 0., L = 1., delta = 1., dt = 4./3600., dx = 1./9.},
Module[{demand, supply, Nsupply, floExct, gamma, inflow, density}, demand = Min[#2 Vf, # capacity - #3] &; supply = Min[(# Kj - #2) w, # capacity - #3] &; Nsupply = Min[(# Kj - #2) Vf - #3 - #4, # capacity - #5] &;
floExct = Evaluate@Min[demand[#, #2, #6], Nsupply[#, #3, #4, #5, #6]] &; gamma = Evaluate@Min[1, supply[L, #2, 0]/(demand[L, #, 0] + 0.001)] &; inflow = (# - \[Beta] #2) dx &; density = (# - #2 + #3)/Vf &;
Compile[{{a1, _Integer}, {a2, _Integer}, {a3, _Integer}},
Module[{k0 = Table[0., {n}], Fk = Table[0., {5}, {n}], kr = Table[0., {n - 2}, {p}], Rk = Table[0., {4}, {n - 2}, {p}], Fq = Table[0., {4}, {n - 1}], Fin = Table[0., {4}, {n - 2}], Rq = Table[0., {4}, {n - 2}, {p}],
RMori = Table[a1 (i1 dx)^2 + a2 (i1 dx) + a3, {i1, 1, n - 2}], Shutoff = False, j = 0, \[Phi], qin, qr, qf, qsum, qrsum, RM, TT, NtwrkTT},
If[300 > Min[RMori] && Max[RMori] > 1200, Print["MR not within bounds"]; NtwrkTT = 10^20,
kr = ReplacePart[#, (\[Alpha] delta/Vf), 1] & /@ kr;
NtwrkTT = TT = Total@(Total@kr); AppendTo[Rk, kr];
While[TT > 0, TT = 0;
\[Phi] = demand[1, #[[-1]], 0] & /@ kr MapThread[gamma, {Take[k0, {2, -2}], Take[k0, {3, -1}]}];
qrsum = Join[Total@Fin, {0}];
qf = MapThread[floExct[L, #1, #2, #3, #4, #5] &, {Most@k0, Rest@(Fk[[1]]), Total@Fq, qrsum, Join[\[Phi], {0}]}];
qin = inflow[\[Phi], Most@qf];
k0 += Join[{0}, density[Most@qf, Rest@qf, qin], {0}];
qsum = Total@Rq;
RM = MapThread[Min[#1, #2] &, {RMori, MapThread[floExct[1, #1[[RML]], #2[[RML + 1]], #3[[RML]], 0, 0] &, {kr, Rk[[1]], qsum}]}];
qr = MapThread[Join[#1, {#2}, #3, {#4}] &, {MapThread[floExct[1, #1, #2, #3, 0, 0] &, {Take[#, {1, RML - 1}] & /@ kr, Take[#, {2, RML}] & /@ Rk[[1]], Take[#, {1, RML - 1}] & /@ qsum}, 2], RM,
MapThread[floExct[1, #1, #2, #3, 0, 0] &, {Take[#, {RML + 1, -2}] & /@ kr, Take[#, {RML + 2, -1}] & /@ Rk[[1]], Take[#, {RML + 1, -2}] & /@ qsum}, 2], \[Phi]}];
kr = MapThread[(#1 + #2) &, {Join[{0}, #] & /@ (density[Most@#, Rest@#, 0] & /@ qr), kr}];
TT += Total@k0; TT += Total@(Total@kr); NtwrkTT += TT; j++;
Fq = Delete[Fq, {1}]; Fin = Delete[Fin, {1}]; Rq = Delete[Rq, {1}]; Fk = Delete[Fk, {1}]; Rk = Delete[Rk, {1}];
AppendTo[Fq, qf]; AppendTo[Fin, qin]; AppendTo[Rq, qr]; AppendTo[Fk, k0]; AppendTo[Rk, kr];
Print["j: ", j];
If[#[[2]] > Kj - \[Alpha]/w, Print["Ramp Spillback"]; NtwrkTT = 10^20; Break[]] & /@ kr;
If[(Shutoff == False) && j > m, Shutoff = True; kr = ReplacePart[#, 0, 1] & /@ kr];
];
]; NtwrkTT dt], CompilationOptions -> {"InlineExternalDefinitions" -> True}]]];
when I run the compiled function with f[0,0,1100]
, it runs the While
loop only once, gives the following error:
CompiledFunction::cfse: Compiled expression {Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null} should be a machine-size real number. >>
CompiledFunction::cfex: Could not complete external evaluation at instruction 491; proceeding with uncompiled evaluation. >>
Then, it proceeds to run the program, I guess in an uncompiled fashion.
One possible variable that refers to {Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null}
may be RM
and I was wondering, if it is the source of problem.
Compile
. $\endgroup$qsum = MapThread[Plus, #] &@Rq
can be changed toqsum=Total@Rq
, 2.qsum = N[Plus @@ Fq]
can be embedded into the definition ofqf
, 3.kr = ReplacePart[#, (\[Alpha] delta/Vf), 1] & /@ kr
can be changed tokr[[All, 1]] = \[Alpha] delta/Vf
. There still exists warnings but I'd like to stop here, as I mentioned above, I don't think compiling these code makes much sense. $\endgroup$compile
or compile the external functions (demand,supply,Nsupply,floExct..etc) and call them from the main compile functionf
? $\endgroup$