CLIENTE.C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <math.h>
#define P_SIZE sizeof(struct pmensaje)
#define P_SIZE_2 sizeof(struct pneurona)
struct pneurona{
int idNeurona;
double valores[3];
double pesos[3];
};
struct pmensaje{
int mensaje; //tipo de operacion
int idNeurona; //identificacion del cliente
int cOrigen; //capa de origen del mensaje
int cDestino; //capa de destino del mensaje
int nDestino; //neurona destino
int capa; //nro de capa en la que estoy
float valor; //valor
};
/**
* envia datos por el puerto especificado
*/
int enviar(char *param, struct pmensaje *m, int puerto){
int sd;
socklen_t lon;
struct sockaddr_in server;
struct hostent *h;
server.sin_family = AF_INET;
server.sin_port = htons(puerto);
if (h = gethostbyname("localhost")){
memcpy(&server.sin_addr, h->h_addr, h->h_length);
}else{
printf("No se encontró %s\n", param);
}
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
lon = sizeof(server);
if(connect(sd, (struct sockaddr *)&server, lon)<0){
perror("Connect");
exit(-1);
}
send(sd, m, P_SIZE, 0);
close(sd);
return 0;
}
/**
* solicita datos por teclado
*/
int pedido_de_datos(int i){
char teclado[P_SIZE];
if (i<3){
printf("Ingrese valor %i: ", i);
}else{
printf("Ingrese valor esperado: ", i);
}
fgets(teclado,sizeof(teclado),stdin);
teclado[strlen(teclado)-1] = '\0';
return atoi(teclado);
}
/**
* primera comunicacion con el servidor
*/
int saludo(char *param, struct pmensaje *m){
int sd, leidos, n;
socklen_t lon;
struct sockaddr_in server;
struct hostent *h;
server.sin_family = AF_INET;
server.sin_port = htons(4000);
if (h = gethostbyname(param)){
memcpy(&server.sin_addr, h->h_addr, h->h_length);
}else{
printf("No se encontró %s\n", param);
}
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
lon = sizeof(server);
if(connect(sd, (struct sockaddr *)&server, lon)<0){
perror("Connect");
exit(-1);
}
send(sd, m, P_SIZE, 0);
leidos = 0;
while (leidos < P_SIZE){
if ((n = recv(sd, m + leidos, P_SIZE - leidos, 0)) <= 0){
close(sd);
break;
}
leidos += n;
}
close(sd);
return m->capa;
}
int imprimirMensaje(struct pmensaje *m){
printf("------------------------------------------------------------------\n");
printf("idNeurona: %i\n", m->idNeurona);
printf("Capa Origen: %i\n", m->cOrigen);
printf("Capa Destino: %i\n", m->cDestino);
printf("Neurona Destino: %i\n", m->nDestino);
printf("Capa: %i\n", m->capa);
printf("Mensaje: %i\n", m->mensaje);
printf("Valor: %5.2f\n", m->valor);
printf("------------------------------------------------------------------\n");
return 0;
}
int imprimirNeurona(struct pneurona *n, int max){
int i;
printf("------------------------------------------------------------------\n");
printf("idNeurona: %i\n", n->idNeurona);
printf("\tPesos\tValores\n");
for (i=0;i<max;i++){
printf("%i)\t%5.2f\t %5.2f\n", i,n->pesos[i], n->valores[i]);
}
printf("------------------------------------------------------------------\n");
}
/**
* calcula la g(net)
*/
double gnet(double pesos[], double valores[], int max, double phi){
double suma;
int i;
suma = 0;
for (i=0;i<max;i++){
suma += (pesos[i]*valores[i])-phi;
}
return suma;
}
/**
* calcula la f(gnet)
*/
double fgnet(double gnet){
double exponencial;
double valor;
exponencial = exp(gnet);
valor = (1/(1+exponencial));
return valor;
}
/**
* Calcula el valor de salida de la neurona (activacion)
*/
int y(double fgnet){
if (fgnet > 0.5){
return 1;
}else{
return 0;
}
}
/**
* Inicualiza las neuronas
*/
int inicializar(struct pneurona *n, int id, int puerto){
int i;
double peso;
peso = 0.33;
n->idNeurona = id;
if (puerto == 4001)
if (id == 6){
peso = 1;
}else{
peso = 0.5;
}
else{
switch(puerto){
case 4021: n->idNeurona = 3;
break;
case 4022: n->idNeurona = 4;
break;
case 4023: n->idNeurona = 5;
break;
}
}
for (i=0; i<3; i++){
n->pesos[i] = peso;
n->valores[i] = 0;
}
printf("id: %i\n", n->idNeurona);
return 0;
}
/**
* Calcula el delta para la neurona 6
*/
double delta6(double gnet, double ydeseado){
return fgnet(gnet)*(1- fgnet(gnet))*(ydeseado-fgnet(gnet));
}
/**
* Calcula el delta para la neurona
*/
double deltak(double gnet, double suma){
return fgnet(gnet)*(1-fgnet(gnet))*suma;
}
/**
* emula la operatoria de la capa de entrada (C1) y la capa de salida (C3)
*/
int operatoriaCapaMixta(struct sockaddr_in local,int sd, int sdcli){
char buffer[P_SIZE];
char buffer2[P_SIZE_2];
char buffer3[P_SIZE_2];
char buffer4[P_SIZE_2];
int phi = 3;
char teclado[P_SIZE];
int i,j=0, deseado,lon, pid;
int salir;
struct pmensaje *mensaje;
struct pneurona *n1;
struct pneurona *n2;
struct pneurona *n3;
int asignado[3];
int deC1 = 0, deC2 = 0, deC3 = 0;
double umbral = 0.5;
double suma1, suma2;
mensaje = (struct pmensaje *) buffer;
n1 = (struct pneurona *) buffer2;
n2 = (struct pneurona *) buffer3;
n3 = (struct pneurona *) buffer4;
inicializar(n1, 1, 4001);
inicializar(n2, 2, 4001);
inicializar(n3, 6, 4001);
printf("*********************************************************\n");
printf("*** Ya puede comenzar la operatoria ***\n");
printf("*********************************************************\n");
salir = 0;
imprimirNeurona(n1,1);
imprimirNeurona(n2,1);
imprimirNeurona(n3,3);
while(!salir){
deseado = pedido_de_datos(3);
for (i=1;i<=2;i++){
mensaje->cOrigen = 1;
mensaje->cDestino = 2;
mensaje->nDestino = 1;
mensaje->idNeurona = i;
mensaje->capa = 4001;
if (i == 1){
n1->pesos[0] = pedido_de_datos(1);
mensaje->valor = fgnet(gnet(n1->pesos,n1->valores,1,umbral));
}else{
n2->pesos[0] = pedido_de_datos(2);
mensaje->valor = fgnet(gnet(n2->pesos, n2->valores, 1,umbral));
}
enviar("localhost", mensaje, 4000);
printf("Mensaje de capa 1 enviado a capa 2\n");
}
//Espera recibir los 3 mensajes de c/u de las neuronas de capa 2
i = 0;
while (i < 3){
lon = sizeof(local);
sdcli = accept(sd, (struct sockaddr *) &local, &lon);
recv(sdcli, mensaje, P_SIZE, 0);
printf("Recibido mensaje de la neurona %i\n", mensaje->idNeurona);
if ((mensaje->cOrigen == 2) && (mensaje->cDestino == 3)){
n3->valores[mensaje->idNeurona-3] = mensaje->valor;
}
i++;
}
/******************************* carteles correspondientes a C3 *********************************************/
i = y(fgnet(gnet(n3->pesos, n3->valores, 3, umbral)));
if (i != deseado){
printf("El valor recibido es distinto del valor deseado (%i != %i)\n", i, deseado);
imprimirNeurona(n3,3);
printf("Corrigiendo pesos con delta = %7.5f...\n", delta6(gnet(n3->pesos, n3->valores, 3, umbral), deseado));
//Retropropago el valor de delta
mensaje->cOrigen = 3;
mensaje->cDestino = 2;
mensaje->idNeurona = 6;
for (i=0; i<3;i++){
mensaje->nDestino = i+3;
mensaje->valor = n3->pesos[i]*delta6(gnet(n3->pesos, n3->valores, 3, umbral), deseado);
enviar("localhost", mensaje, 4000);
}
//Corrijo los pesos de la neurona 3
for (i=0;i<3;i++){
n3->pesos[i] += umbral*delta6(gnet(n3->pesos, n3->valores, 3, umbral), deseado)*fgnet(gnet(n3->pesos, n3->valores, 3, umbral));
}
imprimirNeurona(n3,3);
//Recibe los delta de la capa 2 para la capa 1
i = 0;
suma1 = 0;
suma2 = 0;
printf("Valores originales de los pesos de las neuronas 1 y 2...\n");
imprimirNeurona(n1,1);
imprimirNeurona(n2,1);
while (i < 3){
lon = sizeof(local);
sdcli = accept(sd, (struct sockaddr *) &local, &lon);
recv(sdcli, mensaje, P_SIZE, 0);
printf("Recibido mensaje de la neurona %i\n", mensaje->idNeurona);
if ((mensaje->cOrigen == 2) && (mensaje->cDestino == 1)){
if (mensaje->nDestino == 1){
suma1 += mensaje->valor*n1->pesos[0];
}else{
suma2 += mensaje->valor*n2->pesos[0];
}
}
i++;
}
n1->pesos[0] +=phi*deltak(gnet(n1->pesos, n1->valores, 1, umbral), suma1)*fgnet(gnet(n1->pesos, n1->valores, 1, umbral));
n2->pesos[0] +=phi*deltak(gnet(n2->pesos, n2->valores, 1, umbral), suma2)*fgnet(gnet(n2->pesos, n2->valores, 1, umbral));
printf("Valores resultantes de la correccion de los pesos de las neuronas 1 y 2...\n");
imprimirNeurona(n1,1);
imprimirNeurona(n2,1);
}else{
printf("El valor recibido es igual al deseado %i = %i\n", i, deseado);
}
/**********************************************************************************************************/
printf("Desea salir de la aplicacion? S/N \n");
fgets(teclado,sizeof(teclado),stdin);
teclado[strlen(teclado)-1] = '\0';
salir = strcmp(teclado, "N");
}
printf("*********************************************************\n");
printf("*** Finalizada la operatoria ***\n");
printf("*********************************************************\n");
return salir;
}
}