Utilizar la Simulación de Monte Carlo para la Probabilidad en C

CBeginner
Practicar Ahora

Introducción

En este laboratorio, exploraremos cómo utilizar la simulación de Monte Carlo para estimar probabilidades en el lenguaje de programación C. Empezaremos definiendo un experimento aleatorio simple, como el lanzamiento de una moneda, y luego ejecutaremos múltiples ensayos para contar el número de resultados exitosos. Finalmente, calcularemos la probabilidad estimada dividiendo el número de éxitos por el número total de ensayos. Este laboratorio proporciona una introducción práctica a los conceptos fundamentales de probabilidad y combinatoria usando C, habilidades esenciales para el análisis de datos y la toma de decisiones.

Definir un Experimento Aleatorio

En este paso, exploraremos cómo definir un experimento aleatorio utilizando la simulación de Monte Carlo en C. Un experimento aleatorio es un proceso con resultados inciertos que puede simularse utilizando técnicas de probabilidad.

Entendiendo los Experimentos Aleatorios

Creemos un programa C simple para demostrar un experimento aleatorio básico: la simulación del lanzamiento de una moneda.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NUM_ENSAYOS 1000

int main() {
    // Semilla para el generador de números aleatorios
    srand(time(NULL));

    // Contador de caras
    int caras_conteo = 0;

    // Simular lanzamientos de moneda
    for (int i = 0; i < NUM_ENSAYOS; i++) {
        // Generar un número aleatorio 0 o 1
        int lanzamiento = rand() % 2;

        // Contar caras
        if (lanzamiento == 0) {
            caras_conteo++;
        }
    }

    // Calcular la probabilidad de caras
    double probabilidad = (double)caras_conteo / NUM_ENSAYOS;

    printf("Experimento de Lanzamiento de Moneda:\n");
    printf("Ensayos Totales: %d\n", NUM_ENSAYOS);
    printf("Conteo de Caras: %d\n", caras_conteo);
    printf("Probabilidad Estimada de Caras: %.2f\n", probabilidad);

    return 0;
}

Ejemplo de salida:

Experimento de Lanzamiento de Moneda:
Ensayos Totales: 1000
Conteo de Caras: 502
Probabilidad Estimada de Caras: 0.50

Conceptos Clave Explicados

  1. Generación de Números Aleatorios:

    • srand(time(NULL)) inicializa el generador de números aleatorios
    • rand() % 2 genera 0 o 1 con igual probabilidad
  2. Diseño del Experimento:

    • Definimos el lanzamiento de una moneda como nuestro experimento aleatorio
    • Ejecutamos múltiples ensayos (1000 en este caso)
    • Contamos el número de resultados exitosos (caras)
  3. Estimación de Probabilidad:

    • Probabilidad = (Número de Resultados Exitosos) / (Número Total de Ensayos)
    • En este caso, esperamos una probabilidad cercana a 0.5 para caras

Compilar y Ejecutar el Programa

## Crear el archivo fuente
nano ~/project/experimento_moneda.c

## Compilar el programa
gcc ~/project/experimento_moneda.c -o ~/project/experimento_moneda

## Ejecutar el experimento
~/project/experimento_moneda

Ejemplo de compilación y ejecución:

## Compilación
gcc ~/project/experimento_moneda.c -o ~/project/experimento_moneda

## Ejecución
~/project/experimento_moneda
Experimento de Lanzamiento de Moneda:
Ensayos Totales: 1000
Conteo de Caras: 502
Probabilidad Estimada de Caras: 0.50

Ejecutar Muchos Ensayos Aleatorios y Contar Éxitos

En este paso, ampliaremos nuestra simulación de Monte Carlo ejecutando múltiples ensayos aleatorios y contando con precisión los resultados exitosos. Lo demostraremos a través de un experimento de probabilidad más complejo: estimar π (pi) utilizando la generación de puntos aleatorios.

Método de Monte Carlo para la Estimación de π

Utilizaremos un enfoque geométrico para estimar π generando puntos aleatorios dentro de un cuadrado que contiene un cuarto de círculo.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define NUM_ENSAYOS 100000

int main() {
    // Semilla para el generador de números aleatorios
    srand(time(NULL));

    // Contadores para puntos totales y puntos dentro del círculo
    int puntos_totales = 0;
    int puntos_dentro_circulo = 0;

    // Ejecutar múltiples ensayos
    for (int i = 0; i < NUM_ENSAYOS; i++) {
        // Generar coordenadas aleatorias x e y entre 0 y 1
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;

        // Verificar si el punto está dentro del cuarto de círculo
        if (sqrt(x*x + y*y) <= 1.0) {
            puntos_dentro_circulo++;
        }
        puntos_totales++;
    }

    // Estimar π
    double estimacion_pi = 4.0 * puntos_dentro_circulo / puntos_totales;

    printf("Experimento de Estimación de π:\n");
    printf("Puntos Totales: %d\n", puntos_totales);
    printf("Puntos Dentro del Círculo: %d\n", puntos_dentro_circulo);
    printf("Estimación de π: %.6f\n", estimacion_pi);
    printf("Valor Real de π:    %.6f\n", M_PI);

    return 0;
}

Compilar y Ejecutar el Experimento

## Crear el archivo fuente
nano ~/project/estimacion_pi.c

## Compilar el programa (nótese el enlace a la biblioteca matemática)
gcc ~/project/estimacion_pi.c -o ~/project/estimacion_pi -lm

## Ejecutar el experimento
~/project/estimacion_pi

Ejemplo de salida:

Experimento de Estimación de π:
Puntos Totales: 100000
Puntos Dentro del Círculo: 78540
Estimación de π: 3.141600
Valor Real de π:    3.141593

Conceptos Clave Explicados

  1. Múltiples Ensayos:

    • Ejecutamos un gran número de ensayos aleatorios (100,000)
    • Cada ensayo genera un punto aleatorio en un cuadrado de 1x1
  2. Contar Éxitos:

    • Seguimos los puntos totales y los puntos dentro del cuarto de círculo
    • El éxito se define como un punto que cae dentro del círculo
  3. Estimación de Probabilidad:

    • Probabilidad = (Puntos Exitosos) / (Puntos Totales)
    • Multiplicar por 4 para estimar π debido al método del cuarto de círculo

Técnicas Importantes

  • (double)rand() / RAND_MAX genera un decimal aleatorio entre 0 y 1
  • sqrt(x*x + y*y) calcula la distancia desde el origen
  • Un gran número de ensayos mejora la precisión de la estimación

Estimar Probabilidad = Éxitos/Ensayos

En este paso final, demostraremos cómo calcular la probabilidad analizando la proporción de resultados exitosos a los ensayos totales en un escenario más práctico.

Experimento de Probabilidad de Lanzamiento de Dados

Simularemos el lanzamiento de dos dados y calcularemos la probabilidad de obtener una suma específica (por ejemplo, una suma de 7).

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NUM_ENSAYOS 100000
#define SUMA_OBJETIVO 7

int lanzar_dado() {
    return rand() % 6 + 1;
}

int main() {
    // Semilla para el generador de números aleatorios
    srand(time(NULL));

    // Contadores para lanzamientos totales y lanzamientos exitosos
    int lanzamientos_totales = 0;
    int lanzamientos_exitosos = 0;

    // Ejecutar múltiples ensayos
    for (int i = 0; i < NUM_ENSAYOS; i++) {
        // Lanzar dos dados
        int dado1 = lanzar_dado();
        int dado2 = lanzar_dado();

        // Verificar si la suma coincide con el objetivo
        if (dado1 + dado2 == SUMA_OBJETIVO) {
            lanzamientos_exitosos++;
        }
        lanzamientos_totales++;
    }

    // Calcular la probabilidad
    double probabilidad = (double)lanzamientos_exitosos / lanzamientos_totales;

    printf("Experimento de Probabilidad de Lanzamiento de Dados:\n");
    printf("Suma Objetivo: %d\n", SUMA_OBJETIVO);
    printf("Lanzamientos Totales: %d\n", lanzamientos_totales);
    printf("Lanzamientos Exitosos: %d\n", lanzamientos_exitosos);
    printf("Probabilidad Estimada: %.4f\n", probabilidad);

    // Probabilidad teórica para comparación
    printf("Probabilidad Teórica: %.4f\n", 1.0/6);

    return 0;
}

Compilar y Ejecutar el Experimento

## Crear el archivo fuente
nano ~/project/probabilidad_dados.c

## Compilar el programa
gcc ~/project/probabilidad_dados.c -o ~/project/probabilidad_dados

## Ejecutar el experimento
~/project/probabilidad_dados

Ejemplo de salida:

Experimento de Probabilidad de Lanzamiento de Dados:
Suma Objetivo: 7
Lanzamientos Totales: 100000
Lanzamientos Exitosos: 16644
Probabilidad Estimada: 0.1664
Probabilidad Teórica: 0.1667

Conceptos Clave Explicados

  1. Cálculo de Probabilidad:

    • Probabilidad = (Número de Resultados Exitosos) / (Número Total de Ensayos)
    • En este caso: Lanzamientos Exitosos / Lanzamientos Totales
  2. Simulación de Monte Carlo:

    • Un gran número de ensayos (100,000) proporciona una estimación precisa.
    • La probabilidad simulada se acerca mucho a la probabilidad teórica.
  3. Aleatoriedad y Precisión:

    • srand(time(NULL)) asegura secuencias aleatorias diferentes.
    • Más ensayos aumentan la precisión de la estimación.

Interpretación de la Probabilidad

  • La probabilidad estimada (0.1664) está muy cerca de la probabilidad teórica (1/6 ≈ 0.1667).
  • Demuestra cómo el método de Monte Carlo puede estimar probabilidades.

Resumen

En este laboratorio, aprendimos a definir un experimento aleatorio utilizando la simulación de Monte Carlo en C. Creamos una simple simulación de lanzamiento de una moneda para demostrar los conceptos clave. Primero, inicializamos el generador de números aleatorios y simulamos lanzamientos de moneda, contando el número de resultados exitosos (caras). Luego, estimamos la probabilidad de caras dividiendo el número de resultados exitosos por el número total de ensayos. La salida mostró que la probabilidad estimada estaba cerca del valor esperado de 0.5 para un lanzamiento justo de una moneda.