How to prevent unnecessary event detection in Modelica? - modelica

How can I achieve event detection for y>1 in the S1=... statement only when S2 is true and otherwise prevent it since it only slows down simulation in the general case?
model zeroCrossingTest
// BOOLEAN VARIABLE DECLARATIONS
Boolean S1(start=true, fixed=true);
Boolean S2(start=false, fixed=true);
Boolean S3(start=false, fixed=true);
Real y;
equation
der(y) = -y + 2;
// =================
// TRANSITIONS START
S1 = if pre(S2) then (y>1) else
if pre(S1) then not ( (y>0.2) )
else false;
S2 = if pre(S1) then (y>0.2) else
if pre(S2) then not ( (y>0.5) or (y>1) )
else false;
S3 = if pre(S2) then (y>0.5) else
pre(S3);
end zeroCrossingTest;
The zero crossing from S1 = if pre(S2) then (y>1).. is still computed in OpenModelica (state event at time=0.69), although pre(S2) is false
UPDATE1: Alternative Implementation which does not generate unnecessary events.. thanks #marco
model zeroCrossingTest_OriginalImplementation
// BOOLEAN VARIABLE DECLARATIONS
Boolean S1(start = true, fixed = true);
Boolean S2(start = false, fixed = true);
Boolean S3(start = false, fixed = true);
Real y;
equation
der(y) = -y + 2;
// =================
// TRANSITIONS START
S1 = pre(S2) and y>1 or
pre(S1) and not y>0.2;
S2 = pre(S1) and y>0.2 or
pre(S2) and not ( y>0.5 or y>1 );
S3 = pre(S2) and y>0.5 or
pre(S3);
end zeroCrossingTest_OriginalImplementation;
UPDATE2: a more complex model, which gives the same behaviour of the boolean variables generates unnecessary state events (for y>0.7, y>0.8):
model zeroCrossingTest_OriginalImplementation
Boolean S1(start=true, fixed=true);
Boolean S2(start=false, fixed=true);
Boolean S3(start=false, fixed=true);
Boolean S4(start=false, fixed=true);
Boolean S5(start=false, fixed=true);
Boolean S6(start=false, fixed=true);
Real y;
equation
der(y) = -y + 2;
// =================
// TRANSITIONS START
S1 = pre(S2) and (y>1) or
pre(S6) and (y>0.8) or
pre(S1) and not ( (y>0.2) );
S2 = pre(S1) and (y>0.2) or
pre(S2) and not ( (y>0.5) or (y>1) or (y>0.6) );
S3 = pre(S2) and (y>0.5) or
pre(S3);
S4 = pre(S2) and (y>0.6) or
pre(S4) and not ( (y>0.65) );
S5 = pre(S4) and (y>0.65) or
pre(S5) and not ( (y>0.7) );
S6 = pre(S5) and (y>0.7) or
pre(S6) and not ( (y>0.8) );
end zeroCrossingTest_OriginalImplementation;
UPDATE 3: This implementation generates only the necessary events (2 events in total). Any reason against this approach?
model zeroCrossingTest_OriginalImplementation
Boolean S1(start=true, fixed=true);
Boolean S2(start=false, fixed=true);
Boolean S3(start=false, fixed=true);
Boolean S4(start=false, fixed=true);
Boolean S5(start=false, fixed=true);
Boolean S6(start=false, fixed=true);
Real inS1;
Real inS2;
Real inS3;
Real inS4;
Real inS5;
Real inS6;
Real y;
equation
der(y) = -y + 2;
// =====================
// inState Variables
inS1= if pre(S1) then 1 else 0;
inS2= if pre(S2) then 1 else 0;
inS3= if pre(S3) then 1 else 0;
inS4= if pre(S4) then 1 else 0;
inS5= if pre(S5) then 1 else 0;
inS6= if pre(S6) then 1 else 0;
// =================
// TRANSITIONS START
S1 = pre(S2) and (inS2*y>1) or
pre(S6) and (inS6*y>0.8) or
pre(S1) and not ( (inS1*y>0.2) );
S2 = pre(S1) and (inS1*y>0.2) or
pre(S2) and not ( (inS2*y>0.5) or (inS2*y>1) or (inS2*y>0.6) );
S3 = pre(S2) and (inS2*y>0.5) or
pre(S3);
S4 = pre(S2) and (inS2*y>0.6) or
pre(S4) and not ( (inS4*y>0.65) );
S5 = pre(S4) and (inS4*y>0.65) or
pre(S5) and not ( (inS5*y>0.7) );
S6 = pre(S5) and (inS5*y>0.7) or
pre(S6) and not ( (inS6*y>0.8) );
end zeroCrossingTest_OriginalImplementation;

