C/Visual C - me ayudais a entender que pone aqui por favor?

 
Vista:

me ayudais a entender que pone aqui por favor?

Publicado por Nelek (816 intervenciones) el 17/08/2006 11:16:49
Hola, esta va a ser una de las ultimas veces que postee pidiendo ayuda para mi proyecto. Solo me falta presentar los datos en la pantalla de salida y ya lo he acabado. La cosa está en que no tengo claro como hacerlo porque en la teoría sobre "lógica fuzzy" (en concreto el método "Center of Gravity"), hay diferentes metódicas según autores. El problema es que casi siempre usan integrales y funciones pero... como que eso no concuerda con los ejemplos prácticos que he visto. Voy a comentar un poco el funcionamiento de mi programa y a poner un ejemplo que me han dado en la empresa de un simulador similar hecho en C pero que no acabo de entender y es dónde pido la ayuda. (Lo siento por la longitud del mensaje).

El funcionamiento de mi simulador de sistemas es relativamente simple.

Una pantalla donde se pueden establecer varias entradas, reguladores y salidas. Las entradas se pueden conectar a varios reguladores y varios reguladores pueden tener multiples entradas conectadas. Entre regulador y salida la relación es ÚNICA (un reg una salida, una salida un reg). Cada Salida tiene ciertos Atributos, funciones de Y = X (lineas verticales) y un "punto de trabajo" en dichos attributos que depende de las entradas y reguladores, ademas de UN Valor de Salida que depende de dichos puntos de trabajo en los atributos (el valor de salida se calcula con el "center of gravity" aplicado a los puntos de trabajo de los atributos).
En las Entradas se tienen dos tipos (Y = X o Y = MX+N) de atributos, pero esto no es relevante para mi pregunta, lo unico que aquí interesa es el valor de la Y segun el punto de trabajo de la entrada está en un sitio u otro.
La cosa está en que... según las relaciones que se especifican en el regulador. Los puntos de trabajo en los atributos de salida toman el VALOR MAXIMO DE TODOS LOS VALORES MINIMOS que afectan al funcionamiento de dicho atributo en la salida. Hasta aqui lo tengo todo claro, ya programado y funciona.

El problema viene ahora, una vez tengo los Atributos en las rectas Y=X y un punto de trabajo concreto en Y1 = MAX (MIN1, MIN2, ... MINn). Como diantres saco el valor de la salida?

El ejemplo en C que me han pasado en la empresa es el siguiente. Me interesa entender sobretodo el CENTER OF GRAVITIY (y lo que pueda ser relevante para su funcionamiento). Alguien me explicar que se está haciendo? he intentado descifrarlo pero me hago un lio. Más o menos me hago una idea, pero me gustaría que alguien con más nivel que yo me contestara. Gracias por adelantado, sé que no es algo sencillo lo que pido.

/*
* psim.c
* Frank Neubauer, 1994
*
* This module contains the Fuzzy-Simulationloop
*/
#include <stdio.h>
#include <string.h>
#include "psim.h"

#define HEADER_SIZE (9*4)

typedef struct {
VALUE x,y;
double d,s;
} Point;

typedef enum {
OP_END = 0x00,
OP_CLEAR = 0x01,
OP_FUZZYFYINT = 0x10,
OP_DEFUZZYINT_COG = 0x20,
OP_WEIGHT = 0x30,
OP_MIN = 0x31,
OP_MAX = 0x32
} OPCODE;

typedef BYTE* (*CODEPROC)(BYTE*);

static BYTE* OP_Clear( BYTE * pMem );
static BYTE* OP_FuzzifyInt( BYTE * pMem );
static BYTE* OP_Weight( BYTE * pMem );
static BYTE* OP_Min( BYTE * pMem );
static BYTE* OP_Max( BYTE * pMem );
static BYTE* OP_DefuzzyIntCOG( BYTE * pMem );

typedef struct {
OPCODE Opcode;
CODEPROC CodeProc;
} CODEENTRY;

static CODEENTRY OpcodeTab[] = {
{ OP_CLEAR, OP_Clear },
{ OP_FUZZYFYINT, OP_FuzzifyInt },
{ OP_DEFUZZYINT_COG, OP_DefuzzyIntCOG },
{ OP_WEIGHT, OP_Weight },
{ OP_MIN, OP_Min },
{ OP_MAX, OP_Max },
{ OP_END, NULL }
};

