`forall` expression: parallel or serial calculation? - chapel

My understanding of forall statements is that they are executed in parallel, while for statements are executed in serial. Indeed, the following code seems to confirm this expectation (i.e., a random sequence only for forall because of threading):
for i in 1..5 do writeln( i * 10 );
10
20
30
40
50
forall i in 1..5 do writeln( i * 10 );
10
50
20
30
40
On the other hand, if I use forall (or equivalent [...]) on the right-hand side as an expression
var A = ( forall i in 1..5 do i * 10 );
var B = [ i in 1..5 ] i * 10;
var X = ( forall a in A do a );
var Y = [ a in A ] a;
var P = ( for i in 1..5 do i * 10 ); // for comparison
writeln( "A = ", A );
writeln( "B = ", B );
writeln( "X = ", X );
writeln( "Y = ", Y );
writeln( "P = ", P );
all the results become the same (i.e., ordered from 10 to 50):
A = 10 20 30 40 50
B = 10 20 30 40 50
X = 10 20 30 40 50
Y = 10 20 30 40 50
P = 10 20 30 40 50
Does this mean that forall expressions on the right-hand side of assignment are always executed in serial? If so, is the corresponding [...] also equivalent to for expressions in this context?

Good question. You're correct that using forall expressions ( explicit or []-"bracketed" ) in this way generates deterministic results, but the forall expression does still result in a parallel execution.
Expressions like yours effectively result in a zippered iteration, which is defined such that corresponding iterations will match up. For example, in chapel, seeming "whole-array" operations like:
var A, B, C: [1..10] real;
A = B + C;
are equivalent ( promoted ) to an execution of a zippered forall loop:
var A, B, C: [1..10] real;
forall (a, b, c) in zip(A, B, C) do
a = b + c;
Both of these expressions : (a) specify parallel execution,(b) ensure that corresponding elements of A, B, and C arrays are used within each instance of the loop body (otherwise the language would not be very useful).
Taking one of your examples,
...B = [ i in 1..5 ] i * 10...
is equivalent to:
forall (b, v) in zip(B, [i in 1..5] i * 10) do
b = v;
or:
forall (b, i) in zip(B, 1..5) do
b = i * 10;
and similarly for the other variations you provided.
This is accomplished in Chapel by using a concept known as leader-follower iterators. These were originally described in a paper published at PGAS 2011 named User-Defined Parallel Zippered Iterators in Chapel whose slides are here. They are also described in a Chapel primer on parallel iterators.

Related

Difference between "for" and "forall" on the right-hand side of assignment

In the following code, I am assigning some dummy (test) values to all the elements of a 2-dimensional array (a[][]) and then checking whether the array is filled as expected. When using the line (A), the code works as expected (i.e., it prints "passed").
proc test()
{
const N = 1000;
var a: [1..N, 1..3] real = (for m in 1 .. (3 * N) do (1.0 / m)); // (A)
// var a: [1..N, 1..3] real = [m in 1 .. (3 * N)] (1.0 / m); // (B)
// var a: [1..N, 1..3] real = forall m in 1 .. (3 * N) do (1.0 / m); // (C)
var m = 0;
for i in 1 .. N {
for k in 1 .. 3 {
m += 1;
assert( abs( a[i, k] - 1.0 / m ) < 1.0e-10 );
}
}
writeln("passed");
}
test();
On the other hand, if I use line (B) or (C) instead of (A), the code gives this error:
test.chpl:7: error: iteration over a range with multi-dimensional iterator
I am wondering what is the meaning of this error message? (My expectation is that the right-hand side of the assignment is evaluated first, i.e., a temporary array is created in parallel and assigned to the left-hand side. But is this expectation not correct?)
(I am also wondering whether it is valid to assign a one-dimensional array to a two-dimensional array (as in line (A)) without reshape...?)

What happens when you call a function with different arguments

