Chapel: Can you re-index a domain in place? - chapel

A great man once said, I have a matrix A. But this time she has a friend B. Like the Montagues and Capulets, they have different domains.
// A.domain is { 1..10, 1..10 }
// B.domain is { 0.. 9, 0.. 9 }
for ij in B.domain {
if B[ij] <has a condition> {
// poops
A[ij] = B[ij];
}
}
My guess is I need to reindex so that the B.domain is {1..10, 1..10}. Since B is an input, I get push back from the compiler. Any suggestions?

There's a reindex array method to accomplish exactly this, and you can create a ref to the result to prevent creating a new array:
var Adom = {1..10,1..10},
Bdom = {0..9, 0..9};
var A: [Adom] real,
B: [Bdom] real;
// Set B to 1.0
B = 1;
// 0-based reference to A -- note that Bdom must be same shape as Adom
ref A0 = A.reindex(Bdom);
// Set all of A's values to B's values
for ij in B.domain {
A0[ij] = B[ij];
}
// Confirm A is now 1.0 now
writeln(A);

chapel compiler must object,documentation is explicit and clear on this:
Note that querying an array's domain via the .domain method or the function argument query syntax does not result in a domain expression that can be reassigned. In particular, we cannot do:
VarArr.domain = {1..2*n};
In case the <has_a_condition> is non-intervening and without side-effects, a solution to the expressed will may use domain-operators similar to this pure, contiguous-domain, index translation:
forall ij in B.domain do {
if <has_a_condition> {
A[ ij(1) + A.domain.dims()(1).low,
ij(2) + A.domain.dims()(2).low
] = B[ij];
}
}

Related

Dart - General Summation Function For 'double', 'int', and 'num' Number Types

mySumFunction(myIntList) =
mySumFunction(myDoubleList) =
mySumFunction(myNumList) =
Can a single function calculate all these above? Most functions that can accept num or List<num> as an input can also accept double & int and List<double> & List<int> as inputs as well respectively. Functions involving .reduce() though appear to be some of the exceptions.
sumList(List<num> temp) {
return (temp.reduce((value, element) => (value + element)));
} //Only works with num type variables
Code fixed for Dart 2.13:
// #dart=2.13
T sumList<T extends num>(List<T> temp) {
var result = temp.reduce((value, element) => (value + element) as T);
return result;
}
void main() {
print(sumList<double>([2,3,4.5,5,6]));
}
Result:
20.5
Unless you are specifically looking for a solution using reduce, a forEach can be used compute the sum of nums ints or doubles in a function.
sum(List<num> list) {
var total = 0;
for (var x in list) {
total += x;
}
return total;
}
A shorthand for this is the fold function which is pretty much reduce with an initial value, and it solves the type issue. The following function works on nums doubles or ints.
sumByFolding(List<num> list) {
return list.fold(0, (prev, element) => prev + element);
}
Unlike the reduce function, fold is also safe to use for empty collections.
Another alternative:
sumList(List<num> temp) {
return([...temp].reduce((value, element) => value + element));
}

Variable changes on it's own in C++

I have a loop going through an array trying to find which index is a string. It should solve for what that value should be.
I can't figure out why, but as soon as the if statements start i becomes 1 which gives my code an error.
I'm not very fluent in C++.
for(int i = 0; i < 4; i++) {
if(auto value = std::get_if<std::string>(&varArr[i])) {
solvedIndex = i;
auto value0 = std::get_if<float>(&varArr[0]);
auto value1 = std::get_if<float>(&varArr[1]);
auto value2 = std::get_if<float>(&varArr[2]);
auto value3 = std::get_if<float>(&varArr[3]);
//i changes to 1 when this if starts??
if(i = 0) {
solvedVar = (*value3 / *value1) * *value2;
} else if (i = 1) {
solvedVar = *value3 / (*value0 / *value2);
} else if (i = 2) {
solvedVar = *value0 / (*value3 / *value1);
} else {
solvedVar = *value1 * (*value0 / *value2);
}
break;
}
}
Note that these variables are declared above. Also, varArr is filled with values:
std::variant<std::string, float> varArr[4];
int solvedIndex;
float solvedVar;
As has been noted, in your if statements, you are using the assignment operator (=) but want the equality comparison operator (==). For your variable i the first if statement sets i equal to 0 and if(0) is the same as if(false). So your program goes to the first else-if which sets i equal to 1 and if(1) evaluates to true. Your code then finishes the block within else if (i = 1) {...} and then ends.
That's because operator= is the assignment operator in C++ (and most languages, actually). That changes the value of the variable to the value on the other side. So, for instance:
x = 0
will change the value of x to 0. Doesn't matter if it's in an if statement. It will always change the value to 0 (or whatever the right hand side value is).
What you are looking for is operator==, which is the comparison (aka relational) operator in C++/ That asks the question "Are these two things equal?" So, for instance:
x == 0
asks is x is equal to 0.

