packages feed

hanalyze-0.1.0.0: demo/doe-optim/DOEDemo.hs

{-# LANGUAGE OverloadedStrings #-}
-- | Design of Experiments デモ (Phase O)。
--
-- 全要因/部分要因/ラテン方格/乱塊法/ANOVA/Power/質指標を一括検証。
module Main where

import Text.Printf (printf)

import qualified Hanalyze.Design.Factorial as DF
import qualified Hanalyze.Design.Block     as DB
import qualified Hanalyze.Design.Mixed     as DM
import qualified Hanalyze.Design.Anova     as DA
import qualified Hanalyze.Design.Power     as DP
import qualified Hanalyze.Design.Quality   as DQ

main :: IO ()
main = do
  putStrLn "═══════════════════════════════════════════════════════════════"
  putStrLn "  Design of Experiments デモ (Phase O)"
  putStrLn "═══════════════════════════════════════════════════════════════"
  putStrLn ""

  -- ── 1. 完全要因 2³ ──
  putStrLn "[1] 完全要因 2³ (3 因子各 2 水準 = 8 試行)"
  let d23 = DF.twoLevelFactorial 3
  printRows d23
  printf "  直交度スコア = %.4f (1 で完全直交)\n" (DQ.orthogonalityScore d23)
  printf "  D-efficiency = %.4f\n" (DQ.dEfficiency d23)
  printf "  条件数        = %.4f\n" (DQ.conditionNumber d23)
  putStrLn ""

  -- ── 2. 部分要因 2^(4-1): D=ABC ──
  putStrLn "[2] 部分要因 2^(4-1) (D = ABC)"
  let d4m1 = DF.fractionalFactorial 4 [[1, 2, 3]]
  printRows d4m1
  printf "  試行数: %d (= 完全 16 の半分)\n" (length d4m1)
  printf "  直交度スコア = %.4f\n" (DQ.orthogonalityScore d4m1)
  putStrLn ""

  -- ── 3. ラテン方格 4×4 ──
  putStrLn "[3] ラテン方格 4×4"
  let ls = DB.latinSquare 4
  mapM_ print ls
  putStrLn ""

  -- ── 4. 混合水準 2² × 3 ──
  putStrLn "[4] 混合水準 2² × 3 (= 12 試行)"
  let dMix = DF.mixedFactorial [2, 2, 3]
  printRows (take 4 dMix)
  putStrLn (printf "  ... (合計 %d 試行)" (length dMix) :: String)
  putStrLn ""

  -- ── 5. 乱塊法 (4 ブロック × 5 処理) ──
  putStrLn "[5] 乱塊法 4 ブロック × 5 処理 (各ブロック内ランダム順)"
  let rb = DB.randomizedBlock 4 5 42
  mapM_ (\(i, blk) -> printf "  Block %d: %s\n" (i :: Int) (show blk))
        (zip [1..] rb)
  putStrLn ""

  -- ── 6. ANOVA (一元配置) ──
  putStrLn "[6] 一元配置 ANOVA (3 群、各 5 観測)"
  let labels = concat [replicate 5 g | g <- ["A", "B", "C"]]
      vals   = [4.1, 4.5, 4.0, 4.3, 4.4   -- group A: mean 4.26
              , 5.0, 5.3, 5.2, 5.4, 4.9   -- group B: mean 5.16
              , 5.5, 5.8, 5.6, 5.9, 5.7] -- group C: mean 5.70
  DA.printAnovaTable (DA.oneWayAnova labels vals)
  putStrLn ""

  -- ── 7. 検出力解析 ──
  putStrLn "[7] 検出力解析"
  let d   = DP.cohensD 0 0.5 1.0       -- d = 0.5 (medium)
      pwr = DP.powerTTest d 30 30 0.05
  printf "  t 検定 (n=30 each, d=0.5, α=0.05): power = %.3f\n" pwr
  let n   = DP.sampleSizeTTest 0.5 0.8 0.05
  printf "  d=0.5, target power=0.8 → n = %d (each group)\n" n

  let f      = DP.cohensF [4.26, 5.16, 5.70] 0.30
      anovaP = DP.powerOneWayAnova f 3 5 0.05
  printf "  ANOVA (k=3, n=5/group, f=%.3f): power = %.3f\n" f anovaP
  putStrLn ""

  -- ── 8. 設計の質 ──
  putStrLn "[8] 設計の質 (2³ 完全要因に対する各指標)"
  printf "  直交?           %s\n" (show (DQ.isOrthogonal 1e-9 d23))
  printf "  直交度スコア    = %.4f\n" (DQ.orthogonalityScore d23)
  printf "  条件数          = %.4f\n" (DQ.conditionNumber d23)
  printf "  D-efficiency    = %.4f\n" (DQ.dEfficiency d23)
  printf "  A-efficiency    = %.4f\n" (DQ.aEfficiency d23)
  printf "  VIF (各列)      = %s\n"
         (show (map (\v -> read (printf "%.2f" v :: String) :: Double)
                    (DQ.vifList d23)))
  putStrLn ""

  putStrLn "═══════════════════════════════════════════════════════════════"
  putStrLn "  ✓ 完全要因/部分要因/ラテン方格/乱塊法/ANOVA/Power/品質"
  putStrLn "    全て動作"
  putStrLn "═══════════════════════════════════════════════════════════════"

  where
    printRows :: [[Double]] -> IO ()
    printRows rs = do
      mapM_ (\r -> putStrLn ("  " ++ showRow r)) rs
    showRow = unwords . map (printf "%+5.1f")

    -- DM.crossDesign suppress unused warning
    _ = DM.crossDesign [[1]] [[2]]