I am no OpenModelica expert and I don't know why S1 generates and event at 0.69s in OpenModelica (but not in Dymola, as Markus A. already noted).
But in this case the unnecessary event can be prevented by moving the y > 1 comparison into the if condition:
S1 = if pre(S2) and y > 1 then true
else if pre(S1) and not y > 0.2 then true
else false;
Note that I removed most braces by considering the precedence of operators.
You could also remove the else if branch:
S1 = if pre(S2) and y > 1 or
pre(S1) and not y > 0.2
then true
else false;
Since the comparison already returns true or false, we can remove the if and simply write:
S1 = pre(S2) and y > 1 or
pre(S1) and not y > 0.2;

Related

A minizinc function that checks the neighbors for every element in an n*n matrix

I am trying to search for every neighbor of an element of a n*n matrix in minizinc. So far i use very in efficient way where i have if-else for the whole matrix and separate conditions to handle the boundary variables. I am kinda new to minizinc and I was hoping if there is a n efficient way to do this. maybe with a function or something.
int: size; % Enter the size lads
set of int: board = 0..size-1;
array[board,board] of var 0..1: grid;
var int: z = sum(r in board, c in board) (grid[r,c]);
% solve maximize z;
solve :: int_search(
[grid[i,j] | i,j in board],
smallest,
indomain_max,
complete)
maximize z;
constraint
forall(r in board,c in board,x in board) (
if (r==0/\c==0) then %corner 1
(
if ( (grid[r,c+1] + grid[r+1,c+1]+grid[r,c+1])==3) then (grid[r,c] = 1)
elseif(
(grid[r,c+1] + grid[r+1,c+1]+grid[r,c+1]) ==2)then(grid[r,c] = grid[r,c])
else grid[r,c]=0 endif
)
elseif (r==size-1/\c==size-1) then %corner2
( if ((grid[r-1,c]+grid[r,c-1]+grid[r-1,c-1])==3) then (grid[r,c] = 1)
elseif((grid[r-1,c]+grid[r,c-1]+grid[r-1,c-1]) ==2) then (grid[r,c] = grid[r,c])
else (grid[r,c] = 0) endif
)
elseif (r==0/\c==size-1) then %corner3
( if( (grid[r,c-1]+grid[r+1,c]+grid[r+1,c-1])==3) then (grid[r,c] = 1)
elseif((grid[r,c-1]+grid[r+1,c]+grid[r+1,c-1]) ==2)then (grid[r,c] = grid[r,c])
else(grid[r,c] = 0) endif
)
elseif (r==size-1/\c==0) then %corner4
( if((grid[r-1,c]+grid[r,c+1]+grid[r-1,c+1])==3) then (grid[r,c] = 1)
elseif((grid[r-1,c]+grid[r,c+1]+grid[r-1,c+1]) ==2) then (grid[r,c] = grid[r,c])
else(grid[r,c] = 0) endif
)
elseif (r==0/\c==x/\c!=0/\c!=size-1) then %top row
( if((grid[r,c-1]+grid[r+1,c-1]+grid[r+1,c]+grid[r+1,c+1]+grid[r,c+1])==3) then (grid[r,c] = 1)
elseif((grid[r,c-1]+grid[r+1,c-1]+grid[r+1,c]+grid[r+1,c+1]+grid[r,c+1])==2 ) then (grid[r,c] = grid[r,c])
else(grid[r,c] = 0) endif
)
elseif (r==size-1/\c==x/\c!=0/\c!=size-1) then %last row
( if((grid[r,c-1]+grid[r-1,c-1]+grid[r-1,c]+grid[r-1,c+1]+grid[r,c+1])==3) then (grid[r,c] = 1)
elseif((grid[r,c-1]+grid[r-1,c-1]+grid[r-1,c]+grid[r-1,c+1]+grid[r,c+1]) ==2 ) then (grid[r,c] = grid[r,c])
else(grid[r,c] = 0) endif
)
elseif (r==x/\c==0/\r!=0/\r!=size-1) then %first col
( if ((grid[r-1,c]+grid[r-1,c+1]+grid[r,c+1]+grid[r+1,c+1]+grid[r+1,c])==3) then (grid[r,c] = 1)
elseif((grid[r-1,c]+grid[r-1,c+1]+grid[r,c+1]+grid[r+1,c+1]+grid[r+1,c]) ==2) then (grid[r,c] = grid[r,c])
else (grid[r,c] = 0) endif
)
elseif (r==x/\c==0/\r!=0/\r!=size-1) then %last col
( if((grid[r-1,c]+grid[r-1,c-1]+grid[r,c-1]+grid[r+1,c-1]+grid[r+1,c])==3) then (grid[r,c] = 1)
elseif((grid[r-1,c]+grid[r-1,c-1]+grid[r,c-1]+grid[r+1,c-1]+grid[r+1,c]) ==2)then(grid[r,c] = grid[r,c])
else(grid[r,c] = 0) endif
)
elseif (r!=0 /\ c!=x) /\ (r!=size-1/\c!=x)/\(r!=x/\c!=0)/\(r!=x/\c!=size-1) then %rest
(if(( grid[r-1,c-1] + grid[r-1,c] + grid[r-1,c+1] +
grid[r,c-1] + grid[r,c+1] +
grid[r+1,c-1] + grid[r+1,c] + grid[r+1,c+1]
)==3)then(grid[r,c] = 1)
elseif (( grid[r-1,c-1] + grid[r-1,c] + grid[r-1,c+1] +
grid[r,c-1] + grid[r,c+1] +
grid[r+1,c-1] + grid[r+1,c] + grid[r+1,c+1]
)==2 )then (grid[r,c] = grid[r,c])
else(grid[r,c] = 0)
endif
) /\ %endif
if (grid[r,0]==1 /\ grid[r+1,0]==1) then grid[r+2,0]=0 endif /\
if (grid[0,c]==1 /\ grid[0,c+1]==1) then grid[0,c+2]=0 endif /\
if (grid[size-1,c]==1 /\ grid[size-1,c+1]==1) then grid[size-1,c+2]=0 endif /\
if (grid[r,size-1]==1 /\ grid[r+1,size-1]==1) then grid[r+2,size-1]=0 endif
else r=r/\c=c
endif
)
/\
forall(r in board,c in board)(
if (grid[r,0]==1 /\ grid[r+1,0]==1) then grid[r+2,0]=0 endif /\
if (grid[0,c]==1 /\ grid[0,c+1]==1) then grid[0,c+2]=0 endif /\
if (grid[size,c]==1 /\ grid[size,c+1]==1/\ c<size-2/\c>1) then grid[size-1,c+2]=0 endif /\
if (grid[r,size]==1 /\ grid[r+1,size]==1 /\ r<size-2/\r>1) then grid[r+2,size-1]=0 endif
)
;
output [
if j = 0 then "\n" else " " endif ++
show(grid[i,j])
| i,j in board
]
;
Here is a general approach of summing the neighbors of the cells (and not including "this" cell). For each cell it defines a temporary variable (t) which sums the values of the neighbor cells. You then have to add the logic for different values of t.
int: r = 4; % rows
int: c = 4; % column
array[1..r, 1..c] of var 0..1: x;
constraint
forall(i in 1..r, j in 1..c) (
let {
var 0..r*c: t
}
in
t = sum(a,b in {-1,0,1} where
i+a in 1..r /\ j+b in 1..c % ensure we are in the matrix
/\ (a != 0 \/ b != 0) % don't include "this" cell
) (x[i+a,j+b])
)
;
solve satisfy;
Update: Here's the same model with a function sum_neighbors which calculates the number of neighbors of the specific cells.
int: r = 4; % rows
int: c = 4; % column
array[1..r, 1..c] of var 0..1: x;
function var int: sum_neighbors(int: i,int: j) =
sum(a,b in {-1,0,1} where
i+a in 1..r /\ j+b in 1..c /\ (a != 0 \/ b != 0)
) (x[i+a,j+b])
;
constraint
forall(i in 1..r, j in 1..c) (
let {
var 0..r*c: t
}
in
t = sum_neighbors(r,c)
)
;
solve satisfy;
You don't have to use the temporary t variable, I added it just to be able to test the model. You can now write stuff like
constraint
forall(i in 1..r, j in 1..c) (
if sum_neighbors(r,c) == 2 then
% ...
else
% ...
endif
)
;

