Implementing 4-dimensional Halton Sequence - c++

The psuedocode for the Halton sequnce can be found here. I wrote a function that does this but for some reason checking the Matlab results for the 4th dimensional Halton sequence my numbers do not match up and I am not sure why. Here is my code:
double Halton_Seq(int index, double base){
double f = 1, r;
while(index > 0){
f = f/base;
r = r + f*(fmod(index,base));
index = index/base;
}
return r;
}
Here are the first 10 results I get:
1
0.25
0.5
0.75
0.0625
0.3125
0.5625
0.8125
0.125
0.375
Here is the first 10 results MATLAB gets:
Columns 1 through 2
0 0.5000
Columns 3 through 4
0.2500 0.7500
Columns 5 through 6
0.1250 0.6250
Columns 7 through 8
0.3750 0.8750
Columns 9 through 10
0.0625 0.5625

You forgot to initialize r in line 2.
r = 0;
double Halton_Seq(int index, int base){
double f = 1, r = 0;
while(index > 0){
f = f/base;
r = r + f* (index% base);
index = index/base;
}
return r;
}
// Output for 10 (base 2)
0.000000
0.500000
0.250000
0.750000
0.125000
0.625000
0.375000
0.875000
0.062500
0.562500

Related

Comput modulo between floating point numbers in C++

I have the following code to compute modulo between two floating point numbers:
auto mod(float x, float denom)
{
return x>= 0 ? std::fmod(x, denom) : denom + std::fmod(x + 1.0f, denom) - 1.0f;
}
It does only work partially for negative x:
-8 0
-7.75 0.25
-7.5 0.5
-7.25 0.75
-7 1
-6.75 1.25
-6.5 1.5
-6.25 1.75
-6 2
-5.75 2.25
-5.5 2.5
-5.25 2.75
-5 3
-4.75 -0.75 <== should be 3.25
-4.5 -0.5 <== should be 3.5
-4.25 -0.25 <== should be 3.75
-4 0
-3.75 0.25
-3.5 0.5
-3.25 0.75
-3 1
-2.75 1.25
-2.5 1.5
-2.25 1.75
-2 2
-1.75 2.25
-1.5 2.5
-1.25 2.75
-1 3
-0.75 3.25
-0.5 3.5
-0.25 3.75
0 0
How to fix it for negative x. Denom is assumed to be an integer greater than 0. Note: fmod as is provided by the standard library is broken for x < 0.0f.
x is in the left column, and the output is in the right column, like so:
for(size_t k = 0; k != 65; ++k)
{
auto x = 0.25f*(static_cast<float>(k) - 32);
printf("%.8g %.8g\n", x, mod(x, 4));
}
Note: fmod as is provided by the standard library is broken for x < 0.0f
I guess you want the result to always be a positive value1:
In mathematics, the result of the modulo operation is an equivalence class, and any member of the class may be chosen as representative; however, the usual representative is the least positive residue, the smallest non-negative integer that belongs to that class (i.e., the remainder of the Euclidean division).
The usual workaround was shown in Igor Tadetnik's comment, but that seems not enough.
#IgorTandetnik That worked. Pesky signed zero though, but I guess you cannot do anything about that.
Well, consider this(2, 3):
auto mod(double x, double denom)
{
auto const r{ std::fmod(x, denom) };
return std::copysign(r < 0 ? r + denom : r, 1);
}
1) https://en.wikipedia.org/wiki/Modulo
2) https://en.cppreference.com/w/cpp/numeric/math/copysign
3) https://godbolt.org/z/fdr9cbsYT

how to calculate multiset of elements given probability on each element?

