First question here.
Basically, I want to implement a recursive bisection algorithm in SAS via the use of macros. I have already written a macro that takes two arguments (the lower and upper endpoints of the current interval) and produces a table containing the two endpoints of another interval. The problem I'm having is writing a macro that will iterate this process until the width of the interval is below a certain threshold.
Here is what I have so far, but the code does not work as I expect. Bear in mind, 99% of everything I've ever learned about SAS, I learned in the past three days or so. Much thanks to anyone who can help!
data interval;
input a b;
datalines;
0 1
;
run;
%macro iter(a,b);
data rec;
set interval;
%let a0 = &a;
%let b0 = &b;
%do %while(%sysevalf(&b0 - &a0) > .00001);
%nextint(&a0,&b0);
call symput('a0',trim(left(a)));
call symput('b0',trim(left(b)));
%end;
run;
%mend;
where %nextint(&a0,&b0) produces a table interval with one observation, and two columns a and b with the values calculated from &a0 and &b0. As you can see, SAS is a complete mystery to me and I don't know what I'm doing.
Not sure what your macro %nextint does, but I wrote something just to show how the %iter macro will run.
You need to put those call symput's in a data step.
I used null here just to get new values for the macro variables a0 and b0 from the interval data set.
Note, this will produce the interval data set with the first set of values for a and b where b - a is less than 0.0001.
The %put statements at the end of the macro will show you the changing values of a and b for each interation.
%macro nextint(a1,b1);
data interval;
a = &a1. + 0.1;
b = &b1. - 0.1;
run;
%mend;
%macro iter(a,b);
%let a0 = &a.;
%let b0 = &b.;
%do %while(%sysevalf(%sysevalf(&b0. - &a0.) > 0.0001));
%nextint(&a0,&b0);
data _null_;
set interval;
call symput('a0',strip(a));
call symput('b0',strip(b));
run;
%put &a0.;
%put &b0.;
%put %sysevalf(&b0. - &a0.);
%end;
%mend;
%iter(0,1);
I would suggest that you look into SAS/IML syntax to do numerical analysis work.
This blog by Rick Wicklin explains how you can use SAS/IML to find the root of a function.
If you would still like to use macros and the data step, you can use the
options mprint; statement to debug your code and see in the log which commands are actually ran.
Related
I have the Verilog statement below:
module test (A,B, CLK);
input A, CLK;
output B;
always#(posedge CLK)
if(A) B <= 1'b1;
endmodule
I am expecting a register. However, after I synthesis it with Yosys, I got the result as follow:
assign B = 1'b1;
I don't understand why Yosys translate the above Verilog statement to a constant 1.
Please advice, thanks!
Your B has two possible values:
1'b x during initialization (more in IEEE Std 1364 4.2.2 Variable declarations),
1'b 1 when A is equal to 1'b 1.
You really have only one value. Thats mean you can optimize it to hardwired 1'b 1.
This is not a Yosys fault. All (or almost all) synthesis software will behave same way. If you want to let it work (if I guess what you want), you have to allow B to take two different values. You can do it by initial value equal to 1'b 0 or by reset to value 1'b 0.
I suggest to use reset instead of initial value because initial value can be implemented as A connected to register's set pin.
Interesting! I noticed that if you assign an initial value of zero to the register (e.g. output reg B = 1'b0) you do get a flip-flop. (I used read_verilog <your_code.v> ; synth ; show.)
However, an initial value of one still produces the constant output you mention. So perhaps what's happening here (and I'm only speculating) is that when an initial value is not given, yosys is free to pick its own, in which case it picks 1'b1, so that the whole circuit is equivalent to a simple hard-wired constant? Only when the initial value is zero is the flip-flop necessary?
Foreword
The Fortran program that I'm writing should deal with 1D, 2D and 3D problems depending on ndims, which can be 1, 2 or 3 and is read from an input file.
In these cases the quantity/ies of interest can be stored in arrays (one could be named phi)
of rank dims (ALLOCATABLE(:) or ALLOCATABLE(:,:) or ALLOCATABLE(:,:,:)),
or in arrays of rank 3 (ALLOCATABLE(:,:,:) with third dimension to be set equal to 1 in 2D or both second and third dimensions equal to 1 in 1D);
both cases are explained well in this answer. The first approach seems more elegant to me, but in the following I assume the second one, which is definitely simpler.
These quantities have to be operated on by several subroutines (e.g. mysub) along the ndims dimensions (along "pencils" should give a graphic idea), so I should call something like
SELECT CASE (ndims)
! 3D case
CASE (3)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,k))
END DO
END DO
DO i = ...
DO k = ...
CALL mysub(phi(i,:,k))
END DO
END DO
DO i = ...
DO j = ...
CALL mysub(phi(i,j,:))
END DO
END DO
! 2D case
CASE (2)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,1))
END DO
END DO
DO i = ...
DO k = ...
CALL mysub(phi(i,:,1))
END DO
END DO
! 1D case
CASE (1)
DO j = ...
DO k = ...
CALL mysub(phi(:,1,1))
END DO
END DO
END SELECT
Actual question
Can anyone suggest me (or help me to to devise!) a different way of store phi (maybe involving derived data types?) so that I can collapse the preceding code as follows?
DO id = 1, ndims
CALL mysub2(phi,id)
END DO
(Here mysub2 acts on mysub's place.)
So the question is how should I store phi, so that I can substitute the first code with the second one?
Maybe I could return to the foreword and decide to follow the point 1., in which case would be easier to write a generic interface. This would be, I think, just a way to "hide" exactly what the SELECT CASE would do. Which of the two (SELECT CASE/generic INTERFACE) would be more efficient?
Are these the only two ways to face this problem?
Perhaps I have misunderstood, but I think the answer to the specific question is to not make any changes to the storage or declaration of phi at all.
In the original code, three dimensional data (differentiating rank of the data from rank of the array used to store the data) is processed in slices along the first dimension, then the second, then the third. Two dimensional data is processed along the first, then the second, and one dimensional data is processed along the first only.
So with id going from 1 to the number of dimensions in the data, consider the following implementation of mysub2:
SUBROUTINE mysub2(phi, id)
TYPE(pink_elephant), INTENT(IN) :: phi(:,:,:)
INTEGER, INTENT(IN) :: id
INTEGER :: i, j, k
SELECT CASE (id)
CASE (1)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,k))
END DO
END DO
CASE (2)
DO i = ...
DO k = ...
CALL mysub(phi(i,:,k))
END DO
END DO
CASE (3)
DO i = ...
DO j = ...
CALL mysub(phi(i,j,:))
END DO
END DO
END SELECT
END SUBROUTINE mysub2
~~
Generic interfaces can always be resolved at "compile time" - the specific procedure (not type bound) or binding (type bound) that will be invoked by a particular CALL statement or function reference can be determined just from looking at the declarations in the code.
If you have a situation where "runtime" information is going to affect the choice of procedure, then there has to be some other executable mechanism, other than or additional to the resolution of a generic, that comes into play - if statement, select case, dynamic dispatch, etc, etc, etc.
Asking whether generic resolution is more efficient than a executable decision is therefore not particularly meaningful - they are different things.
You probably want something like this:
program test
integer :: j,ndims
integer :: n ! rank of each dimension, could also be read from input an allocated separately
type arr
real(8) :: x(n) ! one array for each dimension
end type
type(arr),allocatable :: phi
read(*,*) ndims
allocate(phi(ndims))
do j=1,ndims
call mysub(phi(j)%x) ! acts on the array in dimension j
end do
contains
subroutine mysub(x)
...
end subroutine
end program
I am trying to create a step function in scilab, that jumps between two values {28,36} and stays on each for 5 units of 'i'.
Here is my code;
for i=1:25;
if pmodulo(i,5)==0
if a==28
a=36
else
a=28
end
end
end
plot(i,a)
can some one please tell me what am missing, cause i keep getting a plot screen with no graph and my i-axis in the plot screen has values from 20 to 25 instead of 1 to 25, which tells me am doing something wrong
Your code
There are some problems with your Scilab code given. The biggest problem being that i and a are only doubles on the moment of trying to plot them. During the for loop i gets reassigned continuously. So when the for-loop is exited, its value is 25.
The same applies to a. In the first iteration it is completely unknown. So the code will fail for sure. If you add a declaration above the for-loop initializing the value, it would at least exist. But then it will continuously get reassigned either 36 or 28.
At the end of the for-loop you would end up with i=25 and a=36.
Step function
To plot a step function in Scilab. Scilab provides the plot2d2 functionality. Look at the docs for more info, but for your example, below an extremely verbose piece of example code.
start_X = 0;
step_X = 5;
end_X = 24;
high=36;
low=28;
X = [start_X:step_X:end_X];
Y = [low,high,low,high,low];
plot2d2(X,Y);
Getting started with SciLab
DuckDuckGo provides a lot of getting started tutorials, which may give you some more insight in SciLab.
I have a simple m file that I have created as a recursive function:
function[velocity] = terminal(m,c,t,vi)
%inputs:
% m = mass
% c = coeffcient of drag
% t = time
% vi = initial velocity
if t==18, velocity = vi+(9.8-c/m*(vi))*2;
return
end
velocity = vi+(9.8-c/m*(vi))*2;
velocity %used to print out velocity for debugging
terminal(m,c,t+2,velocity);
end
The calculation of velocity is being done correctly as it prints out every recursion. However the "ans" that is returned at the end is the first calculated value of recursion. My question is how do I correctly setup a matlab function recursively? Or can it be done, and is it better to use a loop?
Although my answer will stray away from programming and into the realm of calculus, it should be noted that you can solve your problem both without recursion or a loop since you can exactly solve for an equation v(t) using integration. It appears that you are modeling Stokes' drag on a falling body, so you can use the fourth formula from this integration table to compute a final velocity vFinal that is achieved after falling for a time tDelta given a starting velocity vInitial. Here is the resulting formula you would get:
vFinal = 9.8*m/c + (vInitial - 9.8*m/c)*exp(-c*tDelta/m);
This will be a more accurate answer than approximating vFinal by making sequential steps forward in time (i.e. the Euler method, which can display significant errors or instabilities when the time steps that are taken are too large).
Bear with me, haven't done a lot of Matlab for some time now.
But I would simply call your function iteratively:
velocity = vi
for t = 0:2:18
velocity = velocity+(9.8-c/m*(velocity))*2;
end
Then for each instance of t it would calculate velocity for a given initial velocity and update that value with it's new velocity.
To have it take incremental steps with a size of 2, simply add your step size to it.
Updated in response to the comments
velocity = terminal(m,c,t+2,velocity)
should work.
The problem with recursion here is it adds function call overhead for each time through. This will make your code far slower and less efficient in matlab. Use a loop instead and you will be far ahead of things. Yes, there are cases where recursion is a valuable tool. But in many cases a carefully written loop is the better solution.
Finally, when you DO use recursion, learn when to apply tools like memoization to improve the behavior of the algorithm. Memoization simply means to not recompute that which you have already done. For example it is possible to use recursion for a fibonacci sequence, but this is a terribly inefficient way to do so.
The return value of your function is velocity. Matlab will return the last value assigned to velocity in the function body. Even though velocity is assigned deeper into the recursion, this doesn't matter to Matlab.
velocity in the next call to terminal() is a different variable!
Changing the final line to
function[velocity] = terminal(m,c,t,vi)
%inputs:
% m = mass
% c = coeffcient of drag
% t = time
% vi = initial velocity
if t==18, velocity = vi+(9.8-c/m*(vi))*2;
return
end
velocity = vi+(9.8-c/m*(vi))*2;
velocity %used to print out velocity for debugging
velocity = terminal(m,c,t+2,velocity);
end
Gives the expected result.
This is a really basic question but this is the first time I've used MATLAB and I'm stuck.
I need to simulate a simple series RC network using 3 different numerical integration techniques. I think I understand how to use the ode solvers, but I have no idea how to enter the differential equation of the system. Do I need to do it via an m-file?
It's just a simple RC circuit in the form:
RC dy(t)/dt + y(t) = u(t)
with zero initial conditions. I have the values for R, C the step length and the simulation time but I don't know how to use MATLAB particularly well.
Any help is much appreciated!
You are going to need a function file that takes t and y as input and gives dy as output. It would be its own file with the following header.
function dy = rigid(t,y)
Save it as rigid.m on the MATLAB path.
From there you would put in your differential equation. You now have a function. Here is a simple one:
function dy = rigid(t,y)
dy = sin(t);
From the command line or a script, you need to drive this function through ODE45
[T,Y] = ode45(#rigid,[0 2*pi],[0]);
This will give you your function (rigid.m) running from time 0 through time 2*pi with an initial y of zero.
Plot this:
plot(T,Y)
More of the MATLAB documentation is here:
http://www.mathworks.com/access/helpdesk/help/techdoc/ref/ode23tb.html
The Official Matlab Crash Course (PDF warning) has a section on solving ODEs, as well as a lot of other resources I found useful when starting Matlab.