How can I find the value of s1 and s2 such that from 1:5000 & 5001:10000 the values should be different?

This is my code:
% Initial values
x0 = 0.5;
y0 = 0.6;
dt = 0.01;
time = 100; % time
num_iteration = ceil(time / dt);
num_trajectory = 10000; % Number of trajectories
c = 1; % constant
y = zeros(num_trajectory, num_iteration) + y0;
x = zeros(num_trajectory, num_iteration) + x0;
s1 = zeros(1, num_trajectory);
s2 = zeros(num_trajectory);
for t = 1:5000 % iteration
s1 = 2*x(:, t).^2./(y(:, t) + x(:, t) + c);
s2 = 2*y(:, t);
end
for t1 = 5000:10000 % iteration
s1 = x(:, t1)./y(:, t1);
s2 = y(:, t1);
end
I was unable to find s1 and s2 such that: for 1:5000, s1 and s2 will have a value say, (0.7, 0.4) respectively, and from 5001:10000 s1 and s2 will also have a different value. Overall the vectors s1 and s2 should show some changes as the time t changes.
How can I find such values?

MATLAB: Inputting enough arguments, still getting a "not enough input arguments" error

I'm having problems with the class constructor for my CoaxLine class. I pass it all the arguments it needs, but when I create an object in another program, I get the error:
Error using length Not enough input arguments.
Error in CoaxLine (line 23) function obj = CoaxLine(pow,len,h,freq,x1,x2,y1,y2,dir,split)
Error in Test2 (line 38) coax1 = CoaxLine(3.9,100,4.75,1800,10,110,10,10,0,1);
I got this same error with length even when I removed all the argument requirements for the constructor, and created the object with no inputs. This is my first time building a class in MATLAB, so it is likely that I missed something silly. I appreciate the help.
Here is the code for CoaxLine:
classdef CoaxLine
%UNTITLED2 Summary of this class goes here
% Detailed explanation goes here
properties
%Default values
PA = 3.9;
orientation = 0; %0 for East-West, 1 for North-South
splitter = 1; %0 for left side, 1 for right side
length = 90;
frequency = 1800; %in MHz
height = 4.75;
Ce = 8.77; %Hardcoded for now
Lint = .13; %Hardcoded
nearFieldLength = 2*(length^2)/((3.0*10^8)/(frequency*10^6));
X1 = 10; %Will be points in the simulation axis
X2 = 110;
Y1 = 10;
Y2 = 10;
%loss = 10;
end
methods
function obj = CoaxLine(pow,len,h,freq,x1,x2,y1,y2,dir,split)
%if nargin > 0
obj.PA = pow;
obj.length = len;
obj.height = h;
obj.frequency = freq;
obj.X1 = x1;
obj.X2 = x2;
obj.Y1 = y1;
obj.Y2 = y2;
obj.orientation = dir;
obj.splitter = split;
%end
end
function r = contribution(px,py)
if(obj.orientation == 0)
if(obj.splitter)
if(abs(py - obj.Y1) <= obj.nearFieldLength && px > obj.X1 && px < obj.X2)
H = abs(py - obj.Y1);
x = px - obj.X1;
r = NearFieldPropagation(obj.PA,obj.length,obj.frequency,H,obj.height,obj.Ce,obj.Lint,x);
end
else
if(abs(py - obj.Y1) <= obj.nearFieldLength && px < obj.X1 && px > obj.X2)
H = abs(py - obj.Y1);
x = obj.X1 - px;
r = NearFieldPropagation(obj.PA,obj.length,obj.frequency,H,obj.height,obj.Ce,obj.Lint,x);
end
end
%else
end
end
end
end
The error stems from this line:
nearFieldLength = 2*(length^2)/((3.0*10^8)/(frequency*10^6));
MATLAB thinks that you're trying to call the function length. That requires an argument whose length will be returned.
The use of frequency will give you headaches too. To properly handle this kind of properties you should declare your nearFieldLength as Dependent: http://www.mathworks.com/help/matlab/matlab_oop/access-methods-for-dependent-properties.html and then write a getter for it that will calculate its value on the fly.
Also, as excaza noted, you'll have further errors because you don't declare obj as argument in contribution.
This is my idea on how the code should look like:
classdef CoaxLine
properties
PA = 3.9;
orientation = 0;
splitter = 1;
length = 90;
frequency = 1800;
height = 4.75;
Lint = .13;
X1 = 10;
X2 = 110;
Y1 = 10;
Y2 = 10;
end;
properties(Dependent, SetAccess=private)
Ce;
nearFieldLength;
end;
methods
%//Constructor
function obj = CoaxLine(pow,len,h,freq,x1,x2,y1,y2,dir,split)
if nargin > 0
obj.PA = pow;
obj.length = len;
obj.height = h;
obj.frequency = freq;
obj.X1 = x1;
obj.X2 = x2;
obj.Y1 = y1;
obj.Y2 = y2;
obj.orientation = dir;
obj.splitter = split;
end;
end;
%//Getters for dependent properties
function val = get.Ce(obj) %#ok<MANU>
val = 8.77; %//this can be changed later
end;
function val = get.nearFieldLength(obj)
val = 2*(obj.length^2)/(3E8/(obj.frequency*1E6));
end;
%//Normal methods
function r = contribution(obj, px, py)
r = []; % some default value
if obj.orientation == 0
if obj.splitter
if abs(py - obj.Y1) <= obj.nearFieldLength ...
&& px > obj.X1 ...
&& px < obj.X2
H = abs(py - obj.Y1);
x = px - obj.X1;
r = NearFieldPropagation(obj.PA,obj.length,obj.frequency,H,obj.height,obj.Ce,obj.Lint,x);
end;
else
if abs(py - obj.Y1) <= obj.nearFieldLength ...
&& px < obj.X1 ...
&& px > obj.X2
H = abs(py - obj.Y1);
x = px - obj.X1;
r = NearFieldPropagation(obj.PA,obj.length,obj.frequency,H,obj.height,obj.Ce,obj.Lint,x);
end;
end;
end;
end;
end;
end

