Is it possible to assign labels for cells in arrays? I am just experimenting with arrays and I was curious if you could label different cells with descriptors. There is a diagram below for the kind of thing I wish to achieve-
Arrays are always indexed with integer indexes.
If the meaning of the rows and columns is constant and known at compile-time, you can have integer constants,that have the desired name and the value of the index, e.g.,
integer, parameter :: Plant1 = 1, Plant2 = 2,...
integer, parameter :: Day1 = 1, Day2 = 2,...
Array(Plant2, Day2) = 92
If this is not constant and and can be different every time you run your program for different data, you could certainly have an array of labels
character(label_len), allocatable :: rows(:)
rows = [character(label_len) :: "Plant 1", "Plant 2",...]
but you cannot use this for indexing. To find out which integer index corresponds to "Plant 2" you would have to search the array. This can be slow.
There is a data structure called dictionary that is used to retrieve such data assigned to character string labels more efficiently (still it takes some time). There are some Fortran implementations at https://fortranwiki.org/fortran/show/Hash+tables and hopefully one will also be developed for stdlib.
Related
Suppose I have an array A in Fortran of dimension 10 with numbers.
However I'm only interested in a subset of those numbers (for example 3).
I store those number in a smaller array B
B(1) = A(1)
B(2) = A(5)
B(3) = A(6)
I can also define a mapping table to store index 1, 5, 6 for example
MAP(1) = 1
MAP(2) = 5
MAP(3) = 6
How can I create an inverse map INVMAP such that
INVMAP(1) = 1
INVMAP(5) = 2
INVMAP(6) = 3
with the constrain that INVMAP has dimension 3 (and not 10).
The point is that the array A is too big to be stored in memory and B
is obtained iteratively (A is never really allocated).
Considerations:
I do not care about the 7 discarded values but I care about the position of the one we keep.
Since MAP and INVMAP are storing positions, there will never be collision (its a one to one correspondence).
Maybe it could be possible with HASH or Fortran table but I'm not really sure how because I'm mapping numbers, not keys. Any idea ?
Thanks a lot,
Sam
Here's a very simple solution. No Fortran on this machine so not entirely sure that I have the syntax absolutely correct. Define a derived type like this:
type :: row
integer :: a_index
integer :: a_value ! I've assumed that your A array contains integers
! use another type if you want to
end type
then
type(row), dimension(100) :: b ! In practice you'll probably want b to be
! allocatable
and
b(1) = (1, a(1)) ! each row of b contains the value at an index into a and
! the index
b(2) = (5, a(5))
b(3) = (6, a(6))
Now your map function is simply, in pseudo-code, map(n) = b(n)%a_index
and your inverse map is, again in pseudo-code, invmap(n) = findloc(b%a_index, n).
Since the inverse map is a simple scan, it might become too time-consuming for your taste when b becomes large. Then I might introduce an auxiliary index array pointing into b at intervals, or I might go crazy and start a binary search of b%a_index.
I can also define a mapping table to store index 1, 5, 6 for example
MAP(1) = 1
MAP(2) = 5
MAP(3) = 6
I don't know if you know, but Fortran has a nice feature (one of my favorites) known as Vector Subscripts. You can pass an 'array of indices' as an index to an array, and get the elements corresponding to each index, like this:
integer :: A(10) = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
integer :: map(3) = [1, 5, 6]
print *, A(map)
! outputs 10 50 60
How can I create an inverse map INVMAP such that
INVMAP(1) = 1
INVMAP(5) = 2
INVMAP(6) = 3
Well, if your INVMAP will have a domain and an image of different sizes, it must be a function, not an array. I mean, INVMAP cannot be an array of length 3 and accept indices from 1 to 6, right? Arrays in Fortran (and in most languages) imply contiguous indices.
The intrinsic function FINDLOC can be pretty handy here (I am asuming your function is bijector).
function invmap(map, ids)
integer :: ids(:), map(:), invmap(size(ids))
invmap = [(findloc(map, i), i = 1, size(ids))]
end
You could use this function to relate each map value to its position on map
integer :: myinvmap = invmap(map, [6, 1, 5])
print *, myinvmap ! outputs 3 1 2
print *, invmap(map, [5]) ! outputs 2
The point is that the array A is too big to be stored in memory and B
is obtained iteratively (A is never really allocated).
Now, if you will never allocate the big array, then its values will also be accessed by some function (you can consider it a function actually). You have basically two options here:
Have two arrays, one with the values got from big_array_function, and one with the parameter you passed to big_array (the indices).
Have one array of pairs [index, value]. It is the answer that #HighPerformanceMark provided.
Alternatively... (and not tested...)
Integer, dimension(100) :: A
Logical, dimension(100) :: A_Mask
Integer, dimension( 3) :: B
Integer, dimension(. 3) :: A_pos
Integer, dimension(. 3) :: I, J
A_Mask = .false.
A_Mask(1) = .true.
A_Mask(1) = .true.
A_Mask(1) = .true.
B = PACK(A, MASK=A_Mask)
J = 0
Collect_Positions: Do I = 1, SIZE(A)
If(.not. A_Mask(I)) CYCLE Collect_Positions
J = J+1
A_Pos(J) = I
ENDDO Collect_Positions
...
And then if one want to UNPACK, then the mask has the position... so it is possible to not worry about the position of A in general sense (but may be needed in the OP's case)
I have an array with multiple dimensions (the goal is to allow for about 100) and each dimension has a size of about 2^10 and I only need to store in it about 1000 double precision coefficients. I don't need to do any operation with this array aside from reading and writing into it. The code is written in Fortran 90.
I assume that if I a library like one of the ones mentioned in this answer I would be able to store the do this, but would this be optimized for the simple reading and writing operations? Is there a library that would be most efficient for that purpose?
Edit: By "simple reading and writing operations" I mean the following. Suppose
REAL(8), DIMENSION(1000) :: coeff1
INTEGER, DIMENSION(1000,5) :: index
I want to define coeff2 to store the values in coeff1 and then read itat the indices in index, that is
DO i = 1,1000
index(i,:) = [something]
coeff1(i) = [another something]
coeff2(index(i,1),index(i,2),index(i,3),index(i,4),index(i,5)) = coeff1(i)
ENDDO
Then, for any i I would like to access the value of
coeff2(index(i,1),index(i,2),index(i,3),index(i,4),index(i,5))
as quickly as possible. Being able to do this fast is what I mean by "efficient".
Since the indices in [something] are at most 2^10 I am currently defining coeff2 as follows:
REAL(8), DIMENSION(2**10,2**10,2**10,2**10,2**10) :: coeff2
but this is too wasteful of memory specially since I need to increase the number of dimensions, now 5, to the order of 100 and most elements of this array are equal to 0. So, another measure of efficiency that is relevant to me is that the memory necessary to store coeff2 should not explode as I increase the number of dimensions.
Well, It's still not totally clear to me the nature of your data and the way you want to use it.
If what you need is indexed data, whose indices are not consecutive,
Sparse matrix can be an answer, and there are many solutions already implemented over the internet (as shown in the link you provided). But maybe it would be overkill for what I think you are trying to do. Maybe a simple datatype could serve your purpose, like this:
program indexed_values
implicit none
type :: indexed
integer :: index
real(8) :: value
end type
integer, parameter :: n_coeffs = 1000
integer, parameter :: n_indices = 5
integer :: i
real(8), dimension(n_coeffs) :: coeff1
integer, dimension(n_coeffs, n_indices) :: index
type(indexed), dimension(n_coeffs, n_indices) :: coeff2
type(indexed) :: var
do i = 1, n_coeffs
index(i, :) = [1, 2, 4, 16, 32] * i ! your calc here
coeff1(i) = real(i * 3, 8) ! more calc here
coeff2(i, :)%index = index(i, :)
coeff2(i, :)%value = coeff1(i)
end do
! that's how you fetch the indices and values by stored position
var = coeff2(500, 2)
print*, var%index, var%value ! outputs: 1000 1500.0
! that's how you fetch a value by its index
print*, fetch_by_index(coeff2(500, :), 1000) ! outputs: 1500.0
contains
real(8) function fetch_by_index(indexed_pairs, index)
type(indexed), dimension(:) :: indexed_pairs
integer, intent(in) :: index
integer :: i
do i=1, size(indexed_pairs)
if(index == indexed_pairs(i)%index) then
fetch_by_index = indexed_pairs(i)%value
return
end if
end do
stop "No value stored for this index"
end
end
The provided function for fetching values by its indices could be improved if your indices will be alwyas stored in ascending order (no need to traverse the whole list to fail). Moreover, if you will assing a constant result of coeff1 to all the indices at each row, you could do even better and just not having a coeff2 array at all, just have coeff1 for values and index for the indices, and correlate them by position.
I have a program that takes 2 inputs, N and myarray[ ].
cin >> N;
cin >> myarray[];
In this example say, N=3 which means an integer array of size 3 has to be allocated and suppose that the entries of myarray[ ] are {1,2,3}.
Now I have a function createsubset() that creates all the possible subsets of the entries {1,2,3}. The logic that I am following is:
Total number of subsets of a set containing n elements is m=2^n, because an element can be either present or absent in a subset.
So, when m=7 and corresponding binary notation is 111.
Now iterate from m=0 to m=7 to generate all the subsets(except for the set itself which is outcome of m=8):
Example:
m=0, binary=000, subset={ }
m=1, binary=001, subset={c}
m=2, binary=010, subset={b}
m=3, binary=011, subset={b,c}
and so on.
This is done by a function generate() that iterates from m=0 to m=8.
void generate()
{
for(m=0; m<8; m++)
{
decimaltobinary(m);
}
}
Now, I have to store the output of decimaltobinary() function (which is a 3-bit binary number) in an array which I will use later to create subsets. This is the part where I am stuck right now.
Can we store a multibit binary number in an array and use it directly?
Please help me regarding this.
Any suggestion regarding the createsubset() fuction is also welcomed.
Numbers in C/C++ are stored in binary so there is no need to "convert" them. You can use any C/C++ unsigned integral type you want to to store a 3 bit number so, for example, storing them in std::vector<unsigned char> would work fine.
Along this line, rather than storing the numbers you read into an array [fixed size container] consider storing them in a vector [variable size container] because you don't know the size "up front"
I want to store all the iteration output in a matrix(of size 200x200).
While executing the code : got the error at the
for t in (T2/Taw)*np.arange(-Taw,Taw-1):
i=i+1;
j=0;
for Fd in (B/Taw)*np.arange(-Taw,Taw-1):
j=j+1;
val1=1-abs(t)/T2;
val2=pi*T2*val1;
val3=Fd+mu*t+np.spacing(1);
val4=val2*val3;
ambg[j,i]=np.abs(val1*(sin(val4)/(val4)))**2;
---> 62 ambg[j,i]=np.abs(val1*(sin(val4)/(val4)))**2;
TypeError: list indices must be integers, not tuple
ambg=[] is a list. It can only be indexed with an integer, e.g ambg[i]. ambg[i,j] is the equivalent to ambg[(i,j)], where (i,j) is a tuple. Hence the error message.
If ambg was a list of lists, then it could indexed as ambg[i],[j]. But lists of lists are often constructed by iteratively appending values to a list(s).
If you initialized ambg=np.zeros((N,M)) where i and j will range over range(N) and range(M), then your code should work.
However initializing a numpy array element by element like this is slow, and considered poor practice. I haven't studied your code in detail, but it looks like you might be able to construct ambg with vector operations using T = (T2/Taw)*np.arange(-Taw,Taw-1) and FD = (B/Taw)*np.arange(-Taw,Taw-1).
For example T[:,None] is a single column array, and FD[None,:] a
single row array, that together can be used to calculate the NxN array based on all combinations of their values.
Experiment with something simpler like I = np.arange(10) and J = np.arange(10), and look at I[:,None]*J[None,:], or their sum, or difference, etc.
I am working on a binary linear program problem.
I am not really familiar with any computer language(just learned Java and C++ for a few months), but I may have to use computer anyway since the problem is quite complicated.
The first step is to declare variables m_ij for every entry in (at least 8 X 8) a matrix M.
Then I assign corresponding values of each element of a matrix to each of these variables.
The next is to generate other sets of variables, x_ij1, x_ij2, x_ij3, x_ij4, and x_ij5, whenever the value of m_ij is not 0.
The value of x_ijk variable is either 0 or 1, and I do not have to assign values for x_ijk variables.
Probably the simplest way to do it is to declare and assign a value to each variable, e.g.
int* m_11 = 5, int* m_12 = 2, int* m_13 = 0, ... int* m_1n = 1
int* m_21 = 3, int* m_12 = 1, int* m_13 = 2, ... int* m_2n = 3
and then pick variables, the value of which is not 0, and declare x_ij1 ~ x_ij5 accordingly.
But this might be too much work, especially since I am going to consider many different matrices for this problem.
Is there any way to do this automatically?
I know a little bit of Java and C++, and I am considering using lp_solve package in C++(to solve binary integer linear program problem), but I am willing to use any other language or program if I could do this easily.
I am sure there must be some way to do this(probably using loops, I guess?), and this is a very simple task, but I just don't know about it because I do not have much programming language.
One of my cohort wrote a program for generating a random matrix satisfying some condition we need, so if I could use that matrix as my input, it might be ideal, but just any way to do this would be okay as of now.
Say, if there is a way to do it with MS excel, like putting matrix entries to the cells in an excel file, and import it to C++ and automatically generate variables and assign values to them, then this would simplify the task by a great deal!
Matlab indeed seems very suitable for the task. Though the example offered by #Dr_Sam will indeed create the matrices on the fly, I would recommend you to initialize them before you assign the values. This way your code still ends up with the right variable if something with the same name already existed in the workspace and also your variable will always have the expected size.
Assuming you want to define a square 8x8 matrix:
m = zeros(8)
Now in general, if you want to initialize a three dimensional matrixh of size imax,jmax,kmax:
imax = 8;
jmax = 8;
kmax = 5;
x = zeros(imax,jmax,kmax);
Now assigning to or reading from these matrices is very easy, note that length and with of m have been chosen the same as the first dimensions of x:
m(3,4) = 4; %Assign a value
myvalue = m(3,4) %read the value
m(:,1) = 1:8 *Assign the values 1 through 8 to the first column
x(2,4,5) = 12; %Assign a single value to the three dimensional matrix
x(:,:,2) = m+1; Assign the entire matrix plus one to one of the planes in x.
In C++ you could use a std::vector of vectors, like
std::vector<std::vector<int>> matrix;
You don't need to use separate variables for the matrix values, why would you when you have the matrix?
I don't understand the reason you need to get all values where you evaluate true or false. Instead just put directly into a std::vector the coordinates where your condition evaluates to true:
std::vector<std::pair<int, int> true_values;
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[i].size(); j++)
{
if (some_condition_for_this_matrix_value(matrix[i][j], i, j) == true)
true_values.emplace_back(std::make_pair(i, j));
}
}
Now you have a vector of all matrix coordinates where your condition is true.
If you really want to have both true and false values, you could use a std::unordered_map with a std::pair containing the matrix coordinates as key and bool as value:
// Create a type alias, as this type will be used multiple times
typedef std::map<std::pair<int, int>, bool> bool_map_type;
bool_map_type bool_map;
Insert into this map all values from the matrix, with the coordinates of the matrix as the key, and the map value as true or false depending on whatever condition you have.
To get a list of all entries from the bool_map you can remove any false entries with std::remove_if:
std::remove_if(bool_map.begin(), bool_map.end(),
[](const bool_map_type::value_type& value) {
return value.second == false;
};
Now you have a map containing only entries with their value as true. Iterate over this map to get the coordinates to the matrix
Of course, I may totally have misunderstood your problem, in which case you of course are free to disregard this answer. :)
I know both C++ and Matlab (not Python) and in your case, I would really go for Matlab because it's way easier to use when you start programming (but don't forget to come back to C++ when you will find the limitations to Matlab).
In Matlab, you can define matrices very easily: just type the name of the matrix and the index you want to set:
m(1,1) = 1
m(2,2) = 1
gives you a 2x2 identity matrix (indices start with 1 in Matlab and entries are 0 by default). You can also define 3d matrices the same way:
x(1,2,3) = 2
For the import from Excel, it is possible if you save your excel file in CSV format, you can use the function dlmread to read it in Matlab. You could also try later to implement your algorithm directly in Matlab.
Finally, if you want to solve your binary integer programm, there is already a built-in function in Matlab, called bintprog which can solve it for you.
Hope it helps!