Generating incomplete iterated function systems - c++

I am doing this assignment for fun.
http://groups.csail.mit.edu/graphics/classes/6.837/F04/assignments/assignment0/
There are sample outputs at site if you want to see how it is supposed to look. It involves iterated function systems, whose algorithm according the the assignment is:
for "lots" of random points (x0, y0)
for k=0 to num_iters
pick a random transform fi
(xk+1, yk+1) = fi(xk, yk)
display a dot at (xk, yk)
I am running into trouble with my implementation, which is:
void IFS::render(Image& img, int numPoints, int numIterations){
Vec3f color(0,1,0);
float x,y;
float u,v;
Vec2f myVector;
for(int i = 0; i < numPoints; i++){
x = (float)(rand()%img.Width())/img.Width();
y = (float)(rand()%img.Height())/img.Height();
myVector.Set(x,y);
for(int j = 0; j < numIterations;j++){
float randomPercent = (float)(rand()%100)/100;
for(int k = 0; k < num_transforms; k++){
if(randomPercent < range[k]){
matrices[k].Transform(myVector);
}
}
}
u = myVector.x()*img.Width();
v = myVector.y()*img.Height();
img.SetPixel(u,v,color);
}
}
This is how my pick a random transform from the input matrices:
fscanf(input,"%d",&num_transforms);
matrices = new Matrix[num_transforms];
probablility = new float[num_transforms];
range = new float[num_transforms+1];
for (int i = 0; i < num_transforms; i++) {
fscanf (input,"%f",&probablility[i]);
matrices[i].Read3x3(input);
if(i == 0) range[i] = probablility[i];
else range[i] = probablility[i] + range[i-1];
}
My output shows only the beginnings of a Sierpinski triangle (1000 points, 1000 iterations):
My dragon is better, but still needs some work (1000 points, 1000 iterations):

If you have RAND_MAX=4 and picture width 3, an evenly distributed sequence like [0,1,2,3,4] from rand() will be mapped to [0,1,2,0,1] by your modulo code, i.e. some numbers will occur more often. You need to cut off those numbers that are above the highest multiple of the target range that is below RAND_MAX, i.e. above ((RAND_MAX / 3) * 3). Just check for this limit and call rand() again.
Since you have to fix that error in several places, consider writing a utility function. Then, reduce the scope of your variables. The u,v declaration makes it hard to see that these two are just used in three lines of code. Declare them as "unsigned const u = ..." to make this clear and additionally get the compiler to check that you don't accidentally modify them afterwards.

Related

loop has no effect on specific array element

I'm trying to invert a 3x3 matrix. I gauss the augment that has both the original and the identity matrix. Depending on the matrix dimensions, the identity matrix is generated by a separate function with 1s along the main diagonal and 0s everywhere else. Once the operations are complete, the original matrix should be an identity and the identity should be the inverse. I'm able to successfully turn the original into an identity but the something is preventing the original identity from fully becoming the inverse which is confusing because both arrays are inside the same loops.
const int m = 3;
const int n = 3;
double matrix[m][n];
double ID[m][n] = {};
double pivot;
for(s = 1;s <= m;++s){
pivot = matrix[s-1][s-1];
k = s + 1;
for(i = n;i >= 1;--i){ // makes leading entries 1
ID[s-1][i-1] = ID[s-1][i-1]/pivot;
matrix[s-1][i-1] = matrix[s-1][i-1]/pivot;
}
for(j = k;j <= m;++j){ //converts to upper triangular
for(i = n;i >= 1;--i){
ID[j-1][i-1] = ID[j-1][i-1] - ID[s-1][i-1]*matrix[j-1][s-1]; //*****<--- has no effect on ID[2][0]
matrix[j-1][i-1] = matrix[j-1][i-1] - matrix[s-1][i-1]*matrix[j-1][s-1];
}
}
} //ID[2][0] = 0; <--- gives correct answer when uncommented
for(s = m;s >= 1;--s){
k = s - 1;
for(j = k;j >= 1;--j){ //makes entries above diagonal zero
for(i = 1;i <= n;++i){
ID[j-1][i-1] = ID[j-1][i-1] - ID[s-1][i-1]*matrix[j-1][s-1];
matrix[j-1][i-1] = matrix[j-1][i-1] - matrix[s-1][i-1]*matrix[j-1][s-1];
}
}
}
Here's the process by hand, the big arrow points to where I believe my code is getting stuck. ID[2][0] remains as -1 which in turn prevents ID[0][0] from being set to -3 over the final loop.
method with correct result
result without forcing ID(2)[0] to 0
result forcing ID(2)[0] to 0
I don't understand what is going wrong as the loop works fine on matrix[m][n].

Eigen: random binary vector with t 1s

