Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

1

.js
Скачиваний:
16
Добавлен:
28.06.2021
Размер:
7.57 Кб
Скачать
// @ts-check

/**
 * Критические значения хи квадрат 
 * при alpha = 0.05
 * для числа степеней свободы от 1 до 20
 */ 
const chi2Criticals = [
    3.8,
    6,
    7.8,
    9.5,
    11.1,
    12.6,
    14.1,
    15.5,
    16.9,
    18.3,

    19.7,
    21,
    22.4,
    23.7,
    25,
    26.3,
    27.6,
    28.9,
    30.1,
    31.4
]

/**
 * Получить значение согласно непрерывному равномерному распределению [min, max]
 * @param {number} min 
 * @param {number} max 
 */
function uniform(min, max) {
    const u = Math.random()
    return min + (max - min) * u
}

/**
 * Получить значение согласно дискретному равномерному распределению [min, max]
 * @param {number} lambda - параметр интенсивности
 */
function poisson(lambda) {
    const u = Math.random()
    let p = Math.exp(-lambda)

    let f = p
    let x = 0
    while (!(u < f)) {
        p = lambda * p / (x+1)
        f += p
        x += 1
    }

    return x
}

/**
 * @typedef {Object} IResultItem
 * @property {number} count - наблюдаемая частота 
 * @property {number?} theory - теоретическая частота 
 */

/**
 * Проверка непрерывного равномерного распределения
 * @param {Record<number, IResultItem>} result - Результат выборки сгруппированный в единичные интервалы. 10 => интервал [10, 11)
 * @param {number} N - объем выборки
 */
function checkUniform(result, N) {
    const intervals = Object.keys(result).map((key) => +key) 
    const xCenters = intervals.map((begin) => +begin + 0.5) // т.к. интервал [i, i+1], то центр i + 0.5

    // Выборочное среднее
    const mean = 1 / N * intervals.reduce((acc, xi, index) => {
        const ni = result[xi].count
        return acc + (xCenters[index] * ni)
    }, 0)

    // Дисперсия
    const variable = 1 / N * intervals.reduce((acc, xi, index) => {
        const ni = result[xi].count
        return acc + (ni * ((xCenters[index] - mean)**2))
    }, 0)

    // Среднеквадратичное отклонение
    const sd = Math.sqrt(variable)

    // оценки параметров a, b равномерного распределения
    const a$ = mean - Math.sqrt(3) * sd
    const b$ = mean + Math.sqrt(3) * sd

    // плотность
    const density = 1 / (b$ - a$)
    
    // разбитие, число значений
    const s = intervals.length

    // теоритические частоты
    result[intervals[0]].theory = N * density * (intervals[1] - a$)
    if (s > 2) {
        for (let i = 1; i < s-1; i++) {
            result[intervals[i]].theory = N * density * 1 // 1 взят за ширину
        }
    }
    result[intervals[s-1]].theory = N * density * (b$ - intervals[s-1])

    // число степеней свободы k = s - 3
    const k = s - 3

    // критерий согласия Пирсона (хи квадрат)
    const chi2 = intervals.reduce((acc, xi) => {
        const ni = result[xi].count
        const niTheory = result[xi].theory
        return acc + ((ni - niTheory)**2 / niTheory)
    }, 0)

    const chi2Critical = chi2Criticals[k-1]

    const resultTable =  {}
    Object.keys(result).forEach((key) => {
        resultTable[`${key}-${+key+1}`] = result[key]
    })
    console.table(resultTable)
    console.log(`Степень свободы k = ${k}`)
    console.log(`Уровень значимости alpha = 0.05`)

    console.log(`Хи квадрат наблюдаемое = ${chi2}`)
    console.log(`Хи квадрат критическое = ${chi2Critical}`)
    console.log(`Хи2 наблюдаемое ${chi2 < chi2Critical ? '<' : '>='} Хи2 критическое => исследуемая случайная переменная ${chi2 < chi2Critical ? '' : 'не '}принадлежит закону распределения`)
}

function factorial(n) {
    if (n < 2) {
        return 1
    }

    let result = 1
    for (let i = 1; i <= n; i++) {
        result *= i
    }
    return result
}

/**
 * Проверка дискретного равномерного распределения
 * @param {Record<number, IResultItem>} result - Результат выборки сгруппированный в единичные интервалы. 10 => интервал [10, 11)
 * @param {number} N - объем выборки
 */
function checkPoisson(result, N) {
    const values = Object.keys(result).map((str) => +str)
    // разбитие, число значений
    const s = values.length

    // выборочное среднее
    const mean = 1 / N * values.reduce((acc, xi) => {
        const ni = result[xi].count
        return acc + (+xi * ni)
    }, 0)

    const expectedLambda = mean

    values.forEach((value) => {
        const fact = factorial(value)
        const pi = Math.exp(-expectedLambda) * (expectedLambda**value) / fact
        result[value].theory = pi * N
    })
    
    // критерий согласия Пирсона (хи квадрат)
    const chi2 = values.reduce((acc, xi) => {
        const ni = result[xi].count
        const niTheory = result[xi].theory
        return acc + ((ni - niTheory)**2 / niTheory)
    }, 0)

    // степени свободы
    const k = s - 2

    // хи квадрат критическое при заданном k
    const chi2Critical = chi2Criticals[k-1]
    console.table(result)

    console.log(`lamda теоретическая = ${expectedLambda}`)
    console.log(`Степень свободы k = ${k}`)
    console.log(`Уровень значимости alpha = 0.05`)

    console.log(`Хи квадрат наблюдаемое = ${chi2}`)
    console.log(`Хи квадрат критическое = ${chi2Critical}`)
    console.log(`Хи2 наблюдаемое ${chi2 < chi2Critical ? '<' : '>='} Хи2 критическое => исследуемая случайная переменная ${chi2 < chi2Critical ? '' : 'не '}принадлежит закону распределения`)
}

/* Начало */
function main() {
    const a = 1
    const b = 7

    const result1 = {}
    for (let i = 0; i < (b-a); i++) {
        result1[a+i] = { count: 0 }
    }
    const N1 = 200
    console.log(`Равномерное непрерывное распределение (опытов ${N1}):`)
    for (let index = 0; index < N1; index++) {
        const x = Math.trunc(uniform(a,b))
        result1[x].count += 1
    }
    // @ts-ignore
    checkUniform(result1, N1)

    console.log()

    
    const result2 = {}
    const N2 = 20000
    const lambda = 5
    console.log(`Пуассоновское распределение (lambda = ${lambda}, опытов ${N2}):`)
    for (let index = 0; index < N2; index++) {
        const x = poisson(lambda)
        
        if (result2[x]) {
            result2[x].count += 1
        } else {
            result2[x] = { count: 1 }
        }
        
    }
    // @ts-ignore
    checkPoisson(result2, N2)
}
main()
Соседние файлы в предмете Компьютерное моделирование