Best Way to Add 3 Numbers (or 4, or N) in Java - Kahan Sums?

I found a completely different answer to this question, the whole original question makes no sense anymore. However, the answer way be useful, so I modify it a bit...
I want to sum up three double numbers, say a, b, and c, in the most numerically stable way possible.
I think using a Kahan Sum would be the way to go.
However, a strange thought occured to me: Would it make sense to:
First sum up a, b, and c and remember the (absolute value of the) compensation.
Then sum up a, c, b
If the (absolute value of the) compensation of the second sum is smaller, use this sum instead.
Proceed similar with b, a, c and other permutations of the numbers.
Return the sum with the smallest associated absolute compensation.
Would I get a more "stable" Addition of three numbers this way? Or does the order of numbers in the sum have no (use-able) impact on the compensation left at the end of the Summation? With (use-able) I mean to ask whether the compensation value itself is stable enough to contain Information that I can use?
(I am using the Java programming language, although I think this does not matter here.)
Many thanks,
Thomas.
I think I found a much more reliable way to solve the "Add 3" (or "Add 4" or "Add N" numbers problem.
First of all, I implemented my idea from the original post. It resulted into quite some big code which seemed, initially, to work. However, it failed in the following case: add Double.MAX_VALUE, 1, and -Double.MAX_VALUE. The result was 0.
#njuffa's comments inspired me dig somewhat deeper and at http://code.activestate.com/recipes/393090-binary-floating-point-summation-accurate-to-full-p/, I found that in Python, this problem has been solved quite nicely. To see the full code, I downloaded the Python source (Python 3.5.1rc1 - 2015-11-23) from https://www.python.org/getit/source/, where we can find the following method (under PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2):
static PyObject*
math_fsum(PyObject *self, PyObject *seq)
{
PyObject *item, *iter, *sum = NULL;
Py_ssize_t i, j, n = 0, m = NUM_PARTIALS;
double x, y, t, ps[NUM_PARTIALS], *p = ps;
double xsave, special_sum = 0.0, inf_sum = 0.0;
volatile double hi, yr, lo;
iter = PyObject_GetIter(seq);
if (iter == NULL)
return NULL;
PyFPE_START_PROTECT("fsum", Py_DECREF(iter); return NULL)
for(;;) { /* for x in iterable */
assert(0 <= n && n <= m);
assert((m == NUM_PARTIALS && p == ps) ||
(m > NUM_PARTIALS && p != NULL));
item = PyIter_Next(iter);
if (item == NULL) {
if (PyErr_Occurred())
goto _fsum_error;
break;
}
x = PyFloat_AsDouble(item);
Py_DECREF(item);
if (PyErr_Occurred())
goto _fsum_error;
xsave = x;
for (i = j = 0; j < n; j++) { /* for y in partials */
y = p[j];
if (fabs(x) < fabs(y)) {
t = x; x = y; y = t;
}
hi = x + y;
yr = hi - x;
lo = y - yr;
if (lo != 0.0)
p[i++] = lo;
x = hi;
}
n = i; /* ps[i:] = [x] */
if (x != 0.0) {
if (! Py_IS_FINITE(x)) {
/* a nonfinite x could arise either as
a result of intermediate overflow, or
as a result of a nan or inf in the
summands */
if (Py_IS_FINITE(xsave)) {
PyErr_SetString(PyExc_OverflowError,
"intermediate overflow in fsum");
goto _fsum_error;
}
if (Py_IS_INFINITY(xsave))
inf_sum += xsave;
special_sum += xsave;
/* reset partials */
n = 0;
}
else if (n >= m && _fsum_realloc(&p, n, ps, &m))
goto _fsum_error;
else
p[n++] = x;
}
}
if (special_sum != 0.0) {
if (Py_IS_NAN(inf_sum))
PyErr_SetString(PyExc_ValueError,
"-inf + inf in fsum");
else
sum = PyFloat_FromDouble(special_sum);
goto _fsum_error;
}
hi = 0.0;
if (n > 0) {
hi = p[--n];
/* sum_exact(ps, hi) from the top, stop when the sum becomes
inexact. */
while (n > 0) {
x = hi;
y = p[--n];
assert(fabs(y) < fabs(x));
hi = x + y;
yr = hi - x;
lo = y - yr;
if (lo != 0.0)
break;
}
/* Make half-even rounding work across multiple partials.
Needed so that sum([1e-16, 1, 1e16]) will round-up the last
digit to two instead of down to zero (the 1e-16 makes the 1
slightly closer to two). With a potential 1 ULP rounding
error fixed-up, math.fsum() can guarantee commutativity. */
if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) ||
(lo > 0.0 && p[n-1] > 0.0))) {
y = lo * 2.0;
x = hi + y;
yr = x - hi;
if (y == yr)
hi = x;
}
}
sum = PyFloat_FromDouble(hi);
_fsum_error:
PyFPE_END_PROTECT(hi)
Py_DECREF(iter);
if (p != ps)
PyMem_Free(p);
return sum;
}
This summation method is different from Kahan's method, it uses a variable number of compensation variables. When adding the ith number, at most i additional compensation variables (stored in the array p) get used. This means if I want to add 3 numbers, I may need 3 additional variables. For 4 numbers, I may need 4 additional variables. Since the number of used variables may increase from n to n+1 only after the nth summand is loaded, I can translate the above code to Java as follows:
/**
* Compute the exact sum of the values in the given array
* {#code summands} while destroying the contents of said array.
*
* #param summands
* the summand array – will be summed up and destroyed
* #return the accurate sum of the elements of {#code summands}
*/
private static final double __destructiveSum(final double[] summands) {
int i, j, n;
double x, y, t, xsave, hi, yr, lo;
boolean ninf, pinf;
n = 0;
lo = 0d;
ninf = pinf = false;
for (double summand : summands) {
xsave = summand;
for (i = j = 0; j < n; j++) {
y = summands[j];
if (Math.abs(summand) < Math.abs(y)) {
t = summand;
summand = y;
y = t;
}
hi = summand + y;
yr = hi - summand;
lo = y - yr;
if (lo != 0.0) {
summands[i++] = lo;
}
summand = hi;
}
n = i; /* ps[i:] = [summand] */
if (summand != 0d) {
if ((summand > Double.NEGATIVE_INFINITY)
&& (summand < Double.POSITIVE_INFINITY)) {
summands[n++] = summand;// all finite, good, continue
} else {
if (xsave <= Double.NEGATIVE_INFINITY) {
if (pinf) {
return Double.NaN;
}
ninf = true;
} else {
if (xsave >= Double.POSITIVE_INFINITY) {
if (ninf) {
return Double.NaN;
}
pinf = true;
} else {
return Double.NaN;
}
}
n = 0;
}
}
}
if (pinf) {
return Double.POSITIVE_INFINITY;
}
if (ninf) {
return Double.NEGATIVE_INFINITY;
}
hi = 0d;
if (n > 0) {
hi = summands[--n];
/*
* sum_exact(ps, hi) from the top, stop when the sum becomes inexact.
*/
while (n > 0) {
x = hi;
y = summands[--n];
hi = x + y;
yr = hi - x;
lo = y - yr;
if (lo != 0d) {
break;
}
}
/*
* Make half-even rounding work across multiple partials. Needed so
* that sum([1e-16, 1, 1e16]) will round-up the last digit to two
* instead of down to zero (the 1e-16 makes the 1 slightly closer to
* two). With a potential 1 ULP rounding error fixed-up, math.fsum()
* can guarantee commutativity.
*/
if ((n > 0) && (((lo < 0d) && (summands[n - 1] < 0d)) || //
((lo > 0d) && (summands[n - 1] > 0d)))) {
y = lo * 2d;
x = hi + y;
yr = x - hi;
if (y == yr) {
hi = x;
}
}
}
return hi;
}
This function will take the array summands and add up the elements while simultaneously using it to store the compensation variables. Since we load the summand at index i before the array element at said index may become used for compensation, this will work.
Since the array will be small if the number of variables to add is small and won't escape the scope of our method, I think there is a decent chance that it will be allocated directly on the stack by the JIT, which may make the code quite fast.
I admit that I did not fully understand why the authors of the original code handled infinities, overflows, and NaNs the way they did. Here my code deviates from the original. (I hope I did not mess it up.)
Either way, I can now sum up 3, 4, or n double numbers by doing:
public static final double add3(final double x0, final double x1,
final double x2) {
return __destructiveSum(new double[] { x0, x1, x2 });
}
public static final double add4(final double x0, final double x1,
final double x2, final double x3) {
return __destructiveSum(new double[] { x0, x1, x2, x3 });
}
If I want to sum up 3 or 4 long numbers and obtain the precise result as double, I will have to deal with the fact that doubles can only represent longs in -9007199254740992..9007199254740992L. But this can easily be done by splitting each long into two parts:
public static final long add3(final long x0, final long x1,
final long x2) {
double lx;
return __destructiveSum(new long[] {new double[] { //
lx = x0, //
(x0 - ((long) lx)), //
lx = x1, //
(x1 - ((long) lx)), //
lx = x2, //
(x2 - ((long) lx)), //
});
}
public static final long add4(final long x0, final long x1,
final long x2, final long x3) {
double lx;
return __destructiveSum(new long[] {new double[] { //
lx = x0, //
(x0 - ((long) lx)), //
lx = x1, //
(x1 - ((long) lx)), //
lx = x2, //
(x2 - ((long) lx)), //
lx = x3, //
(x3 - ((long) lx)), //
});
}
I think this should be about right. At least I can now add Double.MAX_VALUE, 1, and -Double.MAX_VALUE and get 1 as result.

How to implement priority queue in matlab

Is there any library in matlab that provides the functionality of min priorityqueue
import java.util.PriorityQueue;
import java.util.*;
public class MyQueue {
Comparator<Double> c;
PriorityQueue<Double> PQ;
public MyQueue() {
c = new Comparator<Double>(){
public int compare(Double o1, Double o2){
if(o2 > o1) {
return -1;
} else if(o1 > o2) {
return 1;
} else {
return 0;
}
}
};
PQ = new PriorityQueue<Double>(1000,c);
}
public void addElement(double d) {
PQ.add(d);
}
public double removeElement() {
return(PQ.remove());
}
}
I have implemented this priorty queue in java. I can call it from matlab. However, I need to associate each cost with an index. I mean it's not only cost of the node that i need to store but also its index. How can I accomplish this. I need to pass the index from matlab
You can use Java's default PriorityQueue like so:
>> q=java.util.PriorityQueue;
>> q.add({value,index});
This is available since Java ≥ 1.5, which is pre-bundled in all MATLAB releases since 7.0.4 (R14).
Otherwise, you can use the one from the file exchange, which you'll have to compile.
There's also a Simulink block for it, but I doubt that's what you're after.
Below is a resizing-array implementation of a priority queue written entirely in matlab. You can attach/couple any kind of data/index you want along with the priority value. Also, you can switch/toggle the behaviour between a min and max priority queue through a boolean argument passed into the constructor when it is created.
classdef PriorityQueue < handle
properties (SetAccess = private)
numElements;
priorityList;
valueList;
flagMaxPriorityQueue;
end
methods (Access = public)
function obj = PriorityQueue( flagMaxPriorityQueue )
if ~exist( 'flagMaxPriorityQueue', 'var' )
flagMaxPriorityQueue = true;
else
if ~(isscalar(flagMaxPriorityQueue) && islogical(flagMaxPriorityQueue))
error( 'ERROR: invalid flagMaxPriorityQueue argument' );
end
end
obj.flagMaxPriorityQueue = flagMaxPriorityQueue;
obj.numElements = 0;
obj.priorityList = {};
obj.valueList = {};
end
function insert(obj, priority, value)
% increase the size of the array if full
if obj.numElements > 0 && obj.numElements + 1 > numel( obj.priorityList )
% double the size of the array and copy stuff
obj.priorityList = cat(1, obj.priorityList, cell(obj.numElements, 1));
obj.valueList = cat(1, obj.valueList, cell(obj.numElements, 1));
end
obj.numElements = obj.numElements + 1;
obj.priorityList{ obj.numElements } = priority;
obj.valueList{ obj.numElements } = value;
obj.swim(obj.numElements);
end
function [priority, value] = pop( obj )
if obj.isEmpty()
error( 'called pop() on an empty priority queue' );
end
priority = obj.priorityList{1};
value = obj.valueList{1};
obj.exch(1, obj.numElements);
obj.numElements = obj.numElements - 1;
obj.sink(1);
obj.priorityList{ obj.numElements + 1 } = [];
obj.valueList{ obj.numElements + 1 } = [];
% halve the size of the arrays if they get one-quarter full
if obj.numElements > 0 && obj.numElements == floor( numel( obj.priorityList ) / 4 )
obj.priorityList( 2 * obj.numElements + 1 : end ) = [];
obj.valueList( 2 * obj.numElements + 1 : end ) = [];
end
end
function [flagEmpty] = isEmpty( obj )
flagEmpty = (obj.numElements == 0);
end
function [qSize] = size( obj )
qSize = obj.numElements;
end
function [priority, value] = peek( obj )
if obj.isEmpty()
error( 'requested max() of an empty priority queue' );
end
priority = obj.priorityList{1};
value = obj.valueList{1};
end
end
methods (Access = private)
function swim(obj, elPos)
while elPos > 1 && obj.compare(floor(elPos / 2), elPos)
obj.exch(floor(elPos / 2), elPos);
elPos = floor(elPos / 2);
end
end
function sink(obj, elPos)
while 2 * elPos <= obj.numElements
j = 2 * elPos;
if j < obj.numElements && obj.compare(j, j+1)
j = j + 1;
end
if ~obj.compare(elPos, j)
break;
end
obj.exch(elPos, j);
elPos = j;
end
end
function [blnCmpResult] = compare(obj, e1, e2)
if obj.flagMaxPriorityQueue
blnCmpResult = (obj.priorityList{e1} < obj.priorityList{e2});
else
blnCmpResult = (obj.priorityList{e1} > obj.priorityList{e2});
end
end
function exch(obj, e1, e2 )
temp = obj.priorityList{e1};
obj.priorityList{e1} = obj.priorityList{e2};
obj.priorityList{e2} = temp;
temp = obj.valueList{e1};
obj.valueList{e1} = obj.valueList{e2};
obj.valueList{e2} = temp;
end
end
end % classdef