I want to compute K*es where K is an Eigen matrix (dimension pxp) and es is a px1 random binary vector with 1s.
For example if p=5 and t=2 a possible es is [1,0,1,0,0]' or [0,0,1,1,0]' and so on...
How do I easily generate es with Eigen?
I came up with even a better solution, which is a combination of std::vector, Egien::Map and std::shuffle.
std::vector<int> esv(p,0);
std::fill_n(esv.begin(),t,1);
Eigen::Map<Eigen::VectorXi> es (esv.data(), esv.size());
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(std::begin(esv), std::end(esv), g);
This solution is memory efficient (since Eigen::Map doesn't copy esv) and has the big advantage that if we want to permute es several times (like in this case), then we just need to repeat std::shuffle(std::begin(esv), std::end(esv), g);
Maybe I'm wrong, but this solution seems more elegant and efficient than the previous ones.
So you're using Eigen. I'm not sure what matrix type you're using, but I'll go off the class Eigen::MatrixXd.
What you need to do is:
Create a 1xp matrix that's all 0
Choose random spots to flip from 0 to 1 that are between 0-p, and make sure that spot is unique.
The following code should do the trick, although you could implement it other ways.
//Your p and t
int p = 5;
int t = 2;
//px1 matrix
MatrixXd es(1, p);
//Initialize the whole 1xp matrix
for (int i = 0; i < p; ++i)
es(1, i) = 0;
//Get a random position in the 1xp matrix from 0-p
for (int i = 0; i < t; ++i)
{
int randPos = rand() % p;
//If the position was already a 1 and not a 0, get a different random position
while (es(1, randPos) == 1)
randPos = rand() % p;
//Change the random position from a 0 to a 1
es(1, randPos) = 1;
}
When t is close to p, Ryan's method need to generate much more than t random numbers. To avoid this performance degrade, you could solve your original problem
find t different numbers from [0, p) that are uniformly distributed
by the following steps
generate t uniformly distributed random numbers idx[t] from [0, p-t+1)
sort these numbers idx[t]
idx[i]+i, i=0,...,t-1 are the result
The code:
VectorXi idx(t);
VectorXd es(p);
es.setConstant(0);
for(int i = 0; i < t; ++i) {
idx(i) = int(double(rand()) / RAND_MAX * (p-t+1));
}
std::sort(idx.data(), idx.data() + idx.size());
for(int i = 0; i < t; ++i) {
es(idx(i)+i) = 1.0;
}

Computing DFT by definition with C++

I'm trying to compute DFT and its inversion, for now by simplest method possible, but it keeps not working. And what's worse, I'm not sure of it. Here is my code:
(realnum is double, freq_func and time_func are vectors of complex)
freq_func toFreq(const time_func & waveform)
{
freq_func res;
res.resize(waveform.size());
const realnum N = spectrum.size();
for (size_t k = 0; k < waveform.size(); k++)
for (size_t n = 0; n < waveform.size(); n++)
res[k] += waveform[n] * exp(complex(0, -2*PI*n*k/N));
return res;
}
time_func toTime(const freq_func & spectrum)
{
freq_func res;
res.resize(spectrum.size());
const realnum N = spectrum.size();
for (size_t n = 0; n < spectrum.size(); n++)
{
for (size_t k = 0; k < spectrum.size(); k++)
res[n] += spectrum[k] * exp(complex(0, 2*PI*n*k/N));
res[n] /= N;
}
return res;
}
Why does it never hold a = toTime(toFreq(a)) nor a = toFreq(toTime(a))? Why does toTime return results with considerable imaginary parts? Or should it? Some of online calculators do. And why does Wikipedia claim, that dividing by N can be moved to toFreq, or even substituted by dividing both by 1/sqrt(N), shouldn't there be only one possible definition?
The expression complex(0, 2*PI*n*k/N) creates and initializes a complex number with real part set to 0 and imaginary part set to 2*PI*n*k/N. To implement the DFT, you'd really want to be using a complex number whose magnitude is 1, and phase is 2*PI*n*k/N. You can do this with:
complex(polar(1,2*PI*n*k/N))
for the forward transform, and
complex(polar(1,-2*PI*n*k/N))
for the inverse transform.
As far as the Wikipedia claim is concerned, it is simply a question of definition of the DFT. Different implementations can choose different definitions and hence scaling by different factors. Normalized DFTs will choose the forward and inverse transform such that a round trip produced the original sequence (e.g. x == toTime(toFreq(x))). Other non-normalized DFTs may choose a different scaling (e.g. to save a few scaling operations when the scale is not important to the application at hand).

Reorganizing a vector in c++

I'd like to preface this question with the fact that I am very inexperienced when it comes to coding, so the solution to this problem could be much easier than what I have been trying. I have a vector 'phas' defined as vector<float> phase; that has 7987200 elements and I want to rearrange this vector into 133120 vectors of 60 elements (called line2 defined as vector<long double> line2;). Each vector of 60 should then be placed one after the other in a vector of vectors 'RFlines2' defined as vector< vector<long double> > RFlines2;and RFlines2.resize(7987200);. I want to fill each of the 60 element vectors with elements of 'phas' separated by 128. for example, the first vector of 60 elements would be filled with phas[0], phas[128], phas[256], ... phas[7680]. The second vector of 60 would then be filled with phas[1], phas[129], phas[257], ... phas[7681],...etc. My current code is as follows:
for(int x = 0; x<133120; x++){
if((x == 128 || x == 7680+128 || x == (7680*a)+128)){
x = 7680*a;
a = a + 1;
}
int j = x;
for(int i = 0; i<60;i++){
line2.pushback(i);
line2[i] = phas[j];
j = j + 128;
}
cout<<"This is x: "<<x<<endl;
RFlines2[x] = line2;
line2.clear();
}
however, after 128 iterations of the outter loop (128 vectors of 60 have been created and 7680 elements from phas have been used), I would need the x value to jump to 7680 to avoid putting elements from phas that have already been used into the next vector of 60 since when x = 128 the first element of the next vector of 60 would be phase[128], which was already used as the 2nd element of the first vector of 60. And then after another 128 x iterations, I would need the x value to jump to 15,360 and so on. The code above is my latest attempt, but when I try to do the fftw on each vector of 60 in RFlines2 as follows:
int c = 0;
for(int x = 0; x < 133120; x++){
//cout<<x<<endl;
fftw_plan p2;
inter = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * W);
outter = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * W);
/* cast elements in line to type fftw_complex */
for (int i = 0; i <60; i++) {
//cout<<i<<endl;
//inter[i][0] = phas[i];
//inter[x][0] = zlines[x];
inter[i][0] = RFlines2[x][i];
inter[i][1] = 0;
}
p2 = fftw_plan_dft_1d(60, inter, outter, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(p2);
//inter[x][0].clear();
for(int u = 0; u<60;u++){
if(u == 0){
cout<<' '<<outter[0][0]<<' '<<c++<<endl;
}
}
fftw_free(inter);
fftw_free(outter);
fftw_destroy_plan((p2));
}
the program crashes after displaying outer[0][0] 128 times. Any ideas how to fix this? Also, let me know if anything that I said doesn't make sense and I'll try to clarify. Thanks in advance!
-Mike
I don't know why your code crashes, because I can't see the whole code here. But I'm going to suggest a way to scatter your data and manage your vectors.
(There is an important caveat though: you should not be using vectors (at least not vectors of vectors) for this task; you are better off using 1D vectors and managing the 2D indexing yourself. But this is a performance thing, and does not impact correctness.)
This is how I suggest you fill your RFLines2: (I have not tried this code, so it may not work.)
// first, build the memory for RFLines2...
vector<vector<long double>> RFLines2 (133120, vector<long double>(60));
// assuming a "phase" vector...
for (unsigned i = 0; i < 7987200; ++i)
{
unsigned const row = (i / (128 * 60)) * 128 + (i % (128 * 60)) % 128;
unsigned const col = (i % (128 * 60)) / 128;
RFLines[row][col] = phase[i];
}
You won't need the line2 intermediate this way.
The rest of the code "should" work. (BTW, I don't understand the inner for loop on u at all. What were you trying to do there?)

Find a centroid of a dataset

If I have some random data set let's say
X Y
1.2 16
5.7 0.256
128.54 6.879
0 2.87
6.78 0
2.98 3.7
... ...
x' y'
How can I find the centroid coordinates of this data set?
p.s. Here what I tried but got wrong results
float Dim1[K];
float Dim2[K];
float centroidD1[K];
float centroidD2[K];
int K = 4;
int counter[K];
for(int i = 0; i < K ; i++)
{
Dim1[i] = 0;
Dim2[i] = 0;
counter[i] = 0;
for(int j = 0; j < hash["Cluster"].size(); j++)
{
if(hash["Cluster"].value(j) == i+1)
{
Dim1[i] += hash["Dim_1"].value(j);
Dim2[i] += hash["Dim_2"].value(j);
counter[i]++;
}
}
}
for(int l = 0; l < K; l++)
{
centroidD1[l] = Dim1[l] / counter[l];
centroidD2[l] = Dim2[l] / counter[l];
}
I guess I choose wrong algorithm for doing it, as I get wrong results.
Calculating a sum and dividing by N is not a good idea if you have a large data set. As your floating point accumulator grows adding a new point eventually stop working due to the magnitude difference. An incremental formula might work better, see: https://math.stackexchange.com/questions/106700/incremental-averageing
If the issue is too large a data set you can verify the basic functioning of your code by using a smaller data set with a hand verified result. For example, just 1 data point, or 10 data points.