Related
I am playing around with xtensor and I just wanted to perform a simple operation to select rows with specific column values. Imagine I've the following array.
[
[0, 1, 1, 3, 4 ]
[0, 2, 1, 5, 6 ]
[0, 3, 1, 3, 2 ]
[0, 4, 1, 5, 7 ]
]
Now I want to select the rows where col2 and col4 has value 3. Which in this case is row 3.
[0, 3, 1, 3, 2 ]
I want to achieve similar to what this answer has achieved.
How can I achieve this in xtensor?
The way to go is to slice with the columns you need, and then look where the condition is true for all columns.
For the latter an overload for xt::all(...) is seemingly not implemented (yet!), but we can use xt::sum(..., axis) to achieve the same:
#include <xtensor/xtensor.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/xio.hpp>
int main()
{
xt::xtensor<int,2> a =
{{0, 1, 1, 3, 4},
{0, 2, 1, 5, 6},
{0, 3, 1, 3, 2},
{0, 4, 1, 5, 7}};
auto test = xt::equal(xt::view(a, xt::all(), xt::keep(1, 3)), 3);
auto n = xt::sum(test, 1);
auto idx = xt::flatten_indices(xt::argwhere(xt::equal(n, 2)));
auto b = xt::view(a, xt::keep(idx), xt::all());
std::cout << b << std::endl;
return 0;
}
My goal is to create a general function that creates a two-dimensional vector filled with permutations (vector) based on a template given and on parameters, as follows:
some positions of the vector have to be fixed, based on a template as a function parameter vector. For example, if the given template is {0, 1, 0, -1, 3, -1}, this means that permutations will only vary by the numbers in places of -1.
n. n-1 is the range of integers the permutation can include. E.g. if n = 4, only 0, 1, 2, 3 can appear in the vector
length, which is the length of the vector
Note, that if a number from the template already appears in it, it will not be generated in the permutations.
So, to give an example:
n = 6, length = 5, template = {2, 1, 0, -1, 0, -1}
the permutations are:
{2, 1, 0, 3, 0, 3}
{2, 1, 0, 3, 0, 4}
{2, 1, 0, 3, 0, 5}
{2, 1, 0, 4, 0, 3}
{2, 1, 0, 4, 0, 4}
{2, 1, 0, 4, 0, 5}
{2, 1, 0, 5, 0, 3}
{2, 1, 0, 5, 0, 4}
{2, 1, 0, 5, 0, 5}
As you can see, the numbers are only generated in indexes 3 and 5 (places, where it was -1), also, the places to do not include 0, 1 or 2, since they already appear in the template.
I need to generate these permutations without using the <algorithm> library.
I assume creating a recursive function is the best option, but I do not know how to move forward. Any suggestions would help.
Thanks
Since you've offered no visible attempt, I assume it might be helpful for you to study some working code. This is in JavaScript (I hope it's producing the expected output). I hope it can help give you some ideas you could translate to C++.
function f(template){
console.log(JSON.stringify(template));
var used = template.reduce((acc, x) => { if (x != -1) acc.add(x); return acc; }, new Set());
console.log(`used: ${Array.from(used)}`);
var needed = new Set(template.reduce((acc, x, i) => { if (!used.has(i)) acc.push(i); return acc; }, []));
console.log(`needed: ${Array.from(needed)}`);
var indexes = template.reduce((acc, x, i) => { if (x == -1) return acc.concat(i); else return acc; }, []);
console.log(`indexes: ${indexes}`);
function g(needed, indexes, template, i=0){
if (i == indexes.length)
return [template];
var result = [];
// Each member of 'needed' must appear in
// each position, indexes[i]
for (x of needed){
let _template = template.slice();
_template[ indexes[i] ] = x;
result = result.concat(
g(needed, indexes, _template, i + 1));
}
return result;
}
return g(needed, indexes, template);
}
var template = [2, 1, 0, -1, 0, -1];
var result = f(template);
var str = '\n';
for (let r of result)
str += JSON.stringify(r) + '\n';
console.log(str);
For scientific purposes (code research) I am using Mathematica to enumerate all periodic sequences of some linear recurrences. As an example the command
Table[{Mod[i * 2^n + j * 4^n + k * 6^n, 7] },{i, 0, 5}, {j, 0, 5}, {k, 0, 5}, {n, 0, 5}]
allows to enumerate all 216 distinct periodic sequences of linear recurrent sequences in a finite field of order 7 (or mod 7) with characteristic polynomial whose roots are 2,4 and 6. The first five sequences it produces are:
{0, 0, 0, 0, 0, 0}, {1, 6, 1, 6, 1, 6}, {2, 5, 2, 5, 2, 5}, {3, 4, 3, 4, 3, 4}, {4, 3, 4, 3, 4, 3}, …
I have two questions:
i) The first sequence is obtained when i=0,j=0,k=0; the second when i=0,j=0,k=1, the third when i=0,j=0,k=2, etc. Is there a way to join these numbers with the sequence they generate so that I will get to know these parameters and therefore to be able to, later (if needed), generate a particular sequence? That is I would like that the output would be something like this
{{0, 0, 0, 0, 0, 0}, {0, 0, 0}}, {{1, 6, 1, 6, 1, 6}, {0, 0, 1}}, {{2, 5, 2, 5, 2, 5}, {0, 0, 2}} , etc.
ii) In the example above (3rd order linear recurrence, and mod 7) the number of sequences obtained (216) is manageable by hand; but this number grows very quickly when the linear recurrence has order higher than 3 and the field has characteristic higher than 7. And, in those cases, most of the sequences that are produced are of no interest to me. I think that I could throw away at least 99% of the sequences that do not interest me if I could add an instruction that would read the output (the sequences obtained) and would say “I only want the sequences such that the products of its elements is 216 (say)”: from the five sequences above only {1, 6, 1, 6, 1, 6} would remain because 1x6x1x6x1x6=216$; or “I only want the sequences such that the products of its elements is 216 or 1000 (say)” from the five sequences above {1, 6, 1, 6, 1, 6} and {2, 5, 2, 5, 2, 5} would remain because 1x6x1x6x1x6 = 216 and 2x5x2x5x2x 5=1000.
Is it possible to do this? I tried some list and tables manipulation, but had no success.
Thank you in advance.
here is the first part..
Flatten[Table[{Table[Mod[i*2^n + j*4^n + k*6^n, 7], {n, 0, 5}], {i, j,
k}}, {i, 0, 5}, {j, 0, 5}, {k, 0, 5}], 2]
{{{0, 0, 0, 0, 0, 0}, {0, 0, 0}}, {{1, 6, 1, 6, 1, 6}, {0, 0,
1}}, {{2, 5, 2, 5, 2, 5}, {0, 0, 2}}, {{3, 4, 3, 4, 3, 4}, {0, 0,
3}},...
better way:
{Table[Mod[#.{2, 4, 6}^n, 7], {n, 0, 5}],#} & /# Tuples[Range[0, 5], {3}]
example finding cases with a specified product:
Reap[Do[
s = Table[Mod[i*2^n + j*4^n + k*6^n, 7], {n, 0, 5}];
If[Times ## s == 81, Sow[{s, {i, j, k}}]],
{i, 0, 5}, {j, 0, 5}, {k, 0, 5}]][[2, 1]]
{{{3, 3, 1, 3, 3, 1}, {1, 2, 0}}, {{3, 1, 3, 3, 1, 3}, {2, 1,
0}}, {{1, 3, 3, 1, 3, 3}, {4, 4, 0}}}
Lets say I have an array A of size n, where 0 <= A[i] <= n.
Lets say I have 2 arrays Forward and Backward, size n, where:
Forward[i] = index j where
A[j] = min(A[i], A[i+1], ..., A[n-1])
and
Backward[i] = index j where
A[j] = min(A[i], A[i-1], ..., A[0])
My question is:
given A, Forward and Backward
given 2 indexes l and r
Can I discover the index k such that A[k] = min(A[l], A[l+1], ..., A[r]) in constant time?
No. Atleast not in O(1) time. A counter example is as follows. 0-based indexing is used here. Let
index = {0, 1, 2, 3, 4, 5, 6, 7, 8}
A = {1, 3, 5, 7, 9, 6, 4, 2, 0}
Forward = {8, 8, 8, 8, 8, 8, 8, 8, 8}
Backward = {0, 0, 0, 0, 0, 0, 0, 0, 8}
Now, if I ask you to get the index of the minimum value in range [3, 7], how will you do it?
Basically they will be of no use to find in the range [a, b]
if forward[a] > b and backward[b] < a.
No you cant. A counter example is:
A = {0, 4, 3, 2, 3, 4, 0}
Forward = {6, 6, 6, 6, 6, 6, 6}
Backward = {0, 0, 0, 0, 0, 0, 0}
l = 1, k = 5
ie Forward and Backward are of no use in that case and you have to search the array which is O(k-l).
I have created a Table of values known as "value1". The "value1" is nothing but a z co-ordinate values alternatively can be called "zone" . These values depending upon the x co-ordinate and y co-ordinate given as "x" and "y" respectively.
The code is give below
value1 = Table[{(10*(Cos[((x - 75)*2*3.14159)/
200]^2)*(Cos[((y - 75)*2*3.14159)/200]^2)) +
20}, {y, 0, 20, 5}, {x, 0, 20, 5}]
The output of "value1" or "zone" is
{{22.5}, {21.7274}, {21.0305}, {20.4775}, {20.1224}}, {{21.7274}, and so on
I have another table of values known as "value 2". This table also gives me a different z co-ordinate value it can be alternatively called "ztwo" . This values also depends upon the x and y co-ordinates defined by "x" and "y" respectively.
Note the z value is generated defined by the expression given below
(((70 - ((10*(Cos[((x - 75)*2*3.14159)/
200]^2)*(Cos[((y - 75)*2*3.14159)/200]^2)) +
20))*0.3333))
I have used the above expression in the table below to generate the "ztwo" values
value2 = Table[{x,y, (((70 - ((10*(Cos[((x - 75)*2*3.14159)/
200]^2)*(Cos[((y - 75)*2*3.14159)/200]^2)) +
20))*0.3333))}, {y, 0, 20, 5}, {x, 0, 20, 5}]
Output of "value2"
{{{0, 0, 15.8318}, {5, 0, 16.0892}, {10, 0, 16.3215}, {15, 0, 16.5059}, {20, 0, 16.6242}}, {{0, 5, 16.0892}, {5, 5,16.2672}, {10, 5, 16.4277}, {15, 5, 16.555},and so on
As you can see from above the "value2" is in form of
{x1,y1,ztwo1},{x2,y2,ztwo2},{x3,y3,ztwo3}..and so on
I want to create a table of values know as "value3" which is basically the addition z values from "value 1" known to us as "zone" to ONLY the z values of "value2" known to us as "ztwo" to get the table "value3". In table "value3" only the z values change but it SHOULD be expressed as in form below
{0,0,38.3317},{5,0,37.5592},{10,0,36.8623} and so on
Explanation: How do I get the above??
this is the "zone" values:
{{22.5}, {21.7274}, {21.0305}, {20.4775}, {20.1224}}, {{21.7274}, and so on
Below is "ztwo" values but expressed in{x,y,z} format
{{{0, 0, 15.8318}, {5, 0, 16.0892}, {10, 0, 16.3215}, {15, 0, 16.5059},
{20,0,16.6242}}, {{0, 5, 16.0892} and so on
Now I want a table of "value 3" whose z values change since it is the addition of
corresponding z co-ordinate values from table "value1" and table "value2"
{0,0,15.8318+22.5},{5,0,16.0892+21.7274},{10,0,16.3215+36.8623} and so on
Which will lead to the desired, ideal output like this:
{0,0,38.3317},{5,0,37.5592},{10,0,36.8623} and so on
Question
How Do I create the Table "Value3" which give me the desired output by adding the corresponding z values from table "value1" to table "value2"
You have a small typo in your code... there should be a comma between y and (((70 - ... in the definition of value2 in order to get the result that you posted below.
Fixing that, you can do the following to get your result:
value3 = value2;
value3[[All, All, 3]] += value1[[All, All, 1]];
EDIT:
The code above does the addition the way you want it. I think the confusion is because you want each of the three coordinates as a list instead of a matrix. For that, you simply need to Flatten the list at Level 1.
Flatten[value3, 1]
Out[1]= {{0, 0, 38.3317}, {5, 0, 37.8167}, {10, 0, 37.3521}, {15, 0,
36.9833}, {20, 0, 36.7466}, {0, 5, 37.8167}, {5, 5, 37.4608}, {10,
5, 37.1397}, {15, 5, 36.885}, {20, 5, 36.7214}, {0, 10,
37.3521}, {5, 10, 37.1397}, {10, 10, 36.9482}, {15, 10,
36.7962}, {20, 10, 36.6986}, {0, 15, 36.9833}, {5, 15, 36.885}, {10,
15, 36.7962}, {15, 15, 36.7258}, {20, 15, 36.6806}, {0, 20,
36.7466}, {5, 20, 36.7214}, {10, 20, 36.6986}, {15, 20,
36.6806}, {20, 20, 36.669}}