let say I have a total number
tN = 12
and a set of elements
elem = [1,2,3,4]
and a prob for each element to be taken
prob = [0.0, 0.5, 0.75, 0.25]
i need to get a random multiset of these elements, such as
the taken elements reflects the prob
the sum of each elem is tN
with the example above, here's some possible outcome:
3 3 2 4
2 3 2 3 2
3 4 2 3
2 2 3 3 2
3 2 3 2 2
at the moment, maxtN will be 64, and elements the one above (1,2,3,4).
is this a Knapsack problem? how would you easily resolve it? both "on the fly" or "pre-calculate" approch will be allowed (or at least, depends by the computation time). I'm doing it for a c++ app.
Mission: don't need to have exactly the % in the final seq. Just to give more possibility to an elements to be in the final seq due to its higher prob. In few words: in the example, i prefer get seq with more 3-2 rather than 4, and no 1.
Here's an attempt to select elements with its prob, on 10 takes:
Randomizer randomizer;
int tN = 12;
std::vector<int> elem = {2, 3, 4};
std::vector<float> prob = {0.5f, 0.75f, 0.25f};
float probSum = std::accumulate(begin(prob), end(prob), 0.0f, std::plus<float>());
std::vector<float> probScaled;
for (size_t i = 0; i < prob.size(); i++)
{
probScaled.push_back((i == 0 ? 0.0f : probScaled[i - 1]) + (prob[i] / probSum));
}
for (size_t r = 0; r < 10; r++)
{
float rnd = randomizer.getRandomValue();
int index = 0;
for (size_t i = 0; i < probScaled.size(); i++)
{
if (rnd < probScaled[i])
{
index = i;
break;
}
}
std::cout << elem[index] << std::endl;
}
which gives, for example, this choice:
3
3
2
2
4
2
2
4
3
3
Now i just need to build a multiset which sum up to tN. Any tips?

A many-to-one mapping in the natural domain using discrete input variables?

I would like to find a mapping f:X --> N, with multiple discrete natural variables X of varying dimension, where f produces a unique number between 0 to the multiplication of all dimensions. For example. Assume X = {a,b,c}, with dimensions |a| = 2, |b| = 3, |c| = 2. f should produce 0 to 12 (2*3*2).
a b c | f(X)
0 0 0 | 0
0 0 1 | 1
0 1 0 | 2
0 1 1 | 3
0 2 0 | 4
0 2 1 | 5
1 0 0 | 6
1 0 1 | 7
1 1 0 | 8
1 1 1 | 9
1 2 0 | 10
1 2 1 | 11
This is easy when all dimensions are equal. Assume binary for example:
f(a=1,b=0,c=1) = 1*2^2 + 0*2^1 + 1*2^0 = 5
Using this naively with varying dimensions we would get overlapping values:
f(a=0,b=1,c=1) = 0*2^2 + 1*3^1 + 1*2^2 = 4
f(a=1,b=0,c=0) = 1*2^2 + 0*3^1 + 0*2^2 = 4
A computationally fast function is preferred as I intend to use/implement it in C++. Any help is appreciated!
Ok, the most important part here is math and algorythmics. You have variable dimensions of size (from least order to most one) d0, d1, ... ,dn. A tuple (x0, x1, ... , xn) with xi < di will represent the following number: x0 + d0 * x1 + ... + d0 * d1 * ... * dn-1 * xn
In pseudo-code, I would write:
result = 0
loop for i=n to 0 step -1
result = result * d[i] + x[i]
To implement it in C++, my advice would be to create a class where the constructor would take the number of dimensions and the dimensions itself (or simply a vector<int> containing the dimensions), and a method that would accept an array or a vector of same size containing the values. Optionaly, you could control that no input value is greater than its dimension.
A possible C++ implementation could be:
class F {
vector<int> dims;
public:
F(vector<int> d) : dims(d) {}
int to_int(vector<int> x) {
if (x.size() != dims.size()) {
throw std::invalid_argument("Wrong size");
}
int result = 0;
for (int i = dims.size() - 1; i >= 0; i--) {
if (x[i] >= dims[i]) {
throw std::invalid_argument("Value >= dimension");
}
result = result * dims[i] + x[i];
}
return result;
}
};

fftw and online DFT calculator get different results

I calculated the FFT of array {1,2,3,4,5,6} with fftw/C++ and an online calculator (http://calculator-fx.com/calculator/fast-fourier-transform-calculator-fft/1d-discrete-fourier-transform). And the results seemed to be a bit different.
fftw output:
0 21.000000 0.000000
1 -3.000000 5.196152
2 -3.000000 1.732051
3 -3.000000 0.000000
4 0.000000 0.000000
5 0.000000 0.000000
Online calculator output:
21 + 0j
-3 + 5.196152j
-3 + 1.732051j
-3 + 0j
-3 - 1.732051j
-3 - 5.196152j
As is shown above, the latter two results of fftw turned to be zero.
Can't figure out why. Could anybody help me out? Thanks.
[EDITED]
cpp code:
int main()
{
fftw_complex *out;
fftw_plan plan;
double arr[]={1,2,3,4,5,6};
int n = sizeof(arr)/sizeof(double);
out = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * n );
plan = fftw_plan_dft_r2c_1d ( n, arr, out, FFTW_ESTIMATE );
fftw_execute ( plan );
for (int i = 0; i < n; i++ )
{
printf ( " %3d %12lf %12lf\n", i, out[i][0], out[i][1] );
}
fftw_free(out);
fftw_destroy_plan(plan);
return 0;
}
Oh, you're using the R2C mode (don't know why I didn't think of that before). That only writes n/2 + 1 results, because of the symmetry.
This behaviour is documented: http://www.fftw.org/doc/One_002dDimensional-DFTs-of-Real-Data.html.