static unsigned yResolution;
static BYTE *pCode, *pCodeStart;
static BYTE *pData, *pDataStart;
static BYTE *pVariables;
static VALUE AccuVal;
static size_t InVarCount, OutVarCount;
static VALUE

fi( register VALUE x, register const BYTE * p )
{
if( x < p[1] ) {
if( x <= p[0] ) return 0;
if( p[5] == 0 ) return (x - p[0]) * p[4];
return (VALUE) (((((x - p[0]) * (unsigned) p[4]) >> (p[5] - 1)) + 1) >> 1);
}
if( x <= p[2] ) return (yResolution-1);
if( x >= p[3] ) return 0;
if( p[7] == 0 ) return (p[3] - x) * p[6];
return (VALUE) (((((p[3] - x) * (unsigned) p[6]) >> (p[7] - 1)) + 1) >> 1);
}
/*
* OP_Clear
*/
static BYTE* OP_Clear( BYTE * pMem )
{
int index;
index = (int) *pMem++;
pVariables[index] = 0;
return pMem;
}
/*
* OP_FuzzifyInt
*/
static BYTE* OP_FuzzifyInt( BYTE * pMem )
{
int varindex, memberindex;
varindex = (int) *pMem++;
memberindex = (int) *pMem++;
pVariables[memberindex] = fi( pVariables[varindex], pData );
pData += 8;
return pMem;
}
/*
* OP_Weight
*/
static BYTE* OP_Weight( BYTE * pMem )
{
AccuVal = (VALUE) (((int) AccuVal * *pData++) / 256);
return pMem;
}
/*
* OP_Min
*/
static BYTE* OP_Min( BYTE * pMem )
{
int index, number;
VALUE Value;
number = (int) *pMem++;
AccuVal = yResolution - 1;
while( number-- > 0 ) {
index = (int) *pMem++;
Value = pVariables[index];
if( Value < AccuVal ) AccuVal = Value;
}
return pMem;
}
/*
* OP_Max
*/
static BYTE* OP_Max( BYTE * pMem )
{
int index, number;
index = (int) *pMem++;
if( pVariables[index] < AccuVal ) pVariables[index] = AccuVal;
return pMem;
}
/*
* OP_DefuzzyIntCOG
*/
static BYTE* OP_DefuzzyIntCOG( BYTE * pMem )
{
int varindex, memberindex, number;
unsigned long Numerator = 0, Denominator = 0, Value;
varindex = (int) *pMem++;
number = (int) *pMem++;
while( number-- > 0 ) {
memberindex = (int) *pMem++;
Value = pVariables[memberindex];
Numerator += Value * *pData++;
Denominator += Value;
}
if( Denominator != 0 ) pVariables[varindex] = Numerator / Denominator;
return pMem;
}
/*
* FuzzyEvaluate
*/
BOOL FuzzyEvaluate( VALUE * InVars, VALUE * OutVars)
{
OPCODE Opcode;
CODEENTRY *CodeEntry;
pCode = pCodeStart;
pData = pDataStart;
memcpy( &pVariables[0], InVars, InVarCount );
while( (Opcode = (OPCODE) *pCode++) != OP_END ) {
for( CodeEntry = OpcodeTab; CodeEntry->Opcode != OP_END; CodeEntry++ )
if( CodeEntry->Opcode == Opcode )
break;
if( CodeEntry->CodeProc == NULL ) {
printf( "Unbekannter Operator %02X\n", Opcode );
return FALSE;
}
if( (pCode = CodeEntry->CodeProc( pCode )) == NULL )
return FALSE;
}
#if 0
printf( "%3d %3d %3d\t%3d %3d %3d %3d\t",
pVariables[4], pVariables[5], pVariables[6], pVariables[7],
pVariables[8], pVariables[9], pVariables[10] );
// printf( "%3d %3d %3d %3d\t", pVariables[11], pVariables[12], pVariables[13], pVariables[14
] );
#endif
memcpy( OutVars, &pVariables[InVarCount], OutVarCount );
return TRUE;
}
/*
* ReadLong
*/
static BYTE *ReadLong( BYTE * pMem, unsigned long * pLong )
{
*pLong = (unsigned long) *pMem++;
*pLong += ((unsigned long) *pMem++) << 8;
*pLong += ((unsigned long) *pMem++) << 16;
*pLong += ((unsigned long) *pMem++) << 24;
return pMem;
}
/*
* FuzzyInit
*/
BOOL FuzzyInit( BYTE * pMem, size_t MemLen )
{
BYTE *pMemStart = pMem;
unsigned long Magic, Version;
unsigned long CodeLen, DataLen, VarLen, PrivateLen;
unsigned long nInVars, nOutVars, yRes;
pMem = ReadLong( pMem, &Magic );
pMem = ReadLong( pMem, &Version );
pMem = ReadLong( pMem, &CodeLen );
pMem = ReadLong( pMem, &DataLen );
pMem = ReadLong( pMem, &VarLen );
pMem = ReadLong( pMem, &PrivateLen );
pMem = ReadLong( pMem, &nInVars );
pMem = ReadLong( pMem, &nOutVars );
pMem = ReadLong( pMem, &yRes );
pCodeStart = pMem;
pDataStart = pCodeStart + CodeLen;
pVariables = pDataStart + DataLen;
if( HEADER_SIZE + CodeLen + DataLen + VarLen > MemLen ) {
printf( "Der Speicher reicht nicht aus\n" );
return FALSE;
}
InVarCount = (size_t) nInVars;
OutVarCount = (size_t) nOutVars;
yResolution = (unsigned) yRes;
memset( pVariables, 0, (size_t) VarLen );
return TRUE;
}
/*
* FuzzyTerminate
*/
void FuzzyTerminate()
{}
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Notas adicionales

Publicado por Nelek (816 intervenciones) el 17/08/2006 11:31:51
"""Me interesa entender sobretodo el CENTER OF GRAVITIY""" -> Para dicho ejemplo es : OP_DefuzzyIntCOG

"""El problema es que casi siempre usan integrales y funciones pero... como que eso no concuerda con los ejemplos prácticos que he visto""" -> Las integrales las se hacer, pero lo que no se que funcion coger para que pase por todos los puntos de trabajo de los atributos de salida ya que son pares de coordenadas aleatorias (X definida por el usuario e Y definida por los atributos y el punto de trabajo de las entradas) dentro de un plano finito (x1 = Min, y1 = 0, x2 = Imax, y2 = 1), donde Imin e Imax son definidos por el usuario. La integral de la funcion que define el plano, no es lo que busco. Y funciones que pasen por todos los puntos relevantes simultaneamente van a ser polinomios como minimo de grado "n" donde "n" es el numero de atributos presentes en la pantalla (de 1 a 7). Por lo que las posibilidades son... demasiadas y con valores muy distintos.
Ya he pensado en hacer simplemente rectas desde el origen de coordenadas de la grafica, al primer punto, del primer punto al segundo... y sumar las integrales parciales. Pero el problema es que los resultados no son los que deberían. También he intentado coger dicho valor de la suma de las integrales parciales y normalizarlo a un XX% tomando la superficie total del plano como el 100%. Esta ultima opcion es la que mas se ha acercado a los resultados de sistemas ya existentes y funcionales, pero sigue sin ser la que toca.

En fin... que me quedo sin tiempo y sin ideas. Os agradeceré eternamente cualquier pista, ayuda, respuesta, idea... que me lleve a solucionar el problema.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ya no hace falta

Publicado por Nelek (816 intervenciones) el 17/08/2006 20:35:39
De casualidad me he encontrado con un ejemplo por la red al respecto y he encontrado una formula que me aproxima muchisimo al valor que me daba el ejemplo de la empresa. Supongo que algo asi es lo que debe de hacer el codigo puesto arriba, pero esto es mucho mas sencillo para mi (tanto para entenderlo como para programarlo).

Por si a alguien le interesa la solucion... dicha formula es:

(double) COG = Sumatorio(ATTi.x * ATTi.y) / Sumatorio(ATTi.y)

donde "COG" es el valor que buscaba, "ATTi" son los distintos attributos de salida existentes, "x" e "y" las coordenadas del punto de trabajo de dicho attributo.

Gracias igualmente
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar