-
Notifications
You must be signed in to change notification settings - Fork 1
/
somanim-1d_001.c
175 lines (140 loc) · 3.55 KB
/
somanim-1d_001.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
Self-Organizing Map (1D)
2006.5.14 A.Date
Last modified 31 Jul 2029
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h> /* for usleep */
#define N_XUNITS 20
#define DIM_INPUT 1 /* dimension of input signal space */
double ALPHA=0.2; /* coefficients for neighborhood learning */
double SIGMA=0.8;
int SLEEP=100000; /* set small number if it is too slow. */
int N_LEARNING = 500;
int N_SUB_LEARNING = 10;
double X_RANGE=1.0;
double Y_RANGE=1.0;
double S[DIM_INPUT]; /* input signal */
double RV[N_XUNITS][DIM_INPUT]; /* reference vectors */
FILE *gp;
void som1d();
void init_reference();
void write_data_anim_d1();
/*
gnuplot can read data from standard input (without data file).
after "plot '-'", send data. gnuplot read data until 'e' appear.
*/
int main (int argc, char *argv[] )
{
int i,j,k;
double x,y;
long seed = 1234567; /* set your favorite number */
for (i=1; i<argc; i++) {
switch (*(argv[i]+1)) {
case 'r':
seed = atoi(argv[++i]);
break;
default:
fprintf(stderr, "Usage : %s\n",argv[0]);
fprintf(stderr, "\t-r : random-seed(%ld)\n",seed) ;
exit(0);
break;
}
}
srand48(seed);
gp = popen("gnuplot","w");
// fprintf(gp, "set term aqua\n"); // for mac
fprintf(gp, "set parametric\n");
fprintf(gp, "set style data linespoints\n");
fprintf(gp, "set xlabel \"neural fields\"\n");
fprintf(gp, "set xrange[-0.2:1.2]\n");
fprintf(gp, "set yrange[0:1]\n");
fprintf(gp, "set border 5\n");
fprintf(gp, "set x2tics 0,0.2,1\n");
fprintf(gp, "set noxtics\n");
fprintf(gp, "set noytics\n");
fprintf(gp, "set nokey\n");
fflush(gp);
init_reference();
for(i=0;i<N_LEARNING;i++){
fprintf(gp, "set title 't = %d/%d'\n", i*N_SUB_LEARNING, N_LEARNING*N_SUB_LEARNING);
fprintf(gp, "plot '-'\n");
for(j=0;j<N_SUB_LEARNING;j++){
som1d();
}
write_data_anim_d1();
fprintf(gp,"e\n");
fflush(gp);
usleep(SLEEP);
}
fclose(gp);
}
/* set initial connection */
void
init_reference(){
int i,k;
for (i=0; i < N_XUNITS; i++){
for (k=0; k<DIM_INPUT; k++){
// RV[i][k] = drand48();
RV[i][k] = (double)i/(double)N_XUNITS + (25.0/(double)N_XUNITS)*(drand48()-0.5);
}
}
}
void
som1d()
{
int i,k;
int argmin, d;
double tmp, min, denom, hci;
double sum = 0.0;
/* Choose an input x randomly. Change here if you want strange results */
S[0] = drand48()*X_RANGE;
/*
if ( drand48() > 0.5 ){
S[0] = 0.75 + 0.2*(drand48()-0.5);
}
else{
S[0] = 0.25 + 0.2*(drand48()-0.5);
}
*/
// printf("%.5lf\n",S[0]);
/* find the winner unit which has reference vector closest to the input */
for (k=0; k<DIM_INPUT; k++){
tmp = RV[0][k] - S[k];
sum += tmp*tmp;
}
argmin = 0;
min = sum;
for (i=0; i<N_XUNITS; i++){
sum = 0.0;
for (k=0; k<DIM_INPUT; k++){
tmp = RV[i][k] - S[k];
sum += tmp*tmp;
}
if ( sum < min ){
min = sum;
argmin = i;
}
}
/* neighborhood learning, c = argmin */
for (i=0; i<N_XUNITS; i++){
d = (i-argmin)*(i-argmin);
denom = 2.0*SIGMA*SIGMA;
hci = ALPHA*exp(-(double)d/denom);
for (k=0; k<DIM_INPUT; k++){
RV[i][k] = RV[i][k] + hci* (S[k] -RV[i][k]);
}
}
}
/* write data for gnuplot */
void
write_data_anim_d1(){
int i;
for (i=0; i<N_XUNITS; i++){
fprintf(gp, "%.5lf %.5lf\n", RV[i][0], 0.99);
fprintf(gp, "%.5lf %.5lf\n", (double)i/(double)N_XUNITS+0.01, 0.01);
fprintf(gp, "\n");
}
}