; your code goes here
;;; =============================================
;;; Функції (deffunctions)
;;; =============================================
(deffunction cantor-cdf (?x) ;;; Функція для обчислення кумулятивної функції розподілу Кантора
(if (<= ?x 0.0) then (return 0.0))
(if (>= ?x 1.0) then (return 1.0))
(if (and (> ?x 0.0) (<= ?x (/ 1.0 3.0))) then
(return (/ (cantor-cdf (* 3.0 ?x)) 2.0)))
(if (and (> ?x (/ 1.0 3.0)) (<= ?x (/ 2.0 3.0))) then
(return 0.5))
(if (and (> ?x (/ 2.0 3.0)) (< ?x 1.0)) then
(return (+ 0.5 (/ (cantor-cdf (- (* 3.0 ?x) 2.0)) 2.0))))
(return 0.0) ;;; Не повинно досягатися, якщо x в [0,1]
)
;;; Допоміжні функції для роботи з multifields
(deffunction get-min-from-multifield ($?mf) ;;; Отримати мінімальне значення з multifield
(if (eq (length$ $?mf) 0) then (return 0.0))
(bind ?min-val (nth$ 1 $?mf))
(foreach ?val $?mf
(if (< ?val ?min-val) then (bind ?min-val ?val))
)
(return ?min-val)
)
(deffunction get-max-from-multifield ($?mf) ;;; Отримати максимальне значення з multifield
(if (eq (length$ $?mf) 0) then (return 0.0))
(bind ?max-val (nth$ 1 $?mf))
(foreach ?val $?mf
(if (> ?val ?max-val) then (bind ?max-val ?val))
)
(return ?max-val)
)
(deffunction generate-thresholds (?min-val ?max-val ?alphabet-size) ;;; Генерує пороги інтервалів
(bind ?range-val (- ?max-val ?min-val))
(bind ?thresholds (create$))
;;; Цикл alphabet_size + 1 разів для обчислення i/alphabet_size
(loop-for-count (?i 0 ?alphabet-size)
(bind ?p (if (= ?alphabet-size 0) then 0.0 else (/ (float ?i) ?alphabet-size)))
(bind ?cdf-val (cantor-cdf ?p))
(bind ?threshold-val (+ ?min-val (* ?cdf-val ?range-val)))
(bind ?thresholds (create$ ?thresholds ?threshold-val))
)
;;; Переконуємося, що останній поріг точно дорівнює max-val, якщо діапазон не нульовий (для обробки можливих неточностей float)
(if (and (> ?range-val 0.0) (> (length$ ?thresholds) 0) )
then
(if (< (nth$ (length$ ?thresholds) ?thresholds) ?max-val)
then
(bind ?thresholds (replace$ ?thresholds (length$ ?thresholds) (length$ ?thresholds) ?max-val))
)
)
(return ?thresholds)
)
(deffunction map-value-to-letter (?value ?intervals-mf ?alphabet-chars-mf) ;;; Відображає числове значення на символ алфавіту
(bind ?num-chars (length$ ?alphabet-chars-mf))
(bind ?mapped-letter (nth$ ?num-chars ?alphabet-chars-mf)) ;;; За замовчуванням остання літера
(loop-for-count (?idx 1 ?num-chars)
(bind ?lower-bound (nth$ ?idx ?intervals-mf))
(bind ?upper-bound (nth$ (+ ?idx 1) ?intervals-mf))
(if (and (< ?idx ?num-chars) (>= ?value ?lower-bound) (< ?value ?upper-bound)) then
(bind ?mapped-letter (nth$ ?idx ?alphabet-chars-mf))
(return ?mapped-letter)
)
;;; Останній інтервал включає верхню межу
(if (and (= ?idx ?num-chars) (>= ?value ?lower-bound) (<= ?value ?upper-bound)) then
(bind ?mapped-letter (nth$ ?idx ?alphabet-chars-mf))
(return ?mapped-letter)
)
)
(return ?mapped-letter)
)
(deffunction build-linguistic-row-mf (?original-series-mf ?intervals-mf ?alphabet-chars-mf) ;;; Будує лінгвістичний ряд (multifield)
(bind ?ling-row (create$))
(foreach ?val ?original-series-mf
(bind ?letter (map-value-to-letter ?val ?intervals-mf ?alphabet-chars-mf))
(bind ?ling-row (create$ ?ling-row ?letter))
)
(return ?ling-row)
)
;;; =============================================
;;; Шаблони фактів (deftemplates)
;;; =============================================
(deftemplate precedence-cell ;;; Шаблон для комірки матриці передування
(slot char1 (type SYMBOL))
(slot char2 (type SYMBOL))
(slot count (type INTEGER) (default 0))
)
;;; =============================================
;;; Початкові факти та керування (deffacts)
;;; =============================================
(deffacts initial-data
(numeric-series-raw (values 2.828 2.804 2.776 2.772 2.795 2.77 2.74 2.726 2.716 2.72 2.737))
(alphabet-definition (name "ABCDE"))
(status (phase initialize)) ;;; Початковий стан
)
;;; =============================================
;;; Правила - Керування потоком та логіка (defrules)
;;; =============================================
;;; --- Фаза 1: Налаштування ---
(defrule setup-alphabet-and-sorting-init
(status (phase initialize))
(alphabet-definition (name ?alpha-name))
(numeric-series-raw (values $?nums))
=>
(assert (alphabet (chars (explode$ ?alpha-name))))
(printout t "Фаза: Налаштування завершено. Алфавіт завантажено." crlf)
(foreach ?num ?nums
(assert (number-to-sort (value ?num)))
)
(assert (sorted-list-accumulator (values)))
(printout t "Фаза: Ініціалізація сортування..." crlf)
(assert (status (phase sorting)))
)
;;; --- Фаза 2: Сортування (Стиль сортування вибором) ---
(defrule selection-sort-step
?s <- (status (phase sorting))
?min-fact <- (number-to-sort (value ?min-val))
(not (number-to-sort (value ?v&:(< ?v ?min-val)))) ;;; ?min-val - поточний мінімум
?acc <- (sorted-list-accumulator (values $?sorted-vals))
=>
(retract ?min-fact)
(modify ?acc (values $?sorted-vals ?min-val))
(printout t "Відсортовано: " ?min-val crlf)
)
(defrule finish-sorting
(status (phase sorting))
(not (number-to-sort)) ;;; Всі числа переміщено з number-to-sort
?acc <- (sorted-list-accumulator (values $?final-sorted-list))
=>
(retract ?acc)
(assert (sorted-series (values $?final-sorted-list)))
(printout t "Фаза: Сортування завершено. Відсортований ряд: " $?final-sorted-list crlf)
(assert (status (phase intervals-needed)))
)
;;; --- Фаза 3: Генерація інтервалів ---
(defrule generate-intervals-rule
(status (phase intervals-needed))
(sorted-series (values $?s))
(alphabet (chars $?a))
=>
(bind ?min-val (nth$ 1 $?s)) ;;; Припускаємо, що $?s не порожній після сортування
(bind ?max-val (nth$ (length$ $?s) $?s))
(bind ?alphabet-size (length$ $?a))
;;; Уникаємо ділення на нуль, якщо алфавіт порожній
(if (= ?alphabet-size 0) then (bind ?alphabet-size 1))
(bind ?thresholds-mf (generate-thresholds ?min-val ?max-val ?alphabet-size))
(assert (intervals (thresholds ?thresholds-mf)))
(printout t "Фаза: Інтервали згенеровано. Пороги: " ?thresholds-mf crlf)
(assert (status (phase linguistic-row-needed)))
)
;;; --- Фаза 4: Побудова лінгвістичного ряду ---
(defrule build-linguistic-row-rule
(status (phase linguistic-row-needed))
;;; Використовуємо оригінальний несортований ряд для відображення
(numeric-series-raw (values $?orig-s))
(intervals (thresholds $?t))
(alphabet (chars $?a))
=>
(bind ?ling-row-mf (build-linguistic-row-mf ?orig-s $?t $?a))
(assert (linguistic-series (letters ?ling-row-mf)))
(printout t "Фаза: Лінгвістичний ряд побудовано. Ряд: " ?ling-row-mf crlf)
(assert (status (phase matrix-needed)))
)
;;; --- Фаза 5: Побудова матриці передування ---
(defrule matrix-initialization-and-computation
(status (phase matrix-needed))
(alphabet (chars $?alphabet_chars))
(linguistic-series (letters $?ling_series))
=>
;;; Ініціалізація всіх можливих комірок матриці передування нулями
(printout t "Фаза: Ініціалізація комірок матриці передування..." crlf)
(foreach ?char1 ?alphabet_chars
(foreach ?char2 ?alphabet_chars
(assert (precedence-cell (char1 ?char1) (char2 ?char2) (count 0)))
)
)
;;; Обчислення значень лічильників матриці з лінгвістичного ряду
(printout t "Фаза: Обчислення значень лічильників матриці..." crlf)
(if (> (length$ ?ling_series) 1) then
(loop-for-count (?idx 1 (- (length$ ?ling_series) 1))
(bind ?c1 (nth$ ?idx ?ling_series))
(bind ?c2 (nth$ (+ ?idx 1) ?ling_series))
(bind ?cell-facts (find-all-facts ((?f precedence-cell))
(and (eq ?f:char1 ?c1) (eq ?f:char2 ?c2))))
(if (> (length$ ?cell-facts) 0) then
(bind ?cell-fact (nth$ 1 ?cell-facts)) ;;; Має бути унікальним
(modify ?cell-fact (count (+ (fact-slot-value ?cell-fact count) 1)))
else
;;; Цей випадок в ідеалі не має траплятися, якщо всі комірки були ініціалізовані
(printout t "Увага: Комірка для " ?c1 " -> " ?c2 " не знайдена під час оновлення лічильника." crlf)
(assert (precedence-cell (char1 ?c1) (char2 ?c2) (count 1)))
)
)
)
(printout t "Фаза: Обчислення матриці завершено." crlf)
(assert (status (phase reporting)))
)
;;; --- Фаза 6: Формування звіту ---
(defrule display-results
(status (phase reporting))
(alphabet (chars $?a))
(intervals (thresholds $?t))
(linguistic-series (letters $?ls))
(numeric-series-raw (values $?origs))
(sorted-series (values $?sorteds))
=>
(printout t crlf "--- ФІНАЛЬНІ РЕЗУЛЬТАТИ ---" crlf)
(printout t "Початковий числовий ряд: " $?origs crlf)
(printout t "Відсортований числовий ряд: " $?sorteds crlf)
(printout t "Алфавіт: " (implode$ ?a) crlf)
(printout t "Пороги інтервалів: " ?t crlf)
(printout t "Лінгвістичний ряд: " ?ls crlf)
(printout t "Матриця передування:" crlf)
(printout t " ")
(foreach ?char-col-hdr ?a (printout t ?char-col-hdr " "))
(printout t crlf)
(foreach ?char-row ?a
(printout t ?char-row " | ")
(foreach ?char-col ?a
(do-for-all-facts ((?f precedence-cell))
(and (eq ?f:char1 ?char-row) (eq ?f:char2 ?char-col))
(printout t ?f:count " ")
)
)
(printout t crlf)
)
(printout t "--- КІНЕЦЬ ЗВІТУ ---" crlf)
(assert (status (phase done)))
(halt)
)
;;; Для запуску, зазвичай, потрібно виконати (reset) а потім (run).
(exit)
; empty line at the end