How to make a complete matrix with 2 loops in c++

I have a string in c++ and it represents an upper triangular matrix, What I want to do is meake a complete matrix from this string
std::string input = "1,2,1,3,6,1,4,7,9,1";
//this represents
//1 2 3 4
//2 1 6 7
//3 6 1 9
//4 7 9 1
std::replace(input.begin(), input.end(), ',', ' ');
std::vector<double> Matrix;
std::istringstream inputStream(input);
double value;
int rowNum = 0;
int colNum = 0;
while (inputStream >> value){
for (colNum = 0; colNum < 2; colNum++){
if (colNum >= rowNum){
Matrix.push_back( value );
}
else{
Matrix.push_back( Matrix[colNum * 2 + rowNum]);
}
}
rowNum++;
}
inputStream >> std::ws;
Instead of getting
1 2 3 4
2 1 6 7
3 6 1 9
4 7 9 1
But I am getting
1.0000 1.0000 1.0000 2.0000
1.0000 1.0000 2.0000 1.0000
1.0000 2.0000 1.0000 1.0000
2.0000 1.0000 1.0000 2.0000
What is it my error? I can not see it...
You should show the indexing scheme used for printing the output (i.e. how do you expect the indexes works): your choice of using a vector instead of a matrix make hard to correct the code. For sure, I see the following points that have no clear connection with the input pattern:
1) each number you read you increment the rowNum index. The row should be incremented instead at 'steps' 1, 1+2, 1+2+3,...
2) colNum should range from 0 to current rowNum, instead assumes just 0,1
3) there is no chance to fill a row (say the first) before you read (say the last). You could do if the input would be 1 2 3 4 1 6 7 1 9 1
all these points are related, and origin from the wrong data representation, that make difficult a trivial task.
In C++, a very effective way to tackle these problems is data hiding: consider how easily we can write a class that gives the correct logical representation and doesn't waste space:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
template <class T = double>
class upper_triangular_matrix
{
std::vector<T> Matrix;
public:
upper_triangular_matrix(std::string input)
{
// trade time for space: store the values, compute indexing
std::replace(input.begin(), input.end(), ',', ' ');
std::istringstream inputStream(input);
T value;
while (inputStream >> value)
Matrix.push_back(value);
// validate size: ok 1,1+2,1+2+3 etc
}
T operator()(int r, int c) const
{
// compute indexing accounting for miss duplicated
if (c > r)
std::swap(c, r);
int p = 0, n = 1;
while (r > 0)
{
p += n++;
r--;
}
return Matrix[p + c];
}
};
int main()
{
upper_triangular_matrix<> m("1,2,1,3,6,1,4,7,9,1");
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 4; ++c)
std::cout << m(r, c) << ' ';
std::cout << std::endl;
}
}
when run, this prints
1 2 3 4
2 1 6 7
3 6 1 9
4 7 9 1
It is hard to tell exactly where the error is but here is where it starts:
std::vector<double> Matrix;
Yes, a non-empty std::vector<double> with n elements is a matrix: either a 1xn or a nx1 matrix (or both). In your context this view is, however, utterly unhelpful.
Let's look at the for-loop when you read the first element:
colNum == 0, rowNum == 0 => (1, 1) = Matrix[0] = 1
colNum == 1, rowNum == 0 => (2, 1) = Matrix[1] = 1
This start is clearly wrong. After this rowNum becomes 1:
colNum == 0, rowNum == 1 => (3, 1) = Matrix[2] = Matrix[colNum * 2 + rowNum] = Matrix[1] = 1
colNum == 1, rowNum == 1 => (4, 1) = Matrix[3] = 2
Well, I guess you can write the remainder up yourself. Of course, I could quickly write the code to solve your problem but I think this little exercise is for you. The way to do it is to fill the first row columns (where row is the current row being processed, using conventional index starting with 0) with the values from the transposed matrix and then read the remaining n - row columns (where n is the size of the matrix) from the file.