0% encontró este documento útil (0 votos)
3 vistas13 páginas

Helios

El documento describe un programa para la predicción climática utilizando cadenas de Markov, que permite ingresar un historial de estados climáticos y calcular la matriz de transición. Incluye funcionalidades para predecir el clima a corto plazo, realizar recomendaciones energéticas basadas en la eficiencia de los estados climáticos y calcular la distribución estacionaria a largo plazo. El programa se estructura en secciones que abarcan desde la entrada de datos hasta la visualización de resultados.

Cargado por

Anuel Velázquez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
3 vistas13 páginas

Helios

El documento describe un programa para la predicción climática utilizando cadenas de Markov, que permite ingresar un historial de estados climáticos y calcular la matriz de transición. Incluye funcionalidades para predecir el clima a corto plazo, realizar recomendaciones energéticas basadas en la eficiencia de los estados climáticos y calcular la distribución estacionaria a largo plazo. El programa se estructura en secciones que abarcan desde la entrada de datos hasta la visualización de resultados.

Cargado por

Anuel Velázquez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

// Helios-Tech -- Cadenas de Markov para Prediccion Climatica

// TB1 | Matematica Discreta | Grupo 07 | NRC: 15344

#include <iostream>

#include <iomanip>

#include <string>

#include <vector>

#include <cmath>

using namespace std;

// SECCION 1 -- CONSTANTES

const int NUM_ESTADOS = 4;

const int DIAS_HISTORIAL = 60;

const int DIAS_PREDICCION = 4;

const double TOLERANCIA = 1e-9;

const int MAX_ITER_ESTACIONARIA = 10000;

const string NOMBRES[NUM_ESTADOS] = {

"Soleado", "Parcialmente Soleado", "Parcialmente Nublado", "Nublado"

};

const string ABREV[NUM_ESTADOS] = { " S ", " PS ", " PN ", " N " };

const double EFICIENCIA[NUM_ESTADOS] = { 95.0, 70.0, 40.0, 10.0 };

// SECCION 2 -- INTERFAZ

void mostrarMenu() {
cout << "\n [1] Ingresar historial (60 dias)\n";

cout << " [2] Mostrar historial\n";

cout << " [3] Matriz de Transicion\n";

cout << " [4] Predecir clima (n+1 a n+4)\n";

cout << " [5] Recomendacion energetica\n";

cout << " [6] Distribucion Estacionaria\n";

cout << " [7] Salir\n";

cout << " Opcion: ";

void mostrarEstados() {

cout << "\n Estados: ";

for (int i = 0; i < NUM_ESTADOS; i++)

cout << "[" << i << "] " << NOMBRES[i] << " ";

cout << "\n\n";

bool validarEstado(int e) { return (e >= 0 && e < NUM_ESTADOS); }

// SECCION 3 -- HISTORIAL

vector<int> ingresarHistorial() {

vector<int> historial;

[Link](DIAS_HISTORIAL);

mostrarEstados();

cout << " Ingrese el estado [0-3] para cada dia:\n\n";

for (int dia = 1; dia <= DIAS_HISTORIAL; dia++) {

int estado = -1;


bool valido = false;

while (!valido) {

cout << " Dia " << setw(2) << dia << " -> ";

cin >> estado;

if ([Link]() || !validarEstado(estado)) {

[Link](); [Link](1000, '\n');

cout << " [!] Valor invalido. Ingrese 0, 1, 2 o 3.\n";

else { valido = true; }

historial.push_back(estado);

cout << " " << NOMBRES[estado] << "\n";

cout << "\n [OK] Historial de " << DIAS_HISTORIAL << " dias registrado.\n";

return historial;

void mostrarHistorial(const vector<int>& h) {

if ([Link]()) { cout << "\n [!] Sin historial aun.\n"; return; }

cout << "\n Dia Estado\n " << string(34, '-') << "\n";

for (int i = 0; i < (int)[Link](); i++)

cout << " " << setw(3) << (i + 1) << " " << NOMBRES[h[i]] << "\n";

// SECCION 4 -- MATRIZ DE TRANSICION

// p_ij = n_ij / n_i* (Anderson & Goodman, 1957, ec. 2.8)

vector<vector<int>> construirConteos(const vector<int>& h) {

vector<vector<int>> c(NUM_ESTADOS, vector<int>(NUM_ESTADOS, 0));


for (int i = 0; i < (int)[Link]() - 1; i++)

c[h[i]][h[i + 1]]++;

return c;

vector<vector<double>> construirMatrizTransicion(const vector<vector<int>>& c) {

vector<vector<double>> P(NUM_ESTADOS, vector<double>(NUM_ESTADOS, 0.0));

for (int i = 0; i < NUM_ESTADOS; i++) {

int total = 0;

for (int j = 0; j < NUM_ESTADOS; j++) total += c[i][j];

for (int j = 0; j < NUM_ESTADOS; j++)

P[i][j] = (total == 0) ? 1.0 / NUM_ESTADOS : (double)c[i][j] / total;

return P;

void mostrarMatrizTransicion(const vector<vector<double>>& P) {

cout << "\n Matriz de Transicion P (Anderson & Goodman, 1957)\n\n";

cout << " " << setw(24) << " ";

for (int j = 0; j < NUM_ESTADOS; j++) cout << setw(9) << ABREV[j];

cout << "\n " << string(62, '-') << "\n";

for (int i = 0; i < NUM_ESTADOS; i++) {

cout << " " << left << setw(24) << NOMBRES[i] << right;

double suma = 0.0;

for (int j = 0; j < NUM_ESTADOS; j++) {

cout << setw(9) << fixed << setprecision(4) << P[i][j];

suma += P[i][j];

cout << " (suma=" << fixed << setprecision(2) << suma << ")\n";
}

// SECCION 5 -- PREDICCION CLIMATICA

// pi_k = pi_0 x P^k (Norris, 1997; Weisstein, 2026)

vector<double> multiplicarVectorMatriz(const vector<double>& v,

const vector<vector<double>>& P) {

vector<double> r(NUM_ESTADOS, 0.0);

for (int j = 0; j < NUM_ESTADOS; j++)

for (int i = 0; i < NUM_ESTADOS; i++)

r[j] += v[i] * P[i][j];

return r;

vector<double> construirVectorInicial() {

mostrarEstados();

cout << " Estado del dia actual [0-3]: ";

int e = -1;

while (!validarEstado(e)) {

cin >> e;

if ([Link]() || !validarEstado(e)) {

[Link](); [Link](1000, '\n');

cout << " [!] Invalido. Intente de nuevo: ";

vector<double> pi0(NUM_ESTADOS, 0.0);

pi0[e] = 1.0;

cout << " Estado: " << NOMBRES[e] << "\n";


return pi0;

void predecirClima(const vector<vector<double>>& P) {

cout << "\n === PREDICCION CLIMATICA (pi_k = pi_0 x P^k) ===\n";

vector<double> pi = construirVectorInicial();

for (int k = 1; k <= DIAS_PREDICCION; k++) {

pi = multiplicarVectorMatriz(pi, P);

int mejor = 0;

for (int i = 1; i < NUM_ESTADOS; i++)

if (pi[i] > pi[mejor]) mejor = i;

cout << "\n Dia n+" << k << ":\n";

for (int i = 0; i < NUM_ESTADOS; i++) {

cout << " " << left << setw(24) << NOMBRES[i]

<< right << setw(7) << fixed << setprecision(2)

<< pi[i] * 100 << "%";

if (i == mejor) cout << " << mas probable";

cout << "\n";

// SECCION 6 -- RECOMENDACION ENERGETICA

// E[efic] = sum_i( pi_i * eficiencia_i )

void recomendacionEnergetica(const vector<vector<double>>& P) {

cout << "\n === RECOMENDACION ENERGETICA HELIOS-TECH ===\n";


vector<double> pi = construirVectorInicial();

cout << "\n";

for (int k = 1; k <= DIAS_PREDICCION; k++) {

pi = multiplicarVectorMatriz(pi, P);

double efic = 0.0;

for (int i = 0; i < NUM_ESTADOS; i++) efic += pi[i] * EFICIENCIA[i];

cout << " Dia n+" << k << " | Eficiencia: "

<< fixed << setprecision(1) << efic << "% -> ";

if (efic >= 75.0) cout << "ALTA GENERACION: descargar baterias.\n";

else if (efic >= 50.0) cout << "MODERADA: mantener carga parcial.\n";

else if (efic >= 25.0) cout << "BAJA: cargar baterias preventivamente.\n";

else cout << "CRITICO: activar generadores de respaldo.\n";

// SECCION 7 -- DISTRIBUCION ESTACIONARIA

//

// La distribucion estacionaria pi* satisface:

// pi* = pi* x P y sum(pi*_i) = 1

//

// Esto equivale al sistema lineal (Norris, 1997):

// pi*(P - I) = 0 sujeto a sum(pi*_i) = 1

//

// Metodo: Se reemplaza la ultima ecuacion de (P^T - I)*x = 0

// por la condicion de normalizacion sum(x_i) = 1,

// y se resuelve con eliminacion gaussiana.


// Resuelve Ax = b por eliminacion gaussiana con pivoteo parcial

// Retorna el vector solucion, o vector vacio si el sistema es singular

vector<double> gaussianElimination(vector<vector<double>> A, vector<double> b) {

int n = (int)[Link]();

for (int col = 0; col < n; col++) {

// Pivoteo parcial

int pivotRow = col;

for (int row = col + 1; row < n; row++)

if (fabs(A[row][col]) > fabs(A[pivotRow][col]))

pivotRow = row;

swap(A[col], A[pivotRow]);

swap(b[col], b[pivotRow]);

if (fabs(A[col][col]) < TOLERANCIA) return {}; // singular

for (int row = col + 1; row < n; row++) {

double factor = A[row][col] / A[col][col];

for (int k = col; k < n; k++)

A[row][k] -= factor * A[col][k];

b[row] -= factor * b[col];

// Sustitucion hacia atras

vector<double> x(n, 0.0);

for (int i = n - 1; i >= 0; i--) {

x[i] = b[i];

for (int j = i + 1; j < n; j++)

x[i] -= A[i][j] * x[j];


x[i] /= A[i][i];

return x;

void calcularDistribucionEstacionaria(const vector<vector<double>>& P) {

cout << "\n === DISTRIBUCION ESTACIONARIA (LARGO PLAZO) ===\n";

cout << "\n Resolviendo sistema: pi* = pi* x P, sum(pi*_i) = 1\n";

cout << " Metodo: Eliminacion Gaussiana (Norris, 1997)\n\n";

// Construir sistema (P^T - I) * x = 0, luego reemplazar ultima fila

// por condicion de normalizacion: x_0 + x_1 + ... + x_{n-1} = 1

int n = NUM_ESTADOS;

vector<vector<double>> A(n, vector<double>(n, 0.0));

vector<double> b(n, 0.0);

// Filas 0 .. n-2: columna j de (P^T - I), es decir P[j][i] - delta(i,j)

for (int i = 0; i < n - 1; i++) {

for (int j = 0; j < n; j++)

A[i][j] = P[j][i] - (i == j ? 1.0 : 0.0);

b[i] = 0.0;

// Ultima fila: condicion de normalizacion

for (int j = 0; j < n; j++) A[n - 1][j] = 1.0;

b[n - 1] = 1.0;

vector<double> pi = gaussianElimination(A, b);

if ([Link]()) {
// Fallback: metodo iterativo (potencia) si el sistema es singular

cout << " [!] Sistema singular. Usando metodo iterativo...\n\n";

[Link](n, 1.0 / n);

for (int iter = 0; iter < MAX_ITER_ESTACIONARIA; iter++) {

vector<double> piNuevo = multiplicarVectorMatriz(pi, P);

double diff = 0.0;

for (int i = 0; i < n; i++) diff += fabs(piNuevo[i] - pi[i]);

pi = piNuevo;

if (diff < TOLERANCIA) break;

// Verificacion: pi* x P debe ser igual a pi*

vector<double> verificacion = multiplicarVectorMatriz(pi, P);

double errorMax = 0.0;

for (int i = 0; i < n; i++)

errorMax = max(errorMax, fabs(verificacion[i] - pi[i]));

// Mostrar resultados

cout << " Estado climático pi* (%) Eficiencia ponderada\n";

cout << " " << string(58, '-') << "\n";

double eficLP = 0.0;

for (int i = 0; i < n; i++) {

eficLP += pi[i] * EFICIENCIA[i];

cout << " " << left << setw(26) << NOMBRES[i]

<< right << setw(8) << fixed << setprecision(2) << pi[i] * 100 << "%"

<< " " << setw(5) << fixed << setprecision(1)

<< pi[i] * EFICIENCIA[i] << "%\n";

}
cout << " " << string(58, '-') << "\n";

cout << " " << left << setw(26) << "TOTAL (eficiencia media)"

<< right << setw(8) << "100.00%"

<< " " << setw(5) << fixed << setprecision(1) << eficLP << "%\n";

cout << "\n Error de verificacion (|pi*P - pi*|_max): "

<< scientific << setprecision(2) << errorMax << "\n";

cout << "\n Interpretacion:\n";

cout << " A largo plazo, el sistema converge a esta distribucion\n";

cout << " independientemente del estado inicial (Weisstein, 2026).\n";

cout << " La eficiencia media de largo plazo es "

<< fixed << setprecision(1) << eficLP << "%.\n";

if (eficLP >= 75.0)

cout << " -> Operacion sostenida en ALTA GENERACION.\n";

else if (eficLP >= 50.0)

cout << " -> Operacion sostenida en nivel MODERADO.\n";

else if (eficLP >= 25.0)

cout << " -> Operacion sostenida en nivel BAJO: planificar respaldo.\n";

else

cout << " -> Operacion sostenida en nivel CRITICO: requiere generadores.\n";

// SECCION 8 -- MAIN

int main() {

vector<int> historial;

vector<vector<int>> conteos;
vector<vector<double>> matrizP;

bool cargado = false;

int opcion = 0;

cout << "\n Helios-Tech | Prediccion Climatica | Cadenas de Markov\n";

do {

mostrarMenu();

cin >> opcion;

if ((opcion >= 2 && opcion <= 6) && !cargado) {

cout << "\n [!] Primero ingrese el historial (opcion 1).\n";

continue;

switch (opcion) {

case 1:

historial = ingresarHistorial();

conteos = construirConteos(historial);

matrizP = construirMatrizTransicion(conteos);

cargado = true;

break;

case 2: mostrarHistorial(historial); break;

case 3: mostrarMatrizTransicion(matrizP); break;

case 4: predecirClima(matrizP); break;

case 5: recomendacionEnergetica(matrizP); break;

case 6: calcularDistribucionEstacionaria(matrizP); break;

case 7: cout << "\n Hasta pronto\n\n"; break;

default: cout << "\n [!] Opcion invalida.\n";


}

} while (opcion != 7);

return 0;

También podría gustarte