Create vector of symbolic variables by name through iteration - symbolic-math

I'm trying to create a growing vector inside a for-loop, i.e. the vector is initialized with one element (lets call it q_1) and in the next iteration of the loop the vector is expanded by a second element (lets call it q_2) and so on. Every element is a symbolic element depending on another independent element (in my case that's the time t).
The overall idea is to create a growing second order ODE that I want to solve and plot in every loop.
The first step I already implemented, is the for-loop but I struggle with creating a new symbolic variable inside the loop. My first idea was to create the variable by name so I can use the iteration index i of the loop and create a new unique string every loop, but I don't know how to accomplish this with Maxima.

There are various ways.
use subscripted symbolic variables, e.g., u[1], u[2], u[3], ....
use gensyms (generated symbol names which are guaranteed to be different from any other existing symbol. E.g. gensym() returns something like g4282, then next time gensym() returns g4283, etc.
construct a symbol via concat, e.g. concat('foo, 3) returns foo3. THIS IS THE SOLUTION OF LAST RESORT. TRY ANYTHING ELSE BEFORE RESORTING TO CONCAT. It is too easy to make a mess that way.
If you show the code you have so far, maybe I can give more specific advice.

Building upon the accepted answer, here is an example (using the concat method) of a for loop creating a matrix M with "indexed" symbols e_ij as elements:
M: zeromatrix(6,6)$
for r: 1 thru 6 do (
for c: 1 thru 6 do (
M[r][c]: concat('e_,r,c)
)
)$

Related

Is there a way to append several values to a Pine Script array in a single call?

I want to have a function within which several if conditions looking for specific integer values.
The function in some situations might be called several times in sequence in order to return the resulting values of several different if conditions.
The idea I had for this, in order to reduce the code's bulkiness, was to have the portion of the script executing the function as required run through an integer array whose each stored value is sent to the function.
But in order for this to reduce the amount of bulky code I need a way to add several values at once rather than having the values each added separately.
Is that possible in Pinescript? Or perhaps you have a different solution for executing such function?
To answer my own question, it seems a simple way to update an array to a set of new values is to use the built in function array.from.
var array<int> arr = array.new<int>(0, 0)
arr := array.from(1, 4, 10)
It doesn't even require clearing and appending the new values as it simply replaces the testArr array with the new input.
If one wants to append several additional values to an existing array rather than replacing all of the original values, it can be done like this:
arr := array.concat(arr, array.from(1, 4, 10))
If I understand your question correctly you would like a single mass update (addition) to array elements? No such function exists, each element must be individually updated, ideally in a loop if you have a consistent calculation.

Storing and replacing values in array continuously

I'm trying to read amplitude from a waveform and shine a green, yellow or red light depending on the amplitude of the signal. I'm fairly new to labVIEW and couldnt get my idea that wouldve worked with any other programming language I know to work. What I'm trying to do is take the value of the signal and for everytime it updates I'll store the value of the amplitude into an index of a large array. With each measurement being stored in the n+1 index of the array.
After a certain amount of data points I want to start over and replace values in the array (I use the formula node with the modulus for this). By keeping a finite amount of indexes to check for max value I restrict my amplitude check to a certain time period.
However my problem is that whenever I use the replace array subset to insert a new value into index n, all the other index points get erased. Rendering it pretty much useless. I was thinking its the Initialize array causing problems but I just cant seem to wrap my head around what to do here.
I tried creating just basic arrays in the front panel, but those either are control or indicator arrays and can't seem to be both written and read from, its either control (read but not write) or indicate(write but not read)?. Maybe its just not possible to do what I had in mind in an eloquent way in LabVIEW. If its not possible to do this with arrays in LabVIEW I will look for a different way to do it.
I'm pretty sure I got most of the rest of the code down except for an unfinished part here and there. Its just my issue with the arrays not working as I want them too.
I expected the array to retain its previously inputted data for index n-1 when index n is inputted. And only to be replaced once the index has come back to that specific point.
Instead its like a new array is initialized every time a new index is input.
download link for the VI
What you want to do:
Transport the content of the modified array into the next iteration of the WHILE loop.
What happens:
On each iteration, the content of the array is the same. It is the content of the initial array you created outside.
To solve this, right-click the orange square on the left border of the loop, and make it a "shift register". The symbol changes, and a similar symbol appears on the right border. Now, wire the modified array to the symbol on the right. What flows out into that symbol on the right, comes in from the left symbol on the next iteration.
Edit:
I have optimized your code a little. There is a modulo function, and an IF clause can handle ranges. ..3 means "values lower or equal 3". The next case is "Default", the next "7..". Unfortunately, this only works for integers. Otherwise, one would use nested IF clauses with the < comparator or similar.

replacing r variables with multiple or different values

I have a dataframe (raw) that can have one variable (iv1) with NA's in it. I want to replace the NA with different random values from the distribution of existing scores within (iv1), not one single value. the sample size (n) can be anything - 100 to 1000.
I save the distribution to a new data frame (dbmi) because I want to keep raw and dbmi separate, and calculate the mean and SD of the existing values of iv1 within dbmi. The following code works but replaces all of the NA's with just one value. I think I need to set up a for loop? Some kind of loop that finds the next occurrence of an NA and runs the new 'rnorm' value and sticks it in and goes to the next and does it again etc etc but I cant figure out how to do that. Any help?
dbmi<-raw
attach(dbmi)
rawmean<-mean(dbmi$iv1,na.rm=TRUE)
rawsd<-sd(dbmi$iv1,na.rm=TRUE)
for (i in 1:n){
dbmi$iv1[is.na(dbmi$iv1)]<-rnorm(1,rawmean,rawsd)
}
I actually solved my own problem. I set up the variable locations [i] that had the NA's into a variable called 'pull', then I just created a new stream into a variable called 'new' I used this code to substitute.
dbmi<-raw
attach(dbmi)
rawmean<-mean(dbmi$iv1,na.rm=TRUE)
rawsd<-sd(dbmi$iv1,na.rm=TRUE)
new<-rnorm(num,rawmean,rawsd)
for (i in 1:n){
dbmi$iv1[pull]<-new
}

User defined script for trapezoidal rule for data in an array in Matlab

I am supposed to integrate data of acceleration and time to get velocity using a user defined script.
What I have so far is:
function myIntegral=myCumulativeTrapz(X,Y)
myIntegral=0.5*(Y+(Y+1))*((X+1)-X)
When I hit run, I get this error:
Error: File: myCumulativeTrapz.m Line: 27 Column: 1
Function definitions are not permitted in this context.
If the script for integration was successful, I would then put
velocity=myCumulativeTrapz(data_resultant_acc(:,1), data_resultant_acc(:,2))
in the command window. (Data_resultant_acc is an array where time is in the first column and acceleration is in the second column.)
Can someone help me out and tell me why is this not working?
The error message is shown because Matlab file can't contain both functions and commands that are outside of any functions. So, if you have something like
data_resultant_acc = rand(10,2);
velocity=myCumulativeTrapz(data_resultant_acc(:,1), data_resultant_acc(:,2));
function myIntegral=myCumulativeTrapz(X,Y)
myIntegral=0.5*(Y+(Y+1))*((X+1)-X)
end
change that to
function myProject
data_resultant_acc = rand(10,2);
velocity=myCumulativeTrapz(data_resultant_acc(:,1), data_resultant_acc(:,2));
end
function myIntegral=myCumulativeTrapz(X,Y)
myIntegral=0.5*(Y+(Y+1))*((X+1)-X)
end
thus making myProject the top-level function that will be executed when you run the file (for best results, the file name should be the name of that function).
After that, you will discover that 0.5*(Y+(Y+1))*((X+1)-X) is not a valid formula, for multiple reasons. Since both X and Y are column vectors, the first one should be transposed before multiplication. Also, you are adding 1 to vector components instead of shifting index by 1. A correct way to do the index shift is below:
myIntegral=0.5*(Y(1:end-1)+Y(2:end))'*(X(2:end)-X(1:end-1));
Here the comma selectors create vectors that omit either the very first or the very last entry. The average of two such vectors gives the averages of adjacent values. The difference gives the difference of adjacent values.

TI Process - how to merge two dimensions into a new one?

I have two dimensions - Invoice_In and Invoice_Out. I need to create a new dimension Invoice which combines both of these. Is there any easy way to do this with a TI process (or any other way using TI or Performance Modeler)? Thanks.
Have you consulted the Reference Guide (TM1 TurboIntegrator Functions chapter) about this?
You could use the All subsets of the two dimensions as a data source and iterate through both in the Metadata tab using two processes (or a master process which calls the same process and passes it parameters) but it would be just as easy (and more importantly you could keep it in one process by) doing this in the Prolog tab with a data source of None:
Use DimensionExists as an argument to an If() block to determine
whether the dimension Invoice exists;
If it doesn't, use DimensionCreate to create it. Add any consolidations that you want to add using DimensionElementInsert statements.
Use the DimSiz Rules function to get the number of elements in Invoice_In and Invoice_Out and store both in variables;
Your first loop iterates through InvoiceIn using a While block to count from 1 to the DimSiz value.
In your loop you would obtain the existing element using DimNm(). (You will also need to use ElLev or DType if you want to obtain only the N level elements.) You insert each element into Invoice through DimensionElementInsert. You may also need to use DimensionElementComponentAdd to add it to any top level consolidation.
Your second loop would do exactly the same but for Invoice_Out.
Where you may run into issues is if you have the same element names in both dimensions. DimensionElementInsert won't spit the dummy over that but it will ignore the insertion when it's encountered the second time.
Do NOT call any other processes which are intended to refer to this new dimension in the Prolog. You need to cross the Metadata boundary to ensure that the new dimension is registered with the server.
Export both Elements, copy and paste both list into one sheet.
Use the sheet as a source then use one line of code DimensionElementInsert in your TI.
DimensionElementInsert(DimName, InsertionPoint, ElName, ElType);
Alternatively, use the existing dimensions as a source. Then you don't need to construct a file.
You can set the datasourcename and cycle through N amount of dimensions.
(note: The new dimension needs to exist. Or you can create a new dimension within your TI. Depends how much you want to code. But I gave you the solution with the least coding).

Resources