แบบจำลองการเพิ่มขึ้นของเชื้อมาลาเรียในคน

กำลังเตรียมdraft งานเก่าที่ทำมาหลายปีแล้วไม่ได้มีโอกาสส่งตีพิมพ์สักที เลยเอามาปัดฝุ่นใหม่โดยใช้ Mathematica รู้สึกได้เลยว่า code มันเขียนไม่กี่บรรทัดเอง แถมแชร์ก็ง่าย https://www.wolframcloud.com/obj/sompob/Published/NJW_Im4a.nb

มันจะกระจายยังไงถ้าไม่ทำอะไรเลย

ทำเล่นๆขำ ว่าถ้าไวรัสที่ว่ามันกระจายไปตามจังหวัดต่างๆที่ว่า จำนวนคนติดเชื้อมันพุ่งเยอะขนาดไหน แบบว่าถ้าคนมันคิดว่าเป็นหวัดธรรมดา

โห … ตัวเลขพุ่งขึ้นเร็วมากกก ถ้าเห็นโมเดลทำนายเรื่องอะไรก็ตามอยากให้คิดกันเสมอว่า

“All models are wrong, but some are useful”

ฉะนั้นอย่าเพิ่งไปเชื่ออะไรง่ายๆครับ ทุกโมเดลมันมีสมมุติฐานในการสร้างของมัน ระบบในธรรมชาติมันซับซ้อนมากครับ ไม่มีใครที่จะโมเดลมันได้หมดหรอกครับ ทุกโมเดลมันจะตัดความยุ่งยาก ซับซ้อนออกเพื่อให้โมเดลได้ง่ายครับ

เรียก compiled function จาก compiled function

โดยปกติ Mathematica หรือภาษา Wolfram จะมีปัญหากับการเรียก function ที่สร้างจาก Compile ใน function ที่จะสร้างจาก Compile อีกทีได้ (ส่วนใหญ่เป็นเรื่องที่เกี่ยวกับว่า Funcions ไหนที่มัน compile ได้หรือไม่ได้) แต่ใน version 12 นี้เราสามารถที่จะทำแบบนั้นได้ ถ้า function เหล่านั้นถูก compile ด้วยคำสั่ง FunctionCompile ซึ่งผมมองว่ามันสะดวกอย่างมาก และที่สำคัญเราสามารถที่จะ export สร้างเป็น library ไฟล์ได้ด้วย โดยคำสั่ง FunctionCompileExport สกุลไฟล์ที่สร้างได้ก็ได้แก่

ตัวอย่างการเรียกใช้ compiled function ใน compiled function อีกที ก็สมมุติให้ผมมี function สำหรับทำ bisection เพื่อหาค่าที่ทำให้ function ที่สนใจเป็น 0 หรือใกล้ 0 มากๆ

BisectionMethod = FunctionCompile[
    Function[
        {Typed[f, {"Real64"} -> "Real64"], Typed[lim0, "Real64"], Typed[lim1, "Real64"]},
      Module[{Maxiter = 100, tol = 10.^-8, iter = 0, x0 = lim0, x1 = lim1, mid = 0.0, f0, f1, fmid},
      f0 = f[x0]; 
      f1 = f[x1];
            While[Abs[x1 - x0] >= tol && iter++ < Maxiter,
                mid = (x1 + x0)/2.;
                fmid = f[mid];
                If[Xor[fmid > 0, f0 > 0],
                    x1 = mid; f1 = fmid,
                    x0 = mid; f0 = fmid]];
               mid]]]

โดยfunction ที่ผมจะหา root คือ f(x) = sin(x)+exp(x)

f = FunctionCompile[Function[Typed[arg, "Real64"], Sin[arg] + Exp[arg]]]

จะเห็นได้ว่าทั้ง BisectionMethod และ f ถูกสร้างจาก FunctionCompile แต่ f จะถูกเรียกเข้าไปใช้ใน BisectionMethod อีกที

BisectionMethod[f, -1.0, 1.0]-FindRoot[Sin[x] + Exp[x], {x, -1}][[1, 2]]
(* -5.18667*10^-11 *)

การแพร่กระจายของโรคไข้เลือดออกในจีน

พอดีว่าต้องทำ slides ไปโชว์ว่างานที่รับอยู่ไปถึงไหนแล้ว มันมีส่วนหนึ่งที่ต้องทำให้เห็นว่าผลที่ได้จากโมเดลการระบาดของไข้เลือดออกในจีนกับข้อมูลจริงนั้นมันใกล้เคียงกัน พอดีผมไปเจองานอยู่งานหนึ่งที่น่าสนใจคือ https://bmcmedicine.biomedcentral.com/articles/10.1186/s12916-015-0336-1

Figure 5

เขามีplotกราฟที่แสดงให้เห็นว่ามีการรายงานผู้ติดเชื้อไข้เลือดออกครั้งแรกของแต่ล่ะเมืองของจีนในปีใด ซึ่งผมก็ลองเอามาทำเป็น animation ในโปรแกรม Mathematica ดูสำหรับเปรียบเทียบให้เห็นไปเลยกับโมเดลที่ทำ

โดยผมเขียน code ตามนี้ครับ

เรื่องการเรียกใช้ package ใน package อีกทีของภาษา Wolfram

พอดีกำลังรับงานพัฒนาโมเดลตัวหนึ่งด้วยภาษา Wolfram แล้วเจอปัญหาเรื่องการเรียกใช้ Package ในอีก Package หนึ่ง code ที่เขาส่งมาให้ช่วยดูให้มันมีการเรียกใช้ package ตั้งแต่คำสั่ง BeginPackage เช่น

BeginPackage[ "Package`", {"Package1`", "Package2`"}]
  ...

แต่ปรากฏว่าหลังจากที่ทำการ deploy ไปแล้ว เจอว่ามันมีการคำนวณอะไรบางอย่างผิด ทั้งที่ในตัว unit test ก็ไม่เจอ ผมก็นั่งไล่ดูทีล่ะบรรทัดจนพบว่ามันมีการเขียนทับ functions กัน เพราะชื่อดันเหมือนกัน

ผมก็เลยเปลี่ยนวิธีการเรียก packages ด้วย Needs ไปใช้วิธีเรียกทีล่ะตัวหลังคำสั่ง BeginPackage แทน เช่น

BeginPackage[ "Package`"]
  Needs[ "Package1`"]
  Needs[ "Package2`"]
  ...

ด้วยวิธีนี้ตัว คำสั่งจาก package1 หรือ package2 จะถูกเรียกใช้ได้ภายใน package แต่ด้านนอก package จะเรียกไม่ได้ พูดง่ายๆคือไม่มีผลอะไรกับตัวแปรนอก package