code segment (3.0)

read carefully

Amplificador Para El Iphone (2)

Comments

Ya os enseñe como había quedado el ampli en la primera brico-sesión, en la segunda lo he completado .. lo primero ha sido hacer un pequeño transformador 12v -> 5v algo sencillo usando un integrado 7805 el esquema que he seguido es este ..

image

El montaje bueno, nada complicado (la placa ya la cortaré un poco, más adelante)

image_l

image

Obviamente la prueba unitaria :-). Y después una prueba de integración

image

Y finalmente este es el resultado .. suena fenómeno .. y solo 51 eurillos

image

Por cierto, el ampli tiene integrada una radio, control de graves y agudos.

Fotos

Blog v3.0

Comments

Nuevo blog, dejo atrás el anterior, que estaba basado en WordPress y me paso a algo un poco más friki octopress. Por el momento no tengo intenciones de pasar los antiguos artículos que se pueden consultar aquí oldblog.ideseg.com aunque existe un mágnifico script llamado exitwp de Thomas Frössman, que permite extraer los posts y las imágenes de WordPress, yo lo he hecho y funciona perfectamente. Antes de ejecutarlo hacer una limpieza de los comentarios en WordPress y eliminar el spam.

Está vez en la mudanza he hecho limpieza y no me apetece llevar las maletas nuevas cargadas de cosas viejas, si acaso alguna joyita.

Amplificador Para El Iphone

Comments

A ver que con la que nos esta cayendo .. me hubiera gustado pillarme unos altavoces de esos chulos para el iphone, pero eso sí, de los buenos, los que nos gustan a todos, los que valen una pasta :-)

Pero con esto de recortar gastos…. no encontré una razón para justificar la compra :-(, y como por el trastero guardo mi vieja cadena de música a la cual en su día le pille unos estupendo altavoces B&W (entonces no había crisis :-), me puse a pensar en subir toda la cadena, ampli, cd, radio a casa, pero eso ocupa un montón.

Bueno la cosa es que estas navidades vi el cacharrito este de logitech, que puedes pincharlo en tu cadena por la entrada aux y por BT puedes escuchar tu iphone, de modo en que la idea de volver a subir la cadena a casa molaba, lo que no molaba nada era el espacio que necesita y la cantidad de cables que necesita bufff que pereza

image

Al lio

La cosa es que vi un ampli por ebay que costaba solo 16€ (jeje)

image

Así que se me ocurrió la idea de hacer un poco de brico-mania y meter el ampli este en una caja de esas que parecen libros, y meter también el receptor de logitech, conectar mis altavoces estupendos y a ver…

image

Este es el resultado obtenido por por el momento, ahora hay que meter el receptor y hacer unos ajustes en el voltaje, ya que el ampli funciona con 12v y el receptor de logitech con 5v.

image

Más fotos

Fuzzy Logic Y Expresiones Lambda

Comments

Para un proyecto que estoy realizando, he realizado una prueba de concepto probado a aplicar lógica difusa con el fin de realizar ciertas acciones a partir de una serie de datos imprecisos.

A la hora de expresar las reglas encargadas de modelar nuestro sistema de lógica difusa, (IF-THEN) la mayoría de los sistemas que he visto requerían de un pequeño y simple análizador sintáctico para interpretar las reglas, en este punto me he preguntado si en vez de un análizador sintáctico, podríamos usar expresiones lambda y una interfaz fluida.

FuzzySystem (improvisado)

De modo que he construido un pequeño motor de lógica difusa que tiene la particularidad de usar expresiones lambda y una interfaz fluida para definir el conjunto de reglas.
Este pequeño motor incorpora un par de funciones miembro, una de tipo Trapezoide y otra Triangular, básicamente su uso es el siguiente.
Definimos el sistema, añadimos las variables con sus estados y funciones miembro…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class FuzzyTest
{
    private readonly FuzzySystem _engine = new FuzzySystem();

    public FuzzyTest()
    {
        FuzzyVariable varA = new FuzzyVariable("A");
        varA.Memberships.Add(new TrapezoidMembership("Cerrado", 0, 0, 5, 5));
        varA.Memberships.Add(new TrapezoidMembership("Medio", 4, 4, 6, 6));
        varA.Memberships.Add(new TrapezoidMembership("Abierto", 7, 7, 9, 9));
        _engine.Variables.Add(varA);

        FuzzyVariable varB = new FuzzyVariable("B");
        varB.Memberships.Add(new TrapezoidMembership("Cerrado", 0, 0, 5, 5));
        varB.Memberships.Add(new TrapezoidMembership("Medio", 4, 4, 6, 6));
        varB.Memberships.Add(new TrapezoidMembership("Abierto", 7, 7, 9, 9));
        _engine.Variables.Add(varB);

        FuzzyVariable varR = new FuzzyVariable("R");
        varR.Memberships.Add(new TrapezoidMembership("Frio", 0, 0, 3, 3));
        varR.Memberships.Add(new TrapezoidMembership("Templado", 3, 3, 6, 6));
        varR.Memberships.Add(new TrapezoidMembership("Caliente", 7, 7, 9, 9));
        _engine.Variables.Add(varR);

La definición de reglas mediante expresiones Lambda

El beneficio en este punto es que el sistema no requiere del análizador sintáctico para evaluar las expresiones si no que será el CLR quien se encargue de ello.
Para llevar a cabo esta evaluación de las reglas he definido una clase FuzzyExpresion que tiene definidos los operadores && y || para así como el true y el false para poder evaluar las reglas en consecuencia.

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
public class FuzzyExpression
{
    private readonly FuzzyVariable _variable;
    private string _state;
    private double? _value;

    public double Value
    {
        get
        {
            if (_value.HasValue)
                return _value.Value;
            _value = _variable.Fuzzify(State);
            return _value.Value;
        }
    }

    public string State
    {
        get { return _state; }
    }

    public FuzzyExpression(FuzzySystem engine, string literal)
    {
        _variable = engine.Variables[literal];

        if (_variable == null)
        {
            throw new FuzzyException("variable not found.");
        }
    }

    public FuzzyExpression(double value)
    {
        _value = value;
    }

    public FuzzyExpression Is(string state)
    {
        _state = state;
        _value = _variable.Fuzzify(_state);
        return this;
    }

    public FuzzyExpression Set(string newState)
    {
        _state = newState;
        return this;
    }

    public static FuzzyExpression operator |(FuzzyExpression a, FuzzyExpression b)
    {
        return new FuzzyExpression(Math.Max(a.Value, b.Value));
    }

    public static FuzzyExpression operator &(FuzzyExpression a, FuzzyExpression b)
    {
        return new FuzzyExpression(Math.Min(a.Value, b.Value));
    }

    public static bool operator false(FuzzyExpression a)
    {
        return 0 > a.Value;
    }

    public static bool operator true(FuzzyExpression a)
    {
        return a.Value > 0;
    }
}

Las reglas en la lógica difusa sirven para combinar las distintas proposiciones, no son reglas excesivamente complicadas, y son del tipo IF-THEN, básicamente hay 4 reglas (Implicación Conjunción, Disyunción y negación) que se corresponden con:

  • Implicación IF variable==estado THEN variable = estado
  • Conjunción, equivalente al AND, si dos proposiciones son ciertas simultáneamente
  • Disyunción, cualquiera de las dos proposiciones es cierta OR
  • Negación, invierte la proposición

Finalmente podemos definir las reglas de este modo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
_engine.AddRule(x =>
                x.Variable("A").Is("Abierto") &&
                x.Variable("B").Is("Abierto"))
                .Then(x => x.Variable("R").Set("Caliente"));

_engine.AddRule(x =>
                x.Variable("A").Is("Abierto") &&
                (x.Variable("B").Is("Cerrado") || x.Variable("B").Is("Medio")))
                .Then(x => x.Variable("R").Set("Templado"));

_engine.AddRule(x =>
                x.Variable("B").Is("Abierto") &&
                (x.Variable("A").Is("Cerrado") || x.Variable("A").Is("Medio")))
                .Then(x => x.Variable("R").Set("Templado"));

_engine.AddRule(x =>
                x.Variable("A").Is("Cerrado") &&
                x.Variable("B").Is("Cerrado"))
                .Then(x => x.Variable("R").Set("Frio"));

¿Como funciona?

Una regla tiene una condición (IF) y una consecuencia (THEN), la condición es una función que recibe el sistema y debe devolver una FuzzyExpresion, (Func<FuzzySystem,FuzzyExpression>), esto es parte de la magia ya que una expresión condicional es siempre reducida a una única expresión y finalmente a un único valor.
Y curiosamente la consecuencia de la regla, es exactamente igual, solo que en este caso la expresión no devuelve nada porque la consecuencia es una acción, aqui hay otro pequeño truco que es que la propia regla contiene los dos elementos separados (condición y consecuencia) fijaros en que:

1
2
3
_engine.AddRule(x =>
  x.Variable("A").Is("Abierto") &&
    x.Variable("B").Is("Abierto"))

Esta devolviendo una regla y el método Then es aplicado sobre la regla, y cuando se evalúa la regla si la condición es cierta se evalua la consecuencia, que lo que hace es únicamente cambiar el estado (ver el método Set de FuzzyExpression)

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

public class FuzzyRule
{
   private readonly FuzzySystem _engine;
   private readonly Func _condition;
   private Func _then;


   public double Value { get; set; }

   public FuzzySystem Engine
   {
       get { return _engine; }
   }

   public FuzzyRule(FuzzySystem engine, Func condition)
   {
       _engine = engine;
       _condition = condition;
   }

   public FuzzyExpression Eval()
   {
       Value = _condition(Engine).Value;

       if (Value > 0)
       {
           return _then(Engine);
       }

       return null;
   }

   public void Then(Func then)
   {
       _then = then;
   }
}

Defuzzyficando

Para evaluar nuestro sistema ..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        for (int a = 0; a < 10; a++)
    {
        for (int b = 0; b < 10; b++)
        {
            _engine.Variables["A"].InputValue = a;
            _engine.Variables["B"].InputValue = b;
            _engine.Consecuent = "R";

            var r = _engine.Defuzzy();

            Console.WriteLine(string.Format("A {0} - B {1} = {2,-6} [{3,-10}][{4,-10}] = {5}",
                a,
                b,
                r,
                _engine.GetVariableState("A",a),
                _engine.GetVariableState("B",b),
                _engine.GetVariableState("R", r)));
        }
    }
}

Mejoras de diseño

Hay una cosa que no me gusta mucho y es el hecho de que mi clase FuzzyExpression, tiene tanto el método Is como el método Set y esto habría que dividirlo en dos para no llevar a errores a la hora de la usar la interfaz fluida.

Errores de diseño

Pero no todo es de color de rosa, cuando planifique el sistema, pensé en la posibilidad de guardar las expresiones lambda como texto y después compilarlas usando CodeDom, bien tengo que deciros que cuando me he puesto a ello me he llevado la desagradable sorpresa de que CodeDom no soporta expresiones lambda, de modo que mi gozo en un pozo.

Y digo esto porque es de vital importancia el poder mantener las reglas fuera del código, bien un archivo de configuración, un archivo XML, lo que sea… de este modo podemos realizar ajustes sin tener que recompilar todo …


Para una futura version

Completar estas cositas …

Excel - CS-Solver De VBA a VSTO

Comments

Hace ya algún tiempo que escribí CS-Solver, estos días me he propuesto convertirlo de VBA a VSTO.

CS-Solver es un add-in para Excel que escribí hace algún tiempo, ya que la calculadora que usaba tenía un sistema de resolver ecuaciones muy parecido (PowerOne finance) y sin embargo resolver ecuaciones con Excel era bastante más complicado.

CS-Solver utiliza el método secante para encontrar las raíces de f(x)=0 en un intervalo, este no es tan rápido como el de Newton, pero si más rápido que la bisección ya que acota el intervalo y usa la aproximación más reciente.

A diferencia del método de Newton, no necesitamos calcular la derivada de la función en cada iteración, y que es un proceso más tedioso y requiere cálculo adicional.

Veamos ahora como funciona CS-Solver con un pequeño ejemplo, resolviendo la siguiente ecuación
2x + 5x = 2

image

Primero crearemos una celda C2 a la que daremos un nombre en este caso X, esta es la incógnita, en otra celda teclearemos la función, igualando el resultado a 0, quedando la ecuación **2x+5x-2=0**, esta celda la introduciremos como texto.

Ahora desde el menú de CSSolver, seleccionamos resolver ecuación

En donde se nos pide que introduzcamos la celda que contiene la ecuación a resolver, una vez seleccionada la celda que contiene la ecuación C4 pulsamos sobre Aceptar

image

El resultado aparece en la celda de nombre X que es la incógnita a resolver.

image

Veamos ahora otras cosas que se puede hacer con CS-Solver. Para ello usaremos la formula del Interés compuesto y calcularemos el Valor Futuro de un Capital invertido al 5% de interés anual durante 3 meses.


**Valor Final = Valor Actual * ( 1 + (Interés/12))Meses**

image

Teclearemos la formula igualada a 0, 0=(vactual*(1+interes))meses)-vfinal** para ello, nombraremos la celda C2 como vfinal, C3 como vactual, C4 como interes y C5 como meses**

Si ejecutamos CS-Solver y seleccionamos B7 como la formula a resolver obtendremos el Valor Actual, solucionando la ecuación.

image

Bien, una vez obtenido el resultado deseamos vemos que 1012,55 no es lo esperado que necesitamos obtener al final de nuestra inversión un total de 1125, así que queremos ver cuanto necesitamos ingresar ahora para poder retirar dentro de 3 meses 1125

Para ello, nos basta con eliminar el contenido de la celda C3, (vactual) e indicar en la celda C2 el importe que deseamos obtener. Nuestra hoja de excel quedaría así.

image

Bien, no tenemos que tocar nada más tan solo seleccionar CS-Solver e indicar la formula que ya habíamos escrito, B7

image

CS-Solver comprueba cual es la incógnita de la ecuación, vactual en este caso y comprueba que no tiene valor, así que su objetivo es resolver dicha incógnita.

CS-Solver incorpora también una nueva formula llamada CSSolver con la cual podemos tener en una celda el valor de la incógnita de la ecuación, de este modo se puede tener en una celda =CSSolver(“2xsin(x)-5”) para la ecuación 2xsin(x)=5 e incluso podemos vincular la formula con una celda =CSSolver(A5)

Excel - Distribuciones, Planificaciones, Formulas Matriciales

Comments

No se si lo he comentado alguna vez, pero en el trabajo suelo usar mucho Excel para hacer una gran variedad de cosas, en general mucho de lo que tiene que ver con el área económico financiera (lo terminamos haciendo en Excel).

Muchas de nuestras hojas de cálculo, son planes financieros, estudios de viabilidad, análisis etc. Básicamente estas hojas planifican cobros y pagos ó gastos e ingresos, la cuestión es la planificación, en Excel podemos planificar todo aquello que queramos, es sencillo podemos establecer una fila para cada previsión a realizar y en cada columna podemos poner un periodo (ene, feb, mar…), por último en cada celda (previsión / periodo) el importe de dicha previsión.

image

El problema se complica un poco cuando el importe de cada previsión no tiene un periodo fijo, sino que este debe establecerse en función de otra variable. Supongamos que tenemos que realizar una previsión entre dos periodos dados (Inicio y Final) y el importe debe ser proporcional al número de periodos.

image

Como es lógico las formulas se nos van complicando, más y más en función de las condiciones que necesitamos. Con lo que terminamos creando nuestras funciones en VBA para simplificar el proceso.

1
2
3
4
5
Function csPDistB(importe As Integer, periodo As Integer, inicio As Integer, fin As Integer)
  If (periodo >= inicio) And (periodo <= fin) Then
    csPDistB = importe / ((fin  inicio) + 1)
  End If
End Function

Realizaría el mismo trabajo que las formulas vistas. Dándole una vuelta más podemos crear una función matricial para hacer la misma tarea y que automáticamente tome el periodo actual en función del rango en donde se encuentre.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Public Function csPDistB(importe As Variant, primero As Integer, ultimo As Integer) As Variant
  Dim i As Integer
  Dim nPeriodos As Integer
  Dim valor As Double

  ReDim a(0 To Application.Caller.Rows.Count, 0 To Application.Caller.Columns.Count) As Variant

  On Error GoTo Handler

  nPeriodos = ultimo  primero
  valor = CDbl(importe / (nPeriodos + 1))

  For i = 0 To Application.Caller.Columns.Count
      If i + 1 >= primero And i + 1 <= ultimo Then
         a(0, i) = valor
      End If
  Next

  csPDistB = a

  Exit Function
Handler:
  csPDistB = CVErr(2015)  xlErrNum = 2036
End Function

image

Por último con una pequeñas modificaciones sobre este código podemos crear funciones más complejas para nuestras planificaciones, por ejemplo distribuciones en función de una curva de porcentajes, 25%, 50% y 25% sería el 25% en el primer tercio, el 50% en el segundo tercio y el 25% en el tercer tercio del tiempo.

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
Public Function csPDistCP(importe As Variant, ParamArray porcentajes()) As Variant
  Dim i As Integer
  Dim nParte As Integer
  Dim p As Integer

  ReDim a(Application.Caller.Columns.Count) As Variant

  On Error GoTo Handler

  nParte = (UBound(a) + 1) / (UBound(porcentajes) + 1)

  p = -1

  For i = 0 To UBound(a)
    If i Mod Int(nParte) = 0 Then
       If p < UBound(porcentajes) Then
          p = p + 1
       End If
    End If

    a(i) = CDbl((importe / nParte) * porcentajes(p))

  Next

  csPDistCP = a

  Exit Function

Handler:

  csPDistCP = CVErr(2015)  xlErrNum = 2036

End Function

Un último ejemplo en donde realizamos previsiones los periodos indicados, el importe proporcional al número de periodos.

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
Public Function csPDistP(importe As Variant, ParamArray periodos()) As Variant
  Dim i As Integer
  Dim nPeriodos As Integer
  Dim valor As Double

  ReDim a(Application.Caller.Columns.Count) As Variant

  On Error GoTo Handler

  nPeriodos = UBound(periodos)

  valor = CDbl(importe / (nPeriodos + 1))

  For i = 0 To nPeriodos
      a(periodos(i)) = valor
  Next

  csPDistP = a

  Exit Function

Handler:

  csPDistP = CVErr(2015)  xlErrNum = 2036

End Function