Intersection of two BDDs using CUDD

I would like to find intersection of two BDDs for the following two Boolean functions:
F=A'B'C'D'=1
G=A XOR B XOR C XOR D=1
Here is my code:
int main (int argc, char *argv[])
{
char filename[30];
DdManager *gbm; /* Global BDD manager. */
gbm = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0); /* Initialize a new BDD manager. */
DdNode *bdd, *var, *tmp_neg, *tmp,*f,*g;
int i;
bdd = Cudd_ReadOne(gbm); /*Returns the logic one constant of the manager*/
Cudd_Ref(bdd); /*Increases the reference count of a node*/
for (i = 3; i >= 0; i--) {
var = Cudd_bddIthVar(gbm,i); /*Create a new BDD variable*/
tmp_neg = Cudd_Not(var); /*Perform NOT Boolean operation*/
tmp = Cudd_bddAnd(gbm, tmp_neg, bdd); /*Perform AND Boolean operation*/
Cudd_Ref(tmp);
Cudd_RecursiveDeref(gbm,bdd);
f = tmp;
}
for (i = 3; i >= 0; i--) {
var = Cudd_bddIthVar(gbm,i); /*Create a new BDD variable*/
tmp = Cudd_bddXor(gbm, var, bdd); /*Perform AND Boolean operation*/
Cudd_Ref(tmp);
Cudd_RecursiveDeref(gbm,bdd);
g = tmp;
}
bdd= Cudd_bddIntersect(gbm,f,g);/*Intersection between F and G */
bdd = Cudd_BddToAdd(gbm, bdd); /*Convert BDD to ADD for display purpose*/
print_dd (gbm, bdd, 2,4); /*Print the dd to standard output*/
sprintf(filename, "./bdd/graph.dot"); /*Write .dot filename to a string*/
write_dd(gbm, bdd, filename); /*Write the resulting cascade dd to a file*/
Cudd_Quit(gbm);
return 0;
}
And here is the result I got:
DdManager nodes: 7 | DdManager vars: 4 | DdManager reorderings: 0 | DdManager memory: 8949888
: 3 nodes 2 leaves 2 minterms
ID = 0xaa40f index = 0 T = 0 E = 1
0--- 1
As you can see here the intersection gives A=0 and don't cares for B,C and D. I was expecting values of A,B,C and D that satifies both F and G. But clearly A=0 is not the solution for both F and G. For example someone can choose A=0,B=1 which gives 0 for function F. What is wrong here?
This reply comes awfully late, but just to close the issue, the problem is that the last operand to both Cudd_bddAnd and Cudd_bddXor is bdd instead of f or g. Of course, both f and g should be properly initialized (the way bdd is currently initialized). Fixing the code this way will also take care of the multiple dereferences of bdd, which are going to cause grief should garbage collection kick in.
Also, Cudd_bddIntersect does not compute the AND of two BDDs, but a function that implies the AND. It's used when one wants a witness to the nonemptiness of the conjunction of two BDDs without computing the whole result (and then possibly extracting a witness from it).
Finally, bdd is used as both operand to Cudd_BddToAdd and as destination for the return value. This is guaranteed to "leak" BDD nodes.

How does that recursive function work?

Might be a very basic question but I just got stuck with it. I am trying to run the following recursive function:
//If a is 0 then return b, if b is 0 then return a,
//otherwise return myRec(a/2, 2*b) + myRec(2*a, b/2)
but it just gets stuck in infinite loop. Can anybody help me to run that code and explain how exactly that function works? I built various recursive functions with no problems but this one just drilled a hole in my head.
Thanks.
Here is what I tried to do:
#include<iostream>
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
else return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
int main()
{
if (46 == myRec(100, 100)) {
std::cout << "It works!";
}
}
Well, let us mentally trace it a bit:
Starting with a, b (a >= 2 and b >= 2)
myRec(a/2, 2*b) + something
something + myRec(2*a', b'/2)
Substituting for a/2 for a' and 2*b for b', we get myRec(2*(a/2), (b*2)/2), which is exactly where we started.
Therefore we will never get anywhere.
(Note that I have left out some rounding here, but you should easily see that with this kind of rounding you will only round down a to the nearest even number, at which point it will be forever alternating between that number and half that number)
I think you are missing on some case logic. I last program in C ages ago so correct my syntax if wrong. Assuming numbers less than 1 will be converted to zero automatically...
#include<iostream>
int myRec(int a, int b){
// Recurse only if both a and b are not zero
if (a!=0 && b!=0) {
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
// Otherwise check for any zero for a or b.
else {
if (a==0){
return b;
}
if (b==0){
return a;
}
}
}
UPDATE:
I have almost forgot how C works on return...
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
VBA equivalent with some changes for displaying variable states
Private Function myRec(a As Integer, b As Integer, s As String) As Integer
Debug.Print s & vbTab & a & vbTab & b
If a = 0 Then
myRec = b
End If
If b = 0 Then
myRec = a
End If
If a <> 0 And b <> 0 Then
myRec = myRec(a / 2, 2 * b, s & "L") + myRec(2 * a, b / 2, s & "R")
End If
End Function
Sub test()
Debug.Print myRec(100, 100, "T")
End Sub
Running the test in Excel gives this (a fraction of it as it overstacks Excel):
T: Top | L: Left branch in myRec | R: Right branch in myRec
The root cause will be the sum of the return which triggers more recursive calls.
Repeating of the original values of a and b on each branch from level 2 of the recursive tree...
So MyRec(2,2) = MyRec(1,4) + MyRec(4,1)
And MyRec(1,4) = MyRec(.5,8) + MyRec(2,2)
So MyRec(2,2) = MyRec(.5,8) + MyRec(2,2) + MyRec(4,1)
Oops.
(The .5's will actually be zeroes. But it doesn't matter. The point is that the function won't terminate for a large range of possible inputs.)
Expanding on gha.st's answer, consider the function's return value as a sum of expressions without having to worry about any code.
Firstly, we start with myRec(a,b). Let's just express that as (a,b) to make this easier to read.
As I go down each line, each expression is equivalent, disregarding the cases where a=0 or b=0.
(a,b) =
(a/2, 2b) + (2a, b/2) =
(a/4, 4b) + (a, b) + (a, b) + (4a, b/4)
Now, we see that at a non-terminating point in the expression, calculating (a,b) requires first calculating (a,b).
Recursion on a problem like this works because the arguments typically tend toward a 'base case' at which the recursion stops. A great example is sorting a list; you can recursively sort halves of the list until a list given as input has <= 2 elements, which is trivial without recursion. This is called mergesort.
However, your myRec function does not have a base case, since for non-zero a or b, the same arguments must be passed into the function at some point. That's like trying to sort a list, in which half of the list has as many elements as the entire list.
Try replacing the recursion call with:
return myRec(a/2, b/3) + myRec(a/3, b/2);

possible to index a set by a variable?

I am trying to do something that logically should be possible to do. However, I am not sure how to do this within the realm of linear programming. I am using ZMPL/SCIP, but this should be readable to most.
set I := {1,2,3,4,5};
param u[I] := <1> 10, <2> 20, <3> 30, <4> 40, <5> 50;
var a;
var b;
subto bval:
b == 2;
subto works:
a == u[2];
#subto does_not_work:
# a == u[b];
I am trying to make sure that the variable a is equal to the value at the index b in u. So for example, I ensure that b == 2 and then I try to set the constraint that a == u[b], but that does not work. It complains that I am trying to index with a variable. I am able to just do a == u[2] however, which makes a equal to 20.
Is there a way to easily access u at an index specified by a variable? Thanks for any help/guidance.
EDIT: I think the consensus is that this is not possible because it no longer becomes an LP. In that case, can anyone think of another way to write this so that, depending on the value of b, I can get an associated value from the set u? This would have to avoid directly indexing it.
SOLUTION: Based on the response from Ram, I was able to try it out and found that it was definitely a viable and linear solution. Thanks, Ram! Here is sample solution code in ZMPL:
set I := {1,2,3,4,5};
param u[I] := <1> 10, <2> 20, <3> 30, <4> 40, <5> 50;
var a;
var b;
var y[I] binary;
subto bval:
b == 4;
subto only_one:
sum <i> in I : y[i] == 1;
subto trick:
b == (sum <i> in I : y[i] * i);
subto aval:
(sum <i> in I : u[i]*y[i]) == a;
Yes, you can rewrite and linearize your constraints, by introducing a few extra 0/1 variables (indicator variables). These kinds of tricks are not uncommon in Integer Programming.
Constraints In English
b can take on values from 1 through 5. b = {1..5}
and depending on b's value, the variable a should become u[b]
Indicator Variables
Let's introduce 5 Y variables - Y1..Y5 (one for each possible value of b)
Only one of them can be true at any given time.
Y1 + Y2 + Y3 + Y4 + Y5 = 1
All Y's are binary {0,1}
Here's the trick. We introduce one linear constraint to ensure that the corresponding Y variable will take on value 1, only when b is that value.
b - 1xY1 - 2xY2 - 3xY3 - 4xY4 - 5xY5 = 0
(For example, if b is 3, the constraint above will force Y3 to be 1.)
Now, we want a to take on the value u[b].
a = u[1]xY1 + u[2]xY2 + u[3]xY3 + u[4]xY4 + u[5]xY5
Since u[ 1] ...u[5] are constants known beforehand, the constraint above is also linear.
Here is one reference on these kinds of IF-THEN conditions in Integer Programming. Many of these tricks involve the Big-M, though we didn't need it in this case.
Hope that helps you move forward.