I'm having a task in Modelica, where within a function, I want to read out values of a record (parameters) according to a given string type argument, similar to the dictionary type in Python.
For example I have a record containing coefficicents for different media, I want to read out the coefficients for methane, so my argument is the string "Methane".
Until now I solve this by presenting a second array in my coefficients-record storing the names of the media in strings. This array I parse in a for loop to match the requested media-name and then access the coefficients-array by using the found index.
This is obviously very complicated and leads to a lot of confusing code and nested for loops. Isn't there a more convenient way like the one Python presents with its dictionary type, where a string is directly linked to a value?
Thanks for the help!
There are several different alternatives you can use. I will add the pattern I like most:
model M
function index
input String[:] keys;
input String key;
output Integer i;
algorithm
i := Modelica.Math.BooleanVectors.firstTrueIndex({k == key for k in keys});
end index;
constant String[3] keys = {"A","B","C"};
Real[size(keys,1)] values = {1,2*time,3};
Real c = values[index(keys,"B")] "Coefficient";
annotation(uses(Modelica(version="3.2.1")));
end M;
The reason I like this code is because it can be made efficient by a Modelica compiler. You create a keys vector, and a corresponding data vector. The reason it is not a record is that you want the keys vector to be constant, and the values may vary over time (for a more generic dictionary than you wanted).
The compiler can then create a constant index for any constant names you want to lookup from this. This makes sorting and matching better in the compiler (since there are no unknown indexes). If there is a key you want to lookup at run-time, the code will work for this as well.
Related
In C if I have:
int grades[100][200];
and want to pass the first row, then I write: grades[0], but what if I want to pass first column? writing this won't help grades[][0]
You can't pass columns in C. You pass pointers to the beginning of some continuous data.
Rows in C are written continuously in memory, so you pass the pointer to the first element of some row (you do it implicitly by using its name: matrix[row]; an explicit version would be &matrix[row][0]), and you can use the row by iterating over the continuous memory.
To use columns, you need to pass the whole array (a pointer to the first element in the 2D array, actually), and pass also the length of the rows, and then the function has to jump that length to jump from an element of the same column to the next one. This is one of many possible solutions, you could develop any other solution, for example copying the column in a temporary array as some comment pointed out; but this one is commonly used in cblas functions for example.
If it helps to visualize, a 2-dimensional array is an array of arrays, it's not formulated as a matrix. Thereby, we can pass a sub-array (i.e., a row), but there's no direct way of passing a column.
One way to achieve this is to loop over the outer array, pick the element at the fixed location (mimicking the "column"), and use the values to create a separate array, or pass to function that needs to process the data.
Matrixes do not exist in C (check by reading the C11 standard n1570). Only arrays, and in your example, it is an array of arrays of int. So columns don't exist neither.
A good approach is to view a matrix like some abstract data type (using flexible array members ....) See this answer for details.
Consider also using (and perhaps looking inside its source code) the GNU scientific library GSL, and other libraries like OpenCV, see the list here.
In some cases, arbitrary precision arithmetic (with gmplib) could be needed.
I currently look for an advice on the below piece of code which consists of efficiently looping through a dataset (of cell type) and extracting each column as data vector.
[i,j]=size(fimat);
k=2;
while k<=j % looping through columns
[num2str(k-1),'yr']=cell2mat(fimat(:,k)); %extract each column as vector
k=k+1;
end
My matter undeniably lies in the following statement:
[num2str(k-1),'yr']
that correctly concatenates numbers (reflected by variable k) and string name 'yr'. However the syntax fails in assigning for instance (during 1st iteration)
1yr=cell2mat(fimat(:,2))
The resulting error speaks from itself
Error: An array for multiple LHS assignment cannot contain LEX_TS_STRING.
but I'm still figuring out a way to do it. Thus any feedback would be appreciated.
Thanks
First of all, in matlab, a variable name cannot start with a digit. You should modify your code such that the variable name starts with either a letter or an underscore.
For instance ['yr' num2str(k-1)] or ['_' num2str(k-1) 'yr'] would be better.
Then, what you are trying to do is very strongly discouraged by everyone, including The Mathworks. It would be much better to use a cell yr and call to yr{k} rather than iterative variable names:
yr = cell(j,1);
for k = 2:j
yr{k-1} = cell2mat(fimat(:,k));
end
Anyway, if you still want to do this, you can use eval
while k<=j
eval(['_' num2str(k-1) 'yr = cell2mat(fimat(:,k));']);
k=k+1;
end
Best,
You can not dynamically create variable names like you did. The left side of the = must be a identifier, not a char. The alternative I recommend is to use a cell array instead of individual variable names. For example:
yr{k-1}=cell2mat(fimat(:,k))
If you must use variable names with numbers, which I strongly recommend not to do, you have to use eval for the line. Alternatives which I strongly recommend to check before using eval are struct with dynamic field names and containers.Map
Here is my answer to the question, for sharing purposes. Hope it will help and Thanks to the contributors of this post.
[i,j]=size(fimat); %get dimension of dataset (of cell type)
numdata=cell2mat(fimat(1:i,2:j)); %extract only numeric from dataset
for k=1:j-1
eval(sprintf('yr%d = numdata(:,k)', k));
end
I want to make a 2D array "data" with the following dimensions: data(T,N)
T is a constant and N I dont know anything about to begin with. Is it possible to do something like this in fortran
do i = 1, T
check a few flags
if (all flags ok)
c = c+ 1
data(i,c) = some value
end if
end do
Basically I have no idea about the second dimension. Depending on some flags, if those flags are fine, I want to keep adding more elements to the array.
How can I do this?
There are several possible solutions. You could make data an allocatable array and guess the maximum value for N. As long as you don't excess N, you keep adding data items. If a new item would exceed the array size, you create a temporary array, copy data to the temporary array, deallocate data and reallocate with a larger dimension.
Another design choice would be to use a linked list. This is more flexible in that the length is indefinite. You loss "random access" in that the list is chained rather than indexed. You create an user defined type that contains various data, e.g., scalers, arrays, whatever, and also a pointer. When you add a list item, the pointer points to that next item. The is possible in Fortran >=90 since pointers are supported.
I suggest searching the web or reading a book about these data structures.
Assuming what you wrote is more-or-less how your code really goes, then you assuredly do know one thing: N cannot be greater than T. You would not have to change your do-loop, but you will definitely need to initialize data before the loop.
I tried to find answers, but all I got was answers on how to realize arrays starting with nonzero indexes. Some languages, such as pascal, provide this by default, e.g., you can create an array such as
var foobar: array[1..10] of string;
I've always been wondering: Why would you want to have the array index not to start with 0?
I guess it may be more familiar for beginners to have arrays starting with 1 and the last index being the size of the array, but on a long-term basis, programmers should get used to values starting with 0.
Another purpose I could think of: In some cases, the index could actually represent something thats contained in the respective array-entry. e.g., you want to get all capital letters in an array, it may be handy to have an index being the ASCII-Code of the respective letter. But its pretty easy just to subtract a constant value. In this example, you could (in C) simply do something like this do get all capital letters and access the letter with ascii-code 67:
#define ASCII_SHIFT 65
main()
{
int capital_letters[26];
int i;
for (i=0; i<26; i++){
capital_letters[i] = i+ASCII_SHIFT;
}
printf("%c\n", capital_letters[67-ASCII_SHIFT]);
}
Also, I think you should use hash tables if you want to access entries by some sort of key.
Someone might retort: Why should the index always start with 0? Well, it's a hell of a lot simpler this way. You'll be faster when you just have to type one index when declaring an array. Also, you can always be sure that the first entry is array[0] and the last one is array[length_of_array-1]. It is also common that other data structures start with 0. e.g., if you read a binary file, you start with the 0th byte, not the first.
Now, why do some programming languages have this "feature" and why do some people ask how to achieve this in languages such as C/C++?, is there any situation where an array starting with a nonzero index is way more useful, or even, something simply cannot be done with an array starting at 0?
If your index means something, e.g. an id from a database or some such, then it's useful.
Oh, and you can't use hashes because you want to use it with some other piece of code that expects arrays.
For example, Rails checkboxes. They're passed from the web form as arrays but in my code I want to access the udnerlying database object. The array index is the id, et voila!
Non-zero based arrays are a natural extension of arrays with ordinal indexes that are not integers. In Pascal you can have arrays like:
var
letter_count : array['a'..'z'] of integer;
Or:
type
flags = (GREEN, YELOW, RED);
var
flags_seen = array[flags] of boolean;
A classic is an array with negative indexes:
zero_centered_grid = array[-N..N,-N..N] of sometype;
The idea is that:
Many indexing errors can be detected at compile time if the declaration of indexes is more specific.
Some algorithms (heaps come to mind) have cleaner implementations when the minimum index is something different from zero.
Languages with only zero-based arrays use well defined idioms for the latter, and have efficient implementations of dictionaries/maps for the rest.
I have to do a table lookup to translate from input A to output A'. I have a function with input A which should return A'. Using databases or flat files are not possible for certain reasons. I have to hardcode the lookup in the program itself.
What would be the the most optimum (*space-wise and time-wise separately): Using a hashmap, with A as the key and A' as the value, or use switch case statements in the function?
The table is a string to string lookup with a size of about 60 entries.
If speed is ultra ultra necessary, then I would consider perfect hashing. Otherwise I'd use an array/vector of string to string pairs, created statically in sort order and use binary search. I'd also write a small test program to check the speed and memory constraints were met.
I believe that both the switch and the table-look up will be equivalent (although one should do some tests on the compiler being used). A modern C compiler will implement a big switch with a look-up table. The table look-up can be created more easily with a macro or a scripting language.
For both solutions the input A must be an integer. If this is not the case, one solution will be to implement a huge if-else statement.
If you have strings you can create two arrays - one for input and one for output (this will be inefficient if they aren't of the same size). Then you need to iterate the contents of the input array to find a match. Based on the index you find, you return the corresponding output string.
Make a key that is fast to calculate, and hash
If the table is pretty static, unlikely to change in future, you could have a look-see if adding a few selected chars (with fix indexes) in the "key" string could get unique values (value K). From those insert the "value" strings into a hash_table by using the pre-calculated "K" value for each "key" string.
Although a hash method is fast, there is still the possibility of collision (two inputs generating the same hash value). A fast method depends on the data type of the input.
For integral types, the fastest table lookup method is an array. Use the incoming datum as an index into the array. One of the problems with this method is that the array must account for the entire spectrum of values for the fastest speed. Otherwise execution is slowed down by translating the original index into an index for the array (kind of like a hashing method).
For string input types, a nested look up may be the fastest. One example is to break up tables by length. The first array returns pointers to the table to search based on length, e.g. char * sub_table = First_Array[5] for a string of length 5. These can be configured for specialized input data.
Another method is to use a B-Tree, which is a binary tree of "pages". Behavior is similar to nested arrays.
If you let us know the input type, we can better answer your question.