I am practising an old assignment that I never managed to understand. I understand and get the correct output until '3, 11'. After that comes a = f2(b, c). What I don't understand is, f2 is normally defined as f2(c,a). I tried changing all c to b and all a to c in f2, but when I get to the step b = f1(c) (which is now b = f1(b), and then replace all a in f1 with b, I don't get the correct output with show(a, b) in the f1 function. The output should be a = 10 and b = 6, but since I've replaced all the a's, there is not an a left. I have no clue what I should be doing at the a = f2(b, c) step. Could someone please explain the further steps in order to reach the last 3 correct outputs?
The assignment: (sorry for the bad spacing, I can't manage to paste it properly, it pastes as one whole long line)
a = 3
b = 4
def show (x, y):
print ‘%d, %d’ % (x, y)
def f1 (a):
global b
a *= 2
b += 1
c = a + b
show(a, b)
return c
def f2 (c, a):
a += 3
b = f1(c)
show(c, b)
c = a + b
return c
show(a, b)
c = f1(a)
show(a, c)
a = f2(b, c)
show(a, b)
What will be printed when this program is executed?
The desired output:
3, 4
6, 5
3, 11
10, 6
5, 16
30, 6

Overload Conflict in SML/NJ

I have the following code to compute the Hofstadter H Sequence, but I am getting an overload conflict error message. I am fairly new to SML therefore i am sure what the error is referring to.
(* Hofstadter H-Sequence *)
fun H(0) = [0]
| H(n) = if n = 0 then [0] else x :: (n - H(H(H(n - 1))));
My goal is to insert the value of each iteration into a list and display it.
Ex: H 10; -->[1, 1, 2, 3, 4, 4, 5, 5, 6, 7]
You're trying to write a function with the type int -> int list.
(It's a good idea to think about the types while writing, even though SML will infer them. A good type system is like autofocus for the mind.)
You can't subtract the result of this function from a number (n - H(...)) since it is a list, nor can you pass a list to to this function – H(H(n - 1)) – since it wants a number.
(And where did the first element, x, come from?)
Start simple, with a function that's just the definition of H(n):
fun H 0 = 0
| H n = n - H(H(H(n-1)))
Test:
- H 0;
val it = 0 : int
- H 1;
val it = 1 : int
- H 2;
val it = 1 : int
- H 4;
val it = 3 : int
Then use that to build a list incrementally.
This variant uses a locally defined helper function that uses the current index and a counter:
fun H_seq n = let fun H_seq' m e =
if m < e
then (H m) :: (H_seq' (m+1) e)
else []
in
H_seq' 0 n
end;
Example:
- H_seq 10;
val it = [0,1,1,2,3,4,4,5,5,6] : int list
This is pretty inefficient, but fixing that is part of the more advanced course...

Range Update - Range Query using Fenwick Tree

http://ayazdzulfikar.blogspot.in/2014/12/penggunaan-fenwick-tree-bit.html?showComment=1434865697025#c5391178275473818224
For example being told that the value of the function or f (i) of the index-i is an i ^ k, for k> = 0 and always stay on this matter. Given query like the following:
Add value array [i], for all a <= i <= b as v Determine the total
array [i] f (i), for each a <= i <= b (remember the previous function
values ​​clarification)
To work on this matter, can be formed into Query (x) = m * g (x) - c,
where g (x) is f (1) + f (2) + ... + f (x).
To accomplish this, we
need to know the values ​​of m and c. For that, we need 2 separate
BIT. Observations below for each update in the form of ab v. To
calculate the value of m, virtually identical to the Range Update -
Point Query. We can get the following observations for each value of
i, which may be:
i <a, m = 0
a <= i <= b, m = v
b <i, m = 0
By using the following observation, it is clear that the Range Update - Point Query can be used on any of the BIT. To calculate the value of c, we need to observe the possibility for each value of i, which may be:
i <a, then c = 0
a <= i <= b, then c = v * g (a - 1)
b <i, c = v * (g (b) - g (a - 1))
Again, we need Range Update - Point Query, but in a different BIT.
Oiya, for a little help, I wrote the value of g (x) for k <= 3 yes: p:
k = 0 -> x
k = 1 -> x * (x + 1) / 2
k = 2 -> x * (x + 1) * (2x + 1) / 6
k = 3 -> (x * (x + 1) / 2) ^ 2
Now, example problem SPOJ - Horrible Queries . This problem is
similar issues that have described, with k = 0. Note also that
sometimes there is a matter that is quite extreme, where the function
is not for one type of k, but it could be some that polynomial shape!
Eg LA - Alien Abduction Again . To work on this problem, the solution
is, for each rank we make its BIT counter m respectively. BIT combined
to clear the counters c it was fine.
How can we used this concept if:
Given an array of integers A1,A2,…AN.
Given x,y: Add 1×2 to Ax, add 2×3 to Ax+1, add 3×4 to Ax+2, add 4×5 to
Ax+3, and so on until Ay.
Then return Sum of the range [Ax,Ay].

Kleene Closure for infinite subset

Let L = {an | n >= 0}, where and for all n >= 1.
Thus L consists of sequences of a of all lengths, including a sequence
of length 0. Let L2 be any infinite subset of L. I need to show there always exists a DFA to recognize (L2)*.
If L2 is a finite subset it is very obvious as L2 would be a DFA and hence by kleene closure L2* would be recognized by a DFA. But I am unable to get it for infinite subset as L2 may not be expressed as DFA for eg length of strings is prime.
Approach
While there exists a DFA to describe a set L of all strings an, n >= 0, there is no guarantee that a DFA exists for all subsets of L. The subset of L which contains all strings whose length is prime, as you have mentioned, is one example where a DFA the describes the language does not exist.
The correct approach would be to directly prove that (L')* is a regular language for any subset L' of L.
Definition
Let us define GCD(K) = GCDw ∈ K, |w| > 0 (|w|), where K is any non-empty subset of L. We can now refer to the greatest common divisor of all the lengths of all non-empty words in a language K as GCD(K). This definition applies for both finite and infinite subset of L.
Similarly, we can define LCM(K) = LCMw ∈ K, |w| > 0 (|w|), where K is any non-empty and finite subset of L.
Proof
We will try to prove that when GCD(L') = 1, there exists a number M such that all string an, n >= M belongs to the language (L')*. This leads to (L')* being a regular language, since we can construct a regular expression of the form:
All strings of length less than M and belongs to (L')*
OR
All strings of length more than or equal to M
The regular expression above has a corresponding DFA which has M + 1 states.
When GCD(L') > 1, we can reduce the problem to the case of GCD = 1 by "dividing" all words in the subset L' by GCD(L').
If GCD(L') = 1 (set-wise coprime), there exists a finite subset S of L' where GCD of the length of all strings in S is also 1.
We can prove the claim above by construction.
Pick any element w1 from L', |w1| > 0 and construct set S1 = {w1}
If GCD(Sn) = 1, Sn is the set we want to find.
If GCD(Sn) > 1, pick an element wn+1 from L' and construct set Sn+1 = {wn+1} ∪ Sn, so that
GCD(Sn+1) < GCD(Sn)
If GCD(Sn) > 1, there always exists an element from set L' that decreases the GCD when we add it to the set; otherwise, the GCD of the set L' cannot be 1. And since the length of the first element w1 has finite number of factors, the size of the final set S is finite.
Back to the problem, for any subset L' of L, we can find a finite subset S of L', which satisfies GCD(L') = GCD(S). From the set S, we can construct a generalized linear Diophantine equation with |S| unknowns ai:
a1|w1| + a2|w2| + ... + a|S||w|S|| = c where c is a non-negative integer
Since GCD(S) = 1, the equation above is always solvable, by recursively applying the solution to the simplest form of linear Diophantine equation ax + by = c.
Solve the generalized Diophantine equations above for c = 0 to (LCM(S) - 1). The solutions (a1, a2, ..., a|S|) can contain negative numbers. However, we can keep adding multiples of LCM(S) to both sides of the equations until all the solutions contain only non-negative numbers.
Let k be the smallest multiple of LCM(S) so that all Diophantine equations for c = k * LCM(S) + q, q = 0 to (LCM(S) - 1) has non-negative solution. Then we can define M as k * LCM(S), since any strings whose length larger than M can be decomposed as concatenation of words in S (thus in L').
Example calculation based on the proof
Suppose L' is set of all strings in L whose length is prime.
Let us construct set S = {a2, a5}. S can be {a2, a19} or {a5, a23}, doesn't really matter. The final value of M might be different, but it doesn't affect the fact that (L')* is regular language.
We need to solve 10 equations (separately):
2a1 + 5a2 = 0 => (a1, a2) = (0, 0)
2a1 + 5a2 = 1 => (a1, a2) = (3, -1)
2a1 + 5a2 = 2 => (a1, a2) = (1, 0)
2a1 + 5a2 = 3 => (a1, a2) = (-1, 1)
2a1 + 5a2 = 4 => (a1, a2) = (2, 0)
2a1 + 5a2 = 5 => (a1, a2) = (0, 1)
2a1 + 5a2 = 6 => (a1, a2) = (3, 0)
2a1 + 5a2 = 7 => (a1, a2) = (1, 1)
2a1 + 5a2 = 8 => (a1, a2) = (4, 0)
2a1 + 5a2 = 9 => (a1, a2) = (2, 1)
Add one LCM(2,5) = 10. Note that we can modify the solution directly without solving again, due to the property of LCM:
2a1 + (5a2 + 10) = 1 + 10 => (a1, a2) = (3, 1)
(2a1 + 10) + 5a2 = 3 + 10 => (a1, a2) = (4, 1)
Since all the solutions are non-negative, and we only add one LCM(2,5), M = 10.
The regular expression for (L')* can be constructed:
a2+a4+a5+a6+a7+a8+a9+a10a*
The regular expression is not very compact, but it is not our concern here. For the sake of the proof, we only need to know there exists a number M so that an belongs to (L')* for all n >= M, which implies that there are finite number of states and a DFA can be constructed.