naive_algorithm

advertisement
Definitions and notations
a. Let π’ž be a set of all reset contexts over the program's variables.
b. Denote 𝐺 to be a graph where each vertex is a context from π’ž.
Each context can be expressed as a set of variables, so for ease of expressiveness, instead of using 𝐺𝑖𝑗 to represent a
graph directed edge from context 𝑖 to context 𝑗, it is also possible to reference for instance 𝐺{1,3},{1,3,4} - this indicates
the directed edge from context {𝑋1 , 𝑋3 } to context {𝑋1 , 𝑋2 , 𝑋3 }.
c. Alternatively, the notation (𝑃, 𝑄) will denote the edge from context 𝑃 to context 𝑄.
d. The ⋅ operator (compositional) works on a context graph 𝐺 in the following manner:
′
For every 2 edges 𝐺𝑃,𝑄 and 𝐺𝑃′,𝑄′
in 𝐺 and 𝐺′, respectively, where 𝑄 = 𝑃′ , the result graph 𝐺′′ will hold an edge
′′
𝐺𝑃,𝑄′
such that:
′′
′
𝐺𝑃,𝑄′
= 𝐺𝑃,𝑄 ⋅ 𝐺𝑃′,𝑄′
e. Each edge holds a dependency set, and the compositional operator ⋅ works as defined for dependency sets.
′′
′
i.e. – the 𝐺𝑃,𝑄′
dependency set will be the composition the dependency sets of 𝐺𝑃,𝑄 and 𝐺𝑃′,𝑄′
in this order.
e. The βŠ” operator works on graphs edge-wise, such that provided the edge 𝑃 → 𝑄 exists on both joined graphs:
π‘ŸβŠ”π‘‘
π‘Ÿ
𝑑
𝑖→𝑗 𝑖→𝑗
𝑖→𝑗
′′
′
𝐺𝑃,𝑄
= 𝐺𝑃,𝑄 βŠ” 𝐺𝑃,𝑄
= {𝑖 → 𝑗 | 𝑖 → 𝑗 ∈ 𝐺 ′ 𝑃,𝑄 ⋀𝑖 → 𝑗 ∈ 𝐺𝑃,𝑄 } ⋃ {
|
∈ 𝐺 ′ 𝑃,𝑄 ∨
∈ 𝐺𝑃,𝑄 }
π‘˜→𝑙 π‘˜→𝑙
π‘˜→𝑙
if only one of the graphs holds the edge 𝑃 → 𝑄, the result graph will hold this exact edge. If none of the graphs holds
the edge 𝑃 → 𝑄, then this edge will be missing from the result graph.
f. For a context 𝑃, we define the symbols:
𝑃̂π‘₯,𝑦 = 𝑃 βˆ– {π‘₯} ∪ { π‘₯ |𝑖𝑓 𝑦 ∈ 𝑃}
𝑃̂π‘₯,𝑦,𝑧 = 𝑃 βˆ– {π‘₯} ∪ { π‘₯ |𝑖𝑓 𝑦 ∈ 𝑃⋀ 𝑧 ∈ 𝑃}
π‘ƒΜŒπ‘₯,𝑦,𝑧 = 𝑃 βˆ– {π‘₯} ∪ { π‘₯ |𝑖𝑓 𝑦 ∈ 𝑃 ∨ 𝑧 ∈ 𝑃}
Algorithm (ML-like, at parts):
fun analyse(Core.Cmd c, preContexts : Context list) : G =
case c of
Core.Seq(c1,c2)
=> let
val g = analyse(c1, preContexts);
val g' = analyse(c2, targetContexts1(g));
in
g βˆ™ g'
end;
|
Core.Choice(c1,c2)
=>
analyse(c1, preContexts) βŠ” analyse(c2, preContexts)
1
|
Core.Skip
=> doAssignment(1,Core.Var 1, preContexts)
|
Core.Asgn(i, e)
=> doAssignment(i, e, preContexts)
|
Core.Loop(i, c)
=> doLoop(i, c, preContexts);
targetContexts(𝐺) = the set { t | (𝑠, 𝑑) ∈ 𝐺 } , ordered into a list.
fun doAssignment (x : int, Core.Expr e, preContexts : Context list) : G =
let
fun doAssignmentInternal (x : int, Core.Expr e, PC : Context list) : G =
case e of
Core.Zero =>
1
𝑔′ π‘€β„Žπ‘’π‘Ÿπ‘’ ∀𝑃∈PC : 𝑔′𝑃,𝑃∪{π‘₯} = {𝑖 → 𝑖 | 𝑖 ∉ 𝑃 ∧ 𝑖 ≠ π‘₯}
1
1
| Core.Var y => 𝑔′ π‘€β„Žπ‘’π‘Ÿπ‘’ ∀𝑃∈PC : 𝑔′𝑃,𝑃̂π‘₯,𝑦 = {𝑦 → π‘₯ | 𝑦 ∉ 𝑃} ∪ { 𝑖 → 𝑖 | 𝑖 ∉ 𝑃 ∧ 𝑖 ≠ π‘₯}
| Core.times(Core.Var y, Core.Var z) =>
1
2
𝑔′ π‘€β„Žπ‘’π‘Ÿπ‘’ ∀𝑃∈PC : 𝑔′𝑃,𝑃̂π‘₯,𝑦,𝑧 = {𝑖 → 𝑖 | 𝑖 ∉ 𝑃 ∧ 𝑖 ≠ π‘₯} ∪ {𝑑 → π‘₯ | 𝑑 ∈ {𝑦, 𝑧} ∧ 𝑦, 𝑧 ∉ 𝑃 }
| Core.plus(Core.Var y , Core.Var z) =>
1
1
1
1+
𝑔′ π‘€β„Žπ‘’π‘Ÿπ‘’ ∀𝑃∈PC : 𝑔′𝑃,π‘ƒΜŒπ‘₯,𝑦,𝑧 = {𝑖 → 𝑖 | 𝑖 ≠ π‘₯ ∧ 𝑖 ∉ 𝑃} ∪ {𝑦 → π‘₯|𝑦 ∉ 𝑃 ∧ 𝑧 ∈ 𝑃} ∪
{𝑧 → π‘₯|𝑧 ∉ 𝑃 ∧ 𝑦 ∈ 𝑃} ∪ {𝑑 → π‘₯|𝑑 ∈ {𝑦, 𝑧} ∧ 𝑦, 𝑧 ∉ 𝑃};
val PC = if (preContexts = []) then !allContexts2 else preContexts;
val 𝑔′ = doAssignmentInternal(x,e,PC);
in
𝑔′′
π‘€β„Žπ‘’π‘Ÿπ‘’
𝑔′′𝑃,𝑄
𝑖→𝑗
={ ′
|
𝑖 → 𝑗′
𝑖, 𝑖 ′ ∉ 𝑃 ∧
π‘Ÿ1
𝑗, 𝑗 ′ ∉ 𝑄
π‘Ÿ2
∧
(𝑖 ≠ 𝑖 ′ ∨ 𝑗 ≠ 𝑗 ′ ) ∧
𝑖 → 𝑗 ∈ 𝑔′𝑃,𝑄 ∧ 𝑖 → 𝑗 ∈ 𝑔′𝑃,𝑄 ∧ π‘Ÿ1 , π‘Ÿ2 ≃ 1
} βŠ” 𝑔′𝑃,𝑄
end;
2
allContexts is a "global" Context list which includes all contexts except for the full context (which holds all program
variables).
fun doLoop(Core.Var x, c : Core.Cmd, preContexts : Context list) : G =
doLoopClosure(x, doMIterations(analyse(c, preContexts) ) );
fun lfp(F, g) =
let
val fm = (F g);
in
if (fg = g) then g
else lfp F fg
end;
fun doLoopClosure(x : int, g : G) : G =
𝑔′ π‘€β„Žπ‘’π‘Ÿπ‘’ ∀π‘ƒπ‘œ ,𝑃1 ,𝑃2 : ((𝑃0 , 𝑃1 ) ∈ 𝑔 ∧ (𝑃1 , 𝑃2 ) ∈ 𝑔) → (𝑔′ 𝑃 ,𝑃 = 𝑔𝑃0 ,𝑃1 βˆ™ 𝐿𝐢π‘₯ (𝑔𝑃1 ,𝑃1 ) βˆ™ 𝑔𝑝1 ,𝑝2 ) ;
π‘œ 2
fun doMIterations(g : G) : G =
let
val g' = ref g;
in
lfp (doSingleIteration g') g
end
fun doSingleIteration (ref g) g' : G->G =
(g := !g βŠ” g βˆ™ g'; !g)
Download