Skip to content

Instantly share code, notes, and snippets.

@fxfactorial
Created December 11, 2014 20:28
Show Gist options
  • Save fxfactorial/b488cff19104e316eba7 to your computer and use it in GitHub Desktop.
Save fxfactorial/b488cff19104e316eba7 to your computer and use it in GitHub Desktop.
How to make a smooth gif animation?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <sys/mman.h>
#include "perceptron.h"
double dot_product(float *a, float *b, int len)
{
double sum = 0;
for (int i = 0; i < len; i++)
sum += a[i] * b[i];
return sum;
}
struct sample_data* class_error(float *weights)
{
/* Pick a random sample, if our w vector would have made a
mistake, then that means we needed to have updated */
double result;
for (int i = 0; i < p.num_samples; i++) {
result = dot_product(weights, p.data[i].x, 3);
if ((result > 0 ? 1: -1) != p.data[i].label)
return &p.data[i];
}
return NULL;
}
void __setup_gnuplot(FILE *gp)
{
float a = -(p.v[1] / p.v[2]);
float b = -(p.v[0] / p.v[2]);
fprintf(gp, "set terminal gif animate delay 50\n");
fprintf(gp, "set output \"test.gif\"\n");
fprintf(gp, "set key outside\n");
fprintf(gp, "set xrange [-1:1]\n");
fprintf(gp, "set yrange [-1:1]\n");
fprintf(gp, "set style line 1 lc rgb 'blue' pt 7\n");
fprintf(gp, "set style line 2 lc rgb 'red' pt 7\n");
fprintf(gp, "a=%f\n", a);
fprintf(gp, "b=%f\n", b);
fprintf(gp, "c(x)=a*x + b\n");
fprintf(gp,
"plot c(x) title 'Target',"
" '-' u 1:2 w p ls 1 title 'Positive',"
" '-' u 1:2 w p ls 2 title 'Negative'\n");
/* Pretty inefficient, but I just don't know gnuplot all that well */
for (int i = 0; i < p.num_samples; i++)
if (p.data[i].label == 1)
fprintf(gp, "%f %f\n", p.data[i].x[1], p.data[i].x[2]);
fprintf(gp, "e\n");
for (int i = 0; i < p.num_samples; i++)
if (p.data[i].label == -1)
fprintf(gp, "%f %f\n", p.data[i].x[1], p.data[i].x[2]);
fprintf(gp, "e\n");
}
void run_percep(int save_plot)
{
float weights[] = {0, 0, 0};
struct sample_data *xs;
FILE *gp;
int iteration = 0;
/* Maybe refactor later with mmap*/
FILE *temp = fopen("temp.dat", "w+");
while ((xs = class_error(weights))) {
iteration++;
weights[0] = weights[0] + (xs->label * xs->x[0]);
weights[1] = weights[1] + (xs->label * xs->x[1]);
weights[2] = weights[2] + (xs->label * xs->x[2]);
fprintf(temp, "%f %f\n", weights[1], weights[2]);
}
fflush(temp);
rewind(temp);
gp = popen("gnuplot -persist", "w");
__setup_gnuplot(gp);
fprintf(gp, "h(x) = a*x + b\n");
fprintf(gp, "stats 'temp.dat' nooutput\n");
fprintf(gp, "N = int(STATS_records) - 1\n");
fprintf(gp, "do for [i=0:N]{\n");
fprintf(gp, "stats 'temp.dat' every ::i::i nooutput\n");
fprintf(gp, "a = STATS_min_x\n");
fprintf(gp, "b = STATS_min_y\n");
fprintf(gp, "plot h(x) with lines title sprintf(\"Iteration: %%d\", i)\n");
fprintf(gp, "}\n");
fclose(temp);
// unlink("temp.dat");
pclose(gp);
}
static void init_percep(int N)
{
int min = -1, max = 1;
float vs[4];
double dotp;
p.num_samples = N;
/* Setting up the target vector */
for (int i = 0; i < 4; i++)
vs[i] = ((float)arc4random() / ARC4RANDOM_MAX * (max - min)) + min;
p.v[0] = vs[2] * vs[1] - vs[0] * vs[3];
p.v[1] = vs[3] - vs[2];
p.v[2] = vs[0] - vs[1];
/* Setting up the sample data */
p.data = malloc(sizeof(struct sample_data) * N);
for (int i = 0; i < N; i++) {
p.data[i].x[0] = 1;
p.data[i].x[1] = ((float)arc4random() / ARC4RANDOM_MAX * (max - min)) + min;
p.data[i].x[2] = ((float)arc4random() / ARC4RANDOM_MAX * (max - min)) + min;
dotp = dot_product(p.v, p.data[i].x, 3);
if (dotp > 0)
p.data[i].label = 1;
else
p.data[i].label = -1;
}
}
int main (int argc, char **argv)
{
int n = 200;
init_percep(n);
run_percep(SAVE_PLOT);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment