การแทนความรู้และตรรกศาสตร์ (Knowledge Representation and Logic)

1. บทนำ (Introduction)

1.1 ความสำคัญของการแทนความรู้

การแทนความรู้ (Knowledge Representation) เป็นสาขาหนึ่งของปัญญาประดิษฐ์ที่มุ่งเน้นการพัฒนาวิธีการแสดงความรู้ในรูปแบบที่คอมพิวเตอร์สามารถเข้าใจและประมวลผลได้ การแทนความรู้ที่ดีจะช่วยให้ระบบ AI สามารถ:

1.2 ประวัติความเป็นมา

flowchart TB
    subgraph era1["ยุคบุกเบิก (1950s-1960s)"]
        style era1 fill:#282828,stroke:#d79921,color:#ebdbb2
        A["Logic Theorist
(1956)"] B["General Problem Solver
(1959)"] end subgraph era2["ยุคระบบผู้เชี่ยวชาญ (1970s-1980s)"] style era2 fill:#282828,stroke:#98971a,color:#ebdbb2 C["MYCIN
(1976)"] D["Frames - Minsky
(1975)"] E["Semantic Networks"] end subgraph era3["ยุคออนโทโลยี (1990s-2000s)"] style era3 fill:#282828,stroke:#458588,color:#ebdbb2 F["OWL - Web Ontology Language
(2004)"] G["Protégé
(2000)"] end subgraph era4["ยุคปัจจุบัน (2010s-Present)"] style era4 fill:#282828,stroke:#b16286,color:#ebdbb2 H["Knowledge Graphs
(Google, 2012)"] I["Neuro-Symbolic AI"] end A --> B B --> C B --> D D --> E C --> F E --> F F --> G G --> H H --> I style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style B fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style C fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style D fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style E fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style F fill:#3c3836,stroke:#83a598,color:#ebdbb2 style G fill:#3c3836,stroke:#83a598,color:#ebdbb2 style H fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style I fill:#3c3836,stroke:#d3869b,color:#ebdbb2

1.3 ประเภทของการแทนความรู้

ประเภท ลักษณะ ตัวอย่าง ข้อดี ข้อเสีย
ตรรกศาสตร์ (Logic-based) ใช้กฎเชิงตรรกะ Propositional Logic, FOL แม่นยำ, พิสูจน์ได้ ไม่ยืดหยุ่น
กฎ (Rule-based) ใช้กฎ IF-THEN Production Rules เข้าใจง่าย ยากในการจัดการ
โครงสร้าง (Structured) ใช้โครงสร้างข้อมูล Frames, Scripts จัดระเบียบดี ซับซ้อน
เครือข่าย (Network-based) ใช้กราฟ Semantic Networks มองเห็นได้ ขาดความหมายทางรูปนัย
ความน่าจะเป็น (Probabilistic) ใช้ความน่าจะเป็น Bayesian Networks จัดการความไม่แน่นอน คำนวณซับซ้อน

2. ตรรกศาสตร์เชิงประพจน์ (Propositional Logic)

2.1 วากยสัมพันธ์และอรรถศาสตร์ (Syntax and Semantics)

2.1.1 วากยสัมพันธ์ (Syntax)

วากยสัมพันธ์ กำหนดกฎเกณฑ์ในการสร้างประโยคที่ถูกต้องตามหลักไวยากรณ์

องค์ประกอบพื้นฐานของตรรกศาสตร์เชิงประพจน์:

flowchart TD
    subgraph syntax["โครงสร้างวากยสัมพันธ์ (Syntax Structure)"]
        style syntax fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["สูตร (Formula)"]
        B["อะตอม (Atomic)"]
        C["ซับซ้อน (Complex)"]
        D["ตัวแปร P, Q, R..."]
        E["ค่าคงที่ ⊤, ⊥"]
        F["นิเสธ ¬α"]
        G["เชื่อม α ∧ β, α ∨ β"]
        H["เงื่อนไข α → β, α ↔ β"]
    end
    
    A --> B
    A --> C
    B --> D
    B --> E
    C --> F
    C --> G
    C --> H
    
    style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2
    style B fill:#3c3836,stroke:#b8bb26,color:#ebdbb2
    style C fill:#3c3836,stroke:#b8bb26,color:#ebdbb2
    style D fill:#3c3836,stroke:#83a598,color:#ebdbb2
    style E fill:#3c3836,stroke:#83a598,color:#ebdbb2
    style F fill:#3c3836,stroke:#d3869b,color:#ebdbb2
    style G fill:#3c3836,stroke:#d3869b,color:#ebdbb2
    style H fill:#3c3836,stroke:#d3869b,color:#ebdbb2

2.1.2 อรรถศาสตร์ (Semantics)

อรรถศาสตร์ กำหนดความหมายและค่าความจริงของประโยค

การตีความ (Interpretation) คือฟังก์ชันที่กำหนดค่าความจริง (True/False) ให้กับตัวแปรประพจน์แต่ละตัว

สำหรับประพจน์ P และ Q ที่มีการตีความ I:

2.2 ตัวเชื่อมทางตรรกะ (Logical Connectives)

ตัวเชื่อม สัญลักษณ์ ชื่อ ความหมาย
นิเสธ ¬ NOT ไม่ใช่
และ AND และ
หรือ OR หรือ
เงื่อนไข IMPLIES ถ้า...แล้ว
เงื่อนไขสองทาง IFF ก็ต่อเมื่อ

2.3 ตารางค่าความจริง (Truth Tables)

2.3.1 ตารางค่าความจริงพื้นฐาน

P Q ¬P P ∧ Q P ∨ Q P → Q P ↔ Q
T T F T T T T
T F F F T F F
F T T F T T F
F F T F F T T

2.3.2 การตรวจสอบความเป็นสัจนิรันดร์ (Tautology)

สัจนิรันดร์ (Tautology) คือสูตรที่เป็นจริงในทุกการตีความ

ตัวอย่าง: กฎการปฏิเสธซ้อน (Double Negation)

P ¬P ¬¬P P ↔ ¬¬P
T F T T
F T F T

เนื่องจาก P ↔ ¬¬P เป็นจริงในทุกกรณี จึงเป็นสัจนิรันดร์

"""
โปรแกรมสร้างตารางค่าความจริง (Truth Table Generator)
ใช้สำหรับตรวจสอบค่าความจริงของสูตรตรรกศาสตร์เชิงประพจน์
"""

from itertools import product
from typing import Callable, List, Tuple

def create_truth_table(
    variables: List[str], 
    formula: Callable[..., bool],
    formula_name: str = "Result"
) -> None:
    """
    สร้างและแสดงตารางค่าความจริง
    
    พารามิเตอร์:
        variables: รายชื่อตัวแปรประพจน์
        formula: ฟังก์ชันคำนวณค่าความจริงของสูตร
        formula_name: ชื่อของสูตรสำหรับแสดงในตาราง
    """
    # สร้างหัวตาราง
    header = variables + [formula_name]
    print(" | ".join(f"{h:^5}" for h in header))
    print("-" * (7 * len(header)))
    
    # สร้างทุกการตีความที่เป็นไปได้
    for values in product([True, False], repeat=len(variables)):
        # คำนวณค่าความจริงของสูตร
        result = formula(*values)
        
        # แปลงค่าความจริงเป็นสัญลักษณ์
        row = [("T" if v else "F") for v in values]
        row.append("T" if result else "F")
        
        print(" | ".join(f"{cell:^5}" for cell in row))

def NOT(p: bool) -> bool:
    """นิเสธ (Negation): ¬P"""
    return not p

def AND(p: bool, q: bool) -> bool:
    """และ (Conjunction): P ∧ Q"""
    return p and q

def OR(p: bool, q: bool) -> bool:
    """หรือ (Disjunction): P ∨ Q"""
    return p or q

def IMPLIES(p: bool, q: bool) -> bool:
    """เงื่อนไข (Implication): P → Q"""
    return (not p) or q

def IFF(p: bool, q: bool) -> bool:
    """เงื่อนไขสองทาง (Biconditional): P ↔ Q"""
    return p == q

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    print("=== ตัวเชื่อมพื้นฐาน ===\n")
    
    # ตาราง P → Q
    print("ตาราง: P → Q (Implication)")
    create_truth_table(['P', 'Q'], IMPLIES, 'P→Q')
    
    print("\n=== ตรวจสอบสัจนิรันดร์ ===\n")
    
    # กฎ Modus Ponens: ((P → Q) ∧ P) → Q
    def modus_ponens(p: bool, q: bool) -> bool:
        """กฎ Modus Ponens: ถ้า (P → Q) และ P แล้ว Q"""
        premise = AND(IMPLIES(p, q), p)
        return IMPLIES(premise, q)
    
    print("ตาราง: ((P → Q) ∧ P) → Q (Modus Ponens)")
    create_truth_table(['P', 'Q'], modus_ponens, 'MP')
    
    print("\n=== De Morgan's Laws ===\n")
    
    # ¬(P ∧ Q) ↔ (¬P ∨ ¬Q)
    def de_morgan_and(p: bool, q: bool) -> bool:
        """กฎของ De Morgan สำหรับ AND"""
        left = NOT(AND(p, q))
        right = OR(NOT(p), NOT(q))
        return IFF(left, right)
    
    print("ตาราง: ¬(P ∧ Q) ↔ (¬P ∨ ¬Q)")
    create_truth_table(['P', 'Q'], de_morgan_and, 'DeMorgan')

ผลลัพธ์:

=== ตัวเชื่อมพื้นฐาน ===

ตาราง: P → Q (Implication)
  P   |   Q   |  P→Q 
------------------------------------------
  T   |   T   |   T  
  T   |   F   |   F  
  F   |   T   |   T  
  F   |   F   |   T  

=== ตรวจสอบสัจนิรันดร์ ===

ตาราง: ((P → Q) ∧ P) → Q (Modus Ponens)
  P   |   Q   |  MP  
------------------------------------------
  T   |   T   |   T  
  T   |   F   |   T  
  F   |   T   |   T  
  F   |   F   |   T  

2.4 กฎการอนุมาน (Inference Rules)

2.4.1 กฎ Modus Ponens

กฎ Modus Ponens เป็นกฎการอนุมานพื้นฐานที่สำคัญที่สุด:

P Q , P Q

คำอธิบาย:

ตัวอย่าง:

2.4.2 กฎ Modus Tollens

P Q , ¬ Q ¬ P

คำอธิบาย:

2.4.3 กฎ Resolution

Resolution เป็นกฎการอนุมานที่ใช้กันอย่างแพร่หลายในระบบพิสูจน์ทฤษฎีบทอัตโนมัติ

P Q , ¬ P R Q R

คำอธิบาย:

flowchart TD
    subgraph rules["กฎการอนุมานหลัก (Main Inference Rules)"]
        style rules fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["กฎการอนุมาน
(Inference Rules)"] B["Modus Ponens
P→Q, P ⊢ Q"] C["Modus Tollens
P→Q, ¬Q ⊢ ¬P"] D["Resolution
P∨Q, ¬P∨R ⊢ Q∨R"] E["Hypothetical Syllogism
P→Q, Q→R ⊢ P→R"] F["Disjunctive Syllogism
P∨Q, ¬P ⊢ Q"] end A --> B A --> C A --> D A --> E A --> F style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style B fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style C fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style D fill:#3c3836,stroke:#83a598,color:#ebdbb2 style E fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style F fill:#3c3836,stroke:#d3869b,color:#ebdbb2
"""
โปรแกรมแสดงกฎการอนุมานทางตรรกศาสตร์ (Inference Rules Implementation)
"""

from dataclasses import dataclass
from typing import Optional, Set, FrozenSet, List

@dataclass(frozen=True)
class Clause:
    """
    คลาสแทนอนุประโยค (Clause) ในรูปแบบ CNF
    อนุประโยคคือการเชื่อม (disjunction) ของ literals
    """
    literals: FrozenSet[str]
    
    def __str__(self) -> str:
        if not self.literals:
            return "□ (Empty Clause)"
        return " ∨ ".join(sorted(self.literals))
    
    @classmethod
    def from_string(cls, s: str) -> 'Clause':
        """สร้าง Clause จากสตริง เช่น 'P, ¬Q, R'"""
        literals = frozenset(l.strip() for l in s.split(',') if l.strip())
        return cls(literals)

def is_negation(lit1: str, lit2: str) -> bool:
    """ตรวจสอบว่าสอง literals เป็นนิเสธของกัน"""
    if lit1.startswith('¬'):
        return lit1[1:] == lit2
    elif lit2.startswith('¬'):
        return lit2[1:] == lit1
    return False

def resolve(clause1: Clause, clause2: Clause) -> Optional[Clause]:
    """
    ใช้กฎ Resolution กับสองอนุประโยค
    
    พารามิเตอร์:
        clause1: อนุประโยคแรก
        clause2: อนุประโยคที่สอง
    
    คืนค่า:
        อนุประโยคผลลัพธ์ (Resolvent) หรือ None ถ้าไม่สามารถ resolve ได้
    """
    for lit1 in clause1.literals:
        for lit2 in clause2.literals:
            if is_negation(lit1, lit2):
                # ลบ complementary literals ออก
                new_literals = (clause1.literals | clause2.literals) - {lit1, lit2}
                return Clause(new_literals)
    return None

def resolution_proof(
    clauses: List[Clause], 
    goal_negation: Clause,
    verbose: bool = True
) -> bool:
    """
    พิสูจน์โดยใช้วิธี Resolution Refutation
    
    พารามิเตอร์:
        clauses: ฐานความรู้ในรูปอนุประโยค
        goal_negation: นิเสธของเป้าหมายที่ต้องการพิสูจน์
        verbose: แสดงขั้นตอนการพิสูจน์
    
    คืนค่า:
        True ถ้าพิสูจน์ได้ (พบ empty clause)
    """
    all_clauses = set(clauses) | {goal_negation}
    
    if verbose:
        print("=== เริ่มต้น Resolution Proof ===")
        print(f"ฐานความรู้: {[str(c) for c in clauses]}")
        print(f"นิเสธเป้าหมาย: {goal_negation}")
        print()
    
    step = 0
    while True:
        new_clauses = set()
        clause_list = list(all_clauses)
        
        # ลองจับคู่ทุกอนุประโยค
        for i, c1 in enumerate(clause_list):
            for c2 in clause_list[i+1:]:
                resolvent = resolve(c1, c2)
                
                if resolvent is not None:
                    step += 1
                    
                    if verbose:
                        print(f"ขั้นที่ {step}: Resolve({c1}, {c2})")
                        print(f"         ผลลัพธ์: {resolvent}")
                    
                    # พบ empty clause = พิสูจน์สำเร็จ
                    if not resolvent.literals:
                        if verbose:
                            print("\n✓ พบ Empty Clause - พิสูจน์สำเร็จ!")
                        return True
                    
                    new_clauses.add(resolvent)
        
        # ถ้าไม่มีอนุประโยคใหม่ = ไม่สามารถพิสูจน์ได้
        if new_clauses.issubset(all_clauses):
            if verbose:
                print("\n✗ ไม่พบอนุประโยคใหม่ - ไม่สามารถพิสูจน์ได้")
            return False
        
        all_clauses.update(new_clauses)

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    print("=== ตัวอย่าง 1: Modus Ponens ด้วย Resolution ===\n")
    
    # พิสูจน์: จาก (P → Q) และ P, สรุป Q
    # P → Q เทียบเท่า ¬P ∨ Q
    # ฐานความรู้: {¬P ∨ Q, P}
    # ต้องการพิสูจน์: Q
    # นิเสธของเป้าหมาย: ¬Q
    
    kb = [
        Clause.from_string("¬P, Q"),  # P → Q
        Clause.from_string("P")        # P
    ]
    goal_neg = Clause.from_string("¬Q")  # ¬Q (นิเสธของสิ่งที่ต้องการพิสูจน์)
    
    resolution_proof(kb, goal_neg)
    
    print("\n" + "="*50 + "\n")
    print("=== ตัวอย่าง 2: Transitive Reasoning ===\n")
    
    # พิสูจน์: จาก (P → Q), (Q → R), และ P, สรุป R
    kb2 = [
        Clause.from_string("¬P, Q"),  # P → Q
        Clause.from_string("¬Q, R"),  # Q → R
        Clause.from_string("P")        # P
    ]
    goal_neg2 = Clause.from_string("¬R")  # ¬R
    
    resolution_proof(kb2, goal_neg2)

ผลลัพธ์:

=== ตัวอย่าง 1: Modus Ponens ด้วย Resolution ===

=== เริ่มต้น Resolution Proof ===
ฐานความรู้: ['Q ∨ ¬P', 'P']
นิเสธเป้าหมาย: ¬Q

ขั้นที่ 1: Resolve(Q ∨ ¬P, P)
         ผลลัพธ์: Q
ขั้นที่ 2: Resolve(Q, ¬Q)
         ผลลัพธ์: □ (Empty Clause)

✓ พบ Empty Clause - พิสูจน์สำเร็จ!

2.5 รูปแบบบัญญัติ (Normal Forms)

2.5.1 รูปแบบบัญญัติเชื่อม (Conjunctive Normal Form - CNF)

CNF คือการเชื่อม (conjunction) ของอนุประโยค โดยแต่ละอนุประโยคเป็นการแยก (disjunction) ของ literals

( l11 l12 ) ( l21 l22 )

ตัวอย่าง: (P ∨ Q) ∧ (¬P ∨ R) ∧ (¬Q ∨ ¬R)

2.5.2 รูปแบบบัญญัติแยก (Disjunctive Normal Form - DNF)

DNF คือการแยก (disjunction) ของ conjunctions

( l11 l12 ) ( l21 l22 )

ตัวอย่าง: (P ∧ Q) ∨ (¬P ∧ R) ∨ (Q ∧ ¬R)

"""
โปรแกรมแปลงสูตรเป็นรูปแบบบัญญัติ (Normal Form Converter)
"""

from typing import List, Set, Tuple
from itertools import product

class PropositionalFormula:
    """
    คลาสสำหรับจัดการสูตรตรรกศาสตร์เชิงประพจน์
    """
    
    @staticmethod
    def eliminate_implication(formula: str) -> str:
        """
        กำจัดเครื่องหมาย → โดยใช้กฎ: P → Q ≡ ¬P ∨ Q
        """
        # สำหรับตัวอย่างง่าย ๆ
        return formula.replace("→", "∨¬")
    
    @staticmethod
    def apply_de_morgan(formula: str) -> str:
        """
        ใช้กฎของ De Morgan:
        - ¬(P ∧ Q) ≡ ¬P ∨ ¬Q
        - ¬(P ∨ Q) ≡ ¬P ∧ ¬Q
        """
        # การใช้งานจริงต้องมี parser ที่ซับซ้อนกว่านี้
        pass
    
    @staticmethod
    def to_cnf_from_truth_table(
        variables: List[str],
        formula_func
    ) -> List[Set[str]]:
        """
        แปลงสูตรเป็น CNF โดยใช้ตารางค่าความจริง
        
        พารามิเตอร์:
            variables: รายชื่อตัวแปร
            formula_func: ฟังก์ชันคำนวณค่าความจริง
        
        คืนค่า:
            รายการของอนุประโยค (แต่ละอนุประโยคเป็น set ของ literals)
        """
        clauses = []
        
        for values in product([True, False], repeat=len(variables)):
            if not formula_func(*values):
                # สำหรับแถวที่เป็น False สร้างอนุประโยค
                clause = set()
                for var, val in zip(variables, values):
                    if val:
                        clause.add(f{var}")  # ถ้าเป็น True ใส่นิเสธ
                    else:
                        clause.add(var)         # ถ้าเป็น False ใส่ตัวแปรปกติ
                clauses.append(clause)
        
        return clauses
    
    @staticmethod
    def to_dnf_from_truth_table(
        variables: List[str],
        formula_func
    ) -> List[Set[str]]:
        """
        แปลงสูตรเป็น DNF โดยใช้ตารางค่าความจริง
        
        คืนค่า:
            รายการของ conjunctions (แต่ละ conjunction เป็น set ของ literals)
        """
        terms = []
        
        for values in product([True, False], repeat=len(variables)):
            if formula_func(*values):
                # สำหรับแถวที่เป็น True สร้าง minterm
                term = set()
                for var, val in zip(variables, values):
                    if val:
                        term.add(var)           # ถ้าเป็น True ใส่ตัวแปร
                    else:
                        term.add(f{var}")     # ถ้าเป็น False ใส่นิเสธ
                terms.append(term)
        
        return terms

def format_cnf(clauses: List[Set[str]]) -> str:
    """จัดรูปแบบ CNF เป็นสตริง"""
    formatted_clauses = []
    for clause in clauses:
        formatted_clauses.append("(" + " ∨ ".join(sorted(clause)) + ")")
    return " ∧ ".join(formatted_clauses)

def format_dnf(terms: List[Set[str]]) -> str:
    """จัดรูปแบบ DNF เป็นสตริง"""
    formatted_terms = []
    for term in terms:
        formatted_terms.append("(" + " ∧ ".join(sorted(term)) + ")")
    return " ∨ ".join(formatted_terms)

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # กำหนดสูตร: (P → Q) ∧ P
    # ซึ่งเทียบเท่า (¬P ∨ Q) ∧ P
    
    def formula(p: bool, q: bool) -> bool:
        """สูตร: (P → Q) ∧ P"""
        return ((not p) or q) and p
    
    print("สูตร: (P → Q) ∧ P\n")
    
    pf = PropositionalFormula()
    
    # แปลงเป็น CNF
    cnf = pf.to_cnf_from_truth_table(['P', 'Q'], formula)
    print(f"CNF: {format_cnf(cnf)}")
    
    # แปลงเป็น DNF
    dnf = pf.to_dnf_from_truth_table(['P', 'Q'], formula)
    print(f"DNF: {format_dnf(dnf)}")

3. ตรรกศาสตร์เชิงภาคแสดง (Predicate Logic)

3.1 บทนำสู่ตรรกศาสตร์อันดับหนึ่ง (First-Order Logic)

ตรรกศาสตร์อันดับหนึ่ง (First-Order Logic - FOL) หรือเรียกอีกอย่างว่า ตรรกศาสตร์เชิงภาคแสดง (Predicate Logic) ขยายขอบเขตจากตรรกศาสตร์เชิงประพจน์โดยเพิ่มความสามารถในการ:

3.2 องค์ประกอบของ FOL

flowchart TD
    subgraph fol["องค์ประกอบของ First-Order Logic"]
        style fol fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["First-Order Logic"]
        
        B["ค่าคงที่
(Constants)"] C["ตัวแปร
(Variables)"] D["ภาคแสดง
(Predicates)"] E["ฟังก์ชัน
(Functions)"] F["ตัวเชื่อม
(Connectives)"] G["ตัวบ่งปริมาณ
(Quantifiers)"] B1["John, Bangkok, 5"] C1["x, y, z"] D1["Human(x), Loves(x,y)"] E1["father(x), plus(x,y)"] F1["∧, ∨, ¬, →, ↔"] G1["∀ (For all)
∃ (Exists)"] end A --> B A --> C A --> D A --> E A --> F A --> G B --> B1 C --> C1 D --> D1 E --> E1 F --> F1 G --> G1 style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style B fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style C fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style D fill:#3c3836,stroke:#83a598,color:#ebdbb2 style E fill:#3c3836,stroke:#83a598,color:#ebdbb2 style F fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style G fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style B1 fill:#504945,stroke:#b8bb26,color:#ebdbb2 style C1 fill:#504945,stroke:#b8bb26,color:#ebdbb2 style D1 fill:#504945,stroke:#83a598,color:#ebdbb2 style E1 fill:#504945,stroke:#83a598,color:#ebdbb2 style F1 fill:#504945,stroke:#d3869b,color:#ebdbb2 style G1 fill:#504945,stroke:#d3869b,color:#ebdbb2

3.3 ตัวบ่งปริมาณ (Quantifiers)

3.3.1 ตัวบ่งปริมาณสากล (Universal Quantifier - ∀)

ตัวบ่งปริมาณสากล (∀) หมายถึง "สำหรับทุก" หรือ "ทั้งหมด"

x . P ( x )

คำอธิบาย: สำหรับทุกค่า x, P(x) เป็นจริง

ตัวอย่าง:

3.3.2 ตัวบ่งปริมาณมีอยู่ (Existential Quantifier - ∃)

ตัวบ่งปริมาณมีอยู่ (∃) หมายถึง "มีอย่างน้อยหนึ่ง" หรือ "มีอยู่"

x . P ( x )

คำอธิบาย: มีอย่างน้อยหนึ่งค่า x ที่ P(x) เป็นจริง

ตัวอย่าง:

3.3.3 ความสัมพันธ์ระหว่างตัวบ่งปริมาณ

กฎ สูตร คำอธิบาย
นิเสธของ ∀ ¬∀x.P(x) ≡ ∃x.¬P(x) "ไม่ใช่ทุก x" = "มี x ที่ไม่"
นิเสธของ ∃ ¬∃x.P(x) ≡ ∀x.¬P(x) "ไม่มี x ที่" = "ทุก x ไม่"
สลับ ∀∀ ∀x.∀y.P(x,y) ≡ ∀y.∀x.P(x,y) สามารถสลับลำดับได้
สลับ ∃∃ ∃x.∃y.P(x,y) ≡ ∃y.∃x.P(x,y) สามารถสลับลำดับได้
ไม่สลับ ∀∃ ∀x.∃y.P(x,y) ≢ ∃y.∀x.P(x,y) ไม่สามารถสลับลำดับได้

3.4 การรวมเป็นหนึ่ง (Unification)

การรวมเป็นหนึ่ง (Unification) เป็นกระบวนการหาการแทนที่ (Substitution) ที่ทำให้สองนิพจน์เท่ากัน

3.4.1 นิยาม

การแทนที่ (Substitution) θ = {x₁/t₁, x₂/t₂, ...} คือการแทนที่ตัวแปร xᵢ ด้วยเทอม tᵢ

ตัวรวม (Unifier) ของสองนิพจน์ E₁ และ E₂ คือการแทนที่ θ ที่ทำให้ E₁θ = E₂θ

ตัวรวมทั่วไปที่สุด (Most General Unifier - MGU) คือตัวรวมที่มีการแทนที่น้อยที่สุด

3.4.2 อัลกอริทึม Unification

"""
โปรแกรม Unification Algorithm
ใช้สำหรับหาตัวรวมทั่วไปที่สุด (MGU) ของสองนิพจน์
"""

from dataclasses import dataclass
from typing import Dict, List, Optional, Union

@dataclass
class Variable:
    """ตัวแปร เช่น x, y, z"""
    name: str
    
    def __str__(self) -> str:
        return self.name
    
    def __hash__(self) -> int:
        return hash(self.name)
    
    def __eq__(self, other) -> bool:
        if isinstance(other, Variable):
            return self.name == other.name
        return False

@dataclass
class Constant:
    """ค่าคงที่ เช่น john, bangkok"""
    name: str
    
    def __str__(self) -> str:
        return self.name
    
    def __hash__(self) -> int:
        return hash(self.name)
    
    def __eq__(self, other) -> bool:
        if isinstance(other, Constant):
            return self.name == other.name
        return False

@dataclass
class Predicate:
    """ภาคแสดง เช่น Loves(john, mary), Father(x, y)"""
    name: str
    args: List[Union['Predicate', Variable, Constant]]
    
    def __str__(self) -> str:
        args_str = ", ".join(str(arg) for arg in self.args)
        return f"{self.name}({args_str})"
    
    def __hash__(self) -> int:
        return hash((self.name, tuple(self.args)))
    
    def __eq__(self, other) -> bool:
        if isinstance(other, Predicate):
            return self.name == other.name and self.args == other.args
        return False

# กำหนด type สำหรับ Term
Term = Union[Predicate, Variable, Constant]
Substitution = Dict[Variable, Term]

def occurs_check(var: Variable, term: Term, subst: Substitution) -> bool:
    """
    ตรวจสอบว่าตัวแปรปรากฏในเทอมหรือไม่ (Occurs Check)
    ป้องกันการสร้าง infinite terms
    
    พารามิเตอร์:
        var: ตัวแปรที่ต้องการตรวจสอบ
        term: เทอมที่ต้องการค้นหา
        subst: การแทนที่ปัจจุบัน
    
    คืนค่า:
        True ถ้าตัวแปรปรากฏในเทอม
    """
    if isinstance(term, Variable):
        if term == var:
            return True
        if term in subst:
            return occurs_check(var, subst[term], subst)
        return False
    elif isinstance(term, Constant):
        return False
    elif isinstance(term, Predicate):
        return any(occurs_check(var, arg, subst) for arg in term.args)
    return False

def apply_substitution(term: Term, subst: Substitution) -> Term:
    """
    ใช้การแทนที่กับเทอม
    
    พารามิเตอร์:
        term: เทอมที่ต้องการแทนที่
        subst: การแทนที่
    
    คืนค่า:
        เทอมหลังจากใช้การแทนที่
    """
    if isinstance(term, Variable):
        if term in subst:
            return apply_substitution(subst[term], subst)
        return term
    elif isinstance(term, Constant):
        return term
    elif isinstance(term, Predicate):
        new_args = [apply_substitution(arg, subst) for arg in term.args]
        return Predicate(term.name, new_args)
    return term

def unify(x: Term, y: Term, subst: Optional[Substitution] = None) -> Optional[Substitution]:
    """
    หาตัวรวมทั่วไปที่สุด (MGU) ของสองเทอม
    
    พารามิเตอร์:
        x: เทอมแรก
        y: เทอมที่สอง
        subst: การแทนที่เริ่มต้น (ถ้ามี)
    
    คืนค่า:
        MGU หรือ None ถ้าไม่สามารถรวมได้
    """
    if subst is None:
        subst = {}
    
    # ใช้การแทนที่ที่มีอยู่กับทั้งสองเทอม
    x = apply_substitution(x, subst)
    y = apply_substitution(y, subst)
    
    # กรณีเทอมเหมือนกัน
    if x == y:
        return subst
    
    # กรณี x เป็นตัวแปร
    if isinstance(x, Variable):
        if occurs_check(x, y, subst):
            return None  # Occurs check failed
        subst[x] = y
        return subst
    
    # กรณี y เป็นตัวแปร
    if isinstance(y, Variable):
        if occurs_check(y, x, subst):
            return None  # Occurs check failed
        subst[y] = x
        return subst
    
    # กรณีทั้งคู่เป็น Predicate
    if isinstance(x, Predicate) and isinstance(y, Predicate):
        if x.name != y.name or len(x.args) != len(y.args):
            return None  # ไม่สามารถรวมได้
        
        for arg_x, arg_y in zip(x.args, y.args):
            subst = unify(arg_x, arg_y, subst)
            if subst is None:
                return None
        
        return subst
    
    return None  # ไม่สามารถรวมได้

def format_substitution(subst: Substitution) -> str:
    """จัดรูปแบบการแทนที่เป็นสตริง"""
    if not subst:
        return "{}"
    items = [f"{var}/{term}" for var, term in subst.items()]
    return "{" + ", ".join(items) + "}"

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    print("=== ตัวอย่าง Unification ===\n")
    
    # ตัวอย่าง 1: Knows(John, x) และ Knows(John, Mary)
    x = Variable("x")
    john = Constant("John")
    mary = Constant("Mary")
    
    term1 = Predicate("Knows", [john, x])
    term2 = Predicate("Knows", [john, mary])
    
    print(f"เทอม 1: {term1}")
    print(f"เทอม 2: {term2}")
    
    result = unify(term1, term2)
    if result:
        print(f"MGU: {format_substitution(result)}")
        print(f"ผลลัพธ์: {apply_substitution(term1, result)}")
    else:
        print("ไม่สามารถรวมได้")
    
    print("\n" + "-"*50 + "\n")
    
    # ตัวอย่าง 2: Loves(x, y) และ Loves(John, Mary)
    y = Variable("y")
    
    term3 = Predicate("Loves", [x, y])
    term4 = Predicate("Loves", [john, mary])
    
    print(f"เทอม 1: {term3}")
    print(f"เทอม 2: {term4}")
    
    result = unify(term3, term4)
    if result:
        print(f"MGU: {format_substitution(result)}")
    else:
        print("ไม่สามารถรวมได้")
    
    print("\n" + "-"*50 + "\n")
    
    # ตัวอย่าง 3: Father(x, y) และ Father(John, x) - occurs check
    term5 = Predicate("Father", [x, y])
    term6 = Predicate("Father", [john, x])
    
    print(f"เทอม 1: {term5}")
    print(f"เทอม 2: {term6}")
    
    result = unify(term5, term6)
    if result:
        print(f"MGU: {format_substitution(result)}")
    else:
        print("ไม่สามารถรวมได้")

ผลลัพธ์:

=== ตัวอย่าง Unification ===

เทอม 1: Knows(John, x)
เทอม 2: Knows(John, Mary)
MGU: {x/Mary}
ผลลัพธ์: Knows(John, Mary)

--------------------------------------------------

เทอม 1: Loves(x, y)
เทอม 2: Loves(John, Mary)
MGU: {x/John, y/Mary}

--------------------------------------------------

เทอม 1: Father(x, y)
เทอม 2: Father(John, x)
MGU: {x/John, y/John}

3.5 การอนุมานแบบโซ่ (Chaining)

3.5.1 การอนุมานแบบโซ่ไปข้างหน้า (Forward Chaining)

การอนุมานแบบโซ่ไปข้างหน้า เริ่มจากข้อเท็จจริงที่มีอยู่ แล้วใช้กฎเพื่อสรุปข้อเท็จจริงใหม่

flowchart LR
    subgraph forward["Forward Chaining"]
        style forward fill:#282828,stroke:#98971a,color:#ebdbb2
        
        A["ข้อเท็จจริง
(Facts)"] B["กฎ
(Rules)"] C["จับคู่
(Match)"] D["ข้อเท็จจริงใหม่
(New Facts)"] E["เป้าหมาย?
(Goal?)"] F["สำเร็จ"] G["วนซ้ำ"] end A --> C B --> C C --> D D --> E E -->|ใช่| F E -->|ไม่| G G --> C style A fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style B fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style C fill:#3c3836,stroke:#83a598,color:#ebdbb2 style D fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style E fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style F fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style G fill:#3c3836,stroke:#fabd2f,color:#ebdbb2

ลักษณะสำคัญ:

3.5.2 การอนุมานแบบโซ่ย้อนกลับ (Backward Chaining)

การอนุมานแบบโซ่ย้อนกลับ เริ่มจากเป้าหมาย แล้วค้นหากฎที่สามารถพิสูจน์เป้าหมายได้

flowchart RL
    subgraph backward["Backward Chaining"]
        style backward fill:#282828,stroke:#458588,color:#ebdbb2
        
        A["เป้าหมาย
(Goal)"] B["หากฎ
(Find Rule)"] C["เป้าหมายย่อย
(Subgoals)"] D["ข้อเท็จจริง?
(Facts?)"] E["สำเร็จ"] F["วนซ้ำ"] G["ล้มเหลว"] end A --> B B --> C C --> D D -->|ใช่| E D -->|ไม่ใช่| F F --> B B -->|ไม่มีกฎ| G style A fill:#3c3836,stroke:#83a598,color:#ebdbb2 style B fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style C fill:#3c3836,stroke:#83a598,color:#ebdbb2 style D fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style E fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style F fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style G fill:#3c3836,stroke:#fb4934,color:#ebdbb2

ลักษณะสำคัญ:

3.5.3 เปรียบเทียบ Forward และ Backward Chaining

คุณลักษณะ Forward Chaining Backward Chaining
การเริ่มต้น จากข้อเท็จจริง จากเป้าหมาย
ทิศทาง ข้อมูล → เป้าหมาย เป้าหมาย → ข้อมูล
การค้นหา กว้าง (อาจไม่จำเป็น) เฉพาะเจาะจง
การใช้งาน Monitoring, Planning Diagnosis, Q&A
ตัวอย่างระบบ CLIPS, Drools Prolog
"""
โปรแกรมแสดง Forward และ Backward Chaining
"""

from typing import Dict, List, Set, Tuple, Optional
from dataclasses import dataclass

@dataclass
class Rule:
    """
    กฎในรูปแบบ IF conditions THEN conclusion
    """
    name: str
    conditions: List[str]
    conclusion: str
    
    def __str__(self) -> str:
        cond_str = " ∧ ".join(self.conditions)
        return f"{self.name}: {cond_str}{self.conclusion}"

class KnowledgeBase:
    """
    ฐานความรู้สำหรับการอนุมาน
    """
    
    def __init__(self):
        self.facts: Set[str] = set()
        self.rules: List[Rule] = []
    
    def add_fact(self, fact: str) -> None:
        """เพิ่มข้อเท็จจริง"""
        self.facts.add(fact)
    
    def add_rule(self, rule: Rule) -> None:
        """เพิ่มกฎ"""
        self.rules.append(rule)
    
    def forward_chain(self, goal: str, verbose: bool = True) -> bool:
        """
        การอนุมานแบบโซ่ไปข้างหน้า (Forward Chaining)
        
        พารามิเตอร์:
            goal: เป้าหมายที่ต้องการพิสูจน์
            verbose: แสดงขั้นตอนการอนุมาน
        
        คืนค่า:
            True ถ้าสามารถพิสูจน์เป้าหมายได้
        """
        if verbose:
            print("=== Forward Chaining ===")
            print(f"ข้อเท็จจริงเริ่มต้น: {self.facts}")
            print(f"เป้าหมาย: {goal}\n")
        
        inferred = set(self.facts)
        iteration = 0
        
        while True:
            iteration += 1
            new_facts = set()
            
            if verbose:
                print(f"--- รอบที่ {iteration} ---")
            
            for rule in self.rules:
                # ตรวจสอบว่าเงื่อนไขทั้งหมดเป็นจริงหรือไม่
                if all(cond in inferred for cond in rule.conditions):
                    if rule.conclusion not in inferred:
                        new_facts.add(rule.conclusion)
                        if verbose:
                            print(f"  ใช้กฎ {rule.name}: {rule.conclusion}")
            
            if not new_facts:
                if verbose:
                    print("  ไม่มีข้อเท็จจริงใหม่")
                break
            
            inferred.update(new_facts)
            
            if goal in inferred:
                if verbose:
                    print(f"\n✓ พบเป้าหมาย '{goal}'!")
                return True
        
        if verbose:
            print(f"\n✗ ไม่สามารถพิสูจน์เป้าหมาย '{goal}'")
        return False
    
    def backward_chain(
        self, 
        goal: str, 
        visited: Optional[Set[str]] = None,
        depth: int = 0,
        verbose: bool = True
    ) -> bool:
        """
        การอนุมานแบบโซ่ย้อนกลับ (Backward Chaining)
        
        พารามิเตอร์:
            goal: เป้าหมายที่ต้องการพิสูจน์
            visited: ชุดของเป้าหมายที่เยี่ยมชมแล้ว (ป้องกัน infinite loop)
            depth: ความลึกของการค้นหา
            verbose: แสดงขั้นตอนการอนุมาน
        
        คืนค่า:
            True ถ้าสามารถพิสูจน์เป้าหมายได้
        """
        if visited is None:
            visited = set()
            if verbose:
                print("=== Backward Chaining ===")
                print(f"ข้อเท็จจริง: {self.facts}")
                print(f"เป้าหมาย: {goal}\n")
        
        indent = "  " * depth
        
        if verbose:
            print(f"{indent}พิสูจน์: {goal}")
        
        # ตรวจสอบว่าเป็นข้อเท็จจริงหรือไม่
        if goal in self.facts:
            if verbose:
                print(f"{indent}✓ เป็นข้อเท็จจริง")
            return True
        
        # ป้องกัน infinite loop
        if goal in visited:
            if verbose:
                print(f"{indent}✗ วนซ้ำ - หยุด")
            return False
        
        visited.add(goal)
        
        # หากฎที่สามารถพิสูจน์เป้าหมายได้
        for rule in self.rules:
            if rule.conclusion == goal:
                if verbose:
                    print(f"{indent}ลองกฎ {rule.name}")
                
                # พิสูจน์เงื่อนไขทั้งหมด
                all_proved = True
                for cond in rule.conditions:
                    if not self.backward_chain(cond, visited, depth + 1, verbose):
                        all_proved = False
                        break
                
                if all_proved:
                    if verbose:
                        print(f"{indent}✓ พิสูจน์ {goal} สำเร็จด้วยกฎ {rule.name}")
                    return True
        
        if verbose:
            print(f"{indent}✗ ไม่สามารถพิสูจน์ {goal}")
        return False

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # สร้างฐานความรู้
    kb = KnowledgeBase()
    
    # เพิ่มข้อเท็จจริง
    kb.add_fact("Human(Socrates)")
    
    # เพิ่มกฎ
    kb.add_rule(Rule("R1", ["Human(x)"], "Mortal(x)"))
    
    # ทดสอบ Forward Chaining
    print("="*60)
    # สำหรับตัวอย่างง่าย ๆ ใช้ string matching
    kb2 = KnowledgeBase()
    kb2.add_fact("A")
    kb2.add_fact("B")
    kb2.add_rule(Rule("R1", ["A", "B"], "C"))
    kb2.add_rule(Rule("R2", ["C"], "D"))
    kb2.add_rule(Rule("R3", ["D", "E"], "F"))
    
    kb2.forward_chain("D")
    
    print("\n" + "="*60 + "\n")
    
    # ทดสอบ Backward Chaining
    kb3 = KnowledgeBase()
    kb3.add_fact("A")
    kb3.add_fact("B")
    kb3.add_rule(Rule("R1", ["A", "B"], "C"))
    kb3.add_rule(Rule("R2", ["C"], "D"))
    
    kb3.backward_chain("D")

ผลลัพธ์:

============================================================
=== Forward Chaining ===
ข้อเท็จจริงเริ่มต้น: {'A', 'B'}
เป้าหมาย: D

--- รอบที่ 1 ---
  ใช้กฎ R1: C
--- รอบที่ 2 ---
  ใช้กฎ R2: D

✓ พบเป้าหมาย 'D'!

============================================================

=== Backward Chaining ===
ข้อเท็จจริง: {'A', 'B'}
เป้าหมาย: D

พิสูจน์: D
ลองกฎ R2
  พิสูจน์: C
  ลองกฎ R1
    พิสูจน์: A
    ✓ เป็นข้อเท็จจริง
    พิสูจน์: B
    ✓ เป็นข้อเท็จจริง
  ✓ พิสูจน์ C สำเร็จด้วยกฎ R1
✓ พิสูจน์ D สำเร็จด้วยกฎ R2

4. ตัวแทนฐานความรู้ (Knowledge-Based Agents)

4.1 โครงสร้างของตัวแทนฐานความรู้

ตัวแทนฐานความรู้ (Knowledge-Based Agent) เป็นตัวแทนที่ใช้ฐานความรู้ภายในเพื่อตัดสินใจและดำเนินการ

flowchart TB
    subgraph agent["Knowledge-Based Agent"]
        style agent fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["สิ่งแวดล้อม
(Environment)"] B["เซนเซอร์
(Sensors)"] C["ฐานความรู้
(Knowledge Base)"] D["กลไกอนุมาน
(Inference Engine)"] E["แอคชูเอเตอร์
(Actuators)"] F["TELL
(เพิ่มความรู้)"] G["ASK
(สอบถาม)"] end A --> B B --> F F --> C C --> D D --> G G --> E E --> A style A fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style B fill:#3c3836,stroke:#83a598,color:#ebdbb2 style C fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style D fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style E fill:#3c3836,stroke:#83a598,color:#ebdbb2 style F fill:#504945,stroke:#d3869b,color:#ebdbb2 style G fill:#504945,stroke:#d3869b,color:#ebdbb2

4.2 ส่วนประกอบหลัก

ส่วนประกอบ หน้าที่ คำอธิบาย
Knowledge Base (KB) เก็บความรู้ ชุดของประโยคในภาษาแทนความรู้
Inference Engine อนุมาน ใช้กฎการอนุมานเพื่อหาข้อสรุปใหม่
TELL เพิ่มความรู้ เพิ่มประโยคใหม่เข้าไปใน KB
ASK สอบถาม สอบถามว่าประโยคใดเป็นจริงหรือไม่

4.3 อัลกอริทึมพื้นฐาน

"""
โปรแกรม Knowledge-Based Agent
"""

from abc import ABC, abstractmethod
from typing import Any, List, Optional, Set
from dataclasses import dataclass, field

@dataclass
class KnowledgeBasedAgent:
    """
    ตัวแทนฐานความรู้ (Knowledge-Based Agent)
    """
    
    kb: Set[str] = field(default_factory=set)
    rules: List[tuple] = field(default_factory=list)
    time: int = 0
    
    def tell(self, sentence: str) -> None:
        """
        เพิ่มความรู้ใหม่เข้าสู่ฐานความรู้
        
        พารามิเตอร์:
            sentence: ประโยคที่ต้องการเพิ่ม
        """
        self.kb.add(sentence)
        print(f"TELL: เพิ่ม '{sentence}' เข้าสู่ KB")
    
    def ask(self, query: str) -> bool:
        """
        สอบถามว่าประโยคเป็นจริงหรือไม่
        
        พารามิเตอร์:
            query: ประโยคที่ต้องการสอบถาม
        
        คืนค่า:
            True ถ้าประโยคเป็นจริงตาม KB
        """
        # ตรวจสอบโดยตรง
        if query in self.kb:
            return True
        
        # ลองอนุมานด้วยกฎ
        for conditions, conclusion in self.rules:
            if conclusion == query:
                if all(self.ask(c) for c in conditions):
                    return True
        
        return False
    
    def add_rule(self, conditions: List[str], conclusion: str) -> None:
        """
        เพิ่มกฎเข้าสู่ฐานความรู้
        
        พารามิเตอร์:
            conditions: รายการเงื่อนไข
            conclusion: ข้อสรุป
        """
        self.rules.append((conditions, conclusion))
        cond_str = " ∧ ".join(conditions)
        print(f"ADD RULE: {cond_str}{conclusion}")
    
    def perceive(self, percept: str) -> None:
        """
        รับข้อมูลจากสิ่งแวดล้อม
        
        พารามิเตอร์:
            percept: ข้อมูลที่รับรู้
        """
        # แปลงข้อมูลที่รับรู้เป็นประโยค
        sentence = f"{percept}(t={self.time})"
        self.tell(sentence)
        self.time += 1
    
    def decide_action(self) -> Optional[str]:
        """
        ตัดสินใจเลือกการกระทำ
        
        คืนค่า:
            การกระทำที่ตัดสินใจ
        """
        # ตัวอย่างง่าย ๆ: ตรวจสอบเงื่อนไขและเลือกการกระทำ
        if self.ask("danger"):
            return "escape"
        elif self.ask("hungry"):
            return "eat"
        elif self.ask("tired"):
            return "rest"
        return "explore"
    
    def run_cycle(self, percept: str) -> str:
        """
        รันวงจรการทำงานหนึ่งรอบ
        
        พารามิเตอร์:
            percept: ข้อมูลที่รับรู้
        
        คืนค่า:
            การกระทำที่เลือก
        """
        print(f"\n=== Cycle {self.time} ===")
        
        # 1. รับรู้
        self.perceive(percept)
        
        # 2. ตัดสินใจ
        action = self.decide_action()
        print(f"ACTION: {action}")
        
        return action

# ตัวอย่างการใช้งาน: Wumpus World Agent
class WumpusAgent(KnowledgeBasedAgent):
    """
    ตัวแทนสำหรับ Wumpus World
    """
    
    def __init__(self):
        super().__init__()
        
        # เพิ่มกฎพื้นฐาน
        self.add_rule(["stench", "~wumpus_known"], "wumpus_nearby")
        self.add_rule(["breeze", "~pit_known"], "pit_nearby")
        self.add_rule(["glitter"], "gold_here")
        
        # เพิ่มกฎการตัดสินใจ
        self.add_rule(["wumpus_nearby"], "danger")
        self.add_rule(["pit_nearby"], "danger")
    
    def decide_action(self) -> str:
        """ตัดสินใจในโลก Wumpus"""
        if self.ask("gold_here"):
            return "grab"
        elif self.ask("danger"):
            return "retreat"
        elif self.ask("safe"):
            return "move_forward"
        return "turn_right"

# ทดสอบ
if __name__ == "__main__":
    print("=== Knowledge-Based Agent Demo ===\n")
    
    agent = WumpusAgent()
    
    # จำลองการรับรู้
    agent.run_cycle("stench")
    agent.run_cycle("breeze")
    agent.run_cycle("glitter")

5. เครือข่ายความหมายและกรอบ (Semantic Networks & Frames)

5.1 เครือข่ายความหมาย (Semantic Networks)

เครือข่ายความหมาย คือกราฟที่แสดงความรู้โดยใช้โหนด (Nodes) แทนแนวคิดหรือวัตถุ และเส้นเชื่อม (Edges) แทนความสัมพันธ์

flowchart TB
    subgraph semantic["ตัวอย่างเครือข่ายความหมาย"]
        style semantic fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["สิ่งมีชีวิต
(Living Thing)"] B["สัตว์
(Animal)"] C["นก
(Bird)"] D["ปลา
(Fish)"] E["นกกระจอก
(Sparrow)"] F["เพนกวิน
(Penguin)"] G["ปลาทอง
(Goldfish)"] H["บินได้
(Can Fly)"] I["มีขน
(Has Feathers)"] J["ว่ายน้ำได้
(Can Swim)"] end A -->|"is-a"| B B -->|"is-a"| C B -->|"is-a"| D C -->|"is-a"| E C -->|"is-a"| F D -->|"is-a"| G C -->|"has-property"| H C -->|"has-property"| I D -->|"has-property"| J F -->|"override"| J style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style B fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style C fill:#3c3836,stroke:#83a598,color:#ebdbb2 style D fill:#3c3836,stroke:#83a598,color:#ebdbb2 style E fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style F fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style G fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style H fill:#504945,stroke:#8ec07c,color:#ebdbb2 style I fill:#504945,stroke:#8ec07c,color:#ebdbb2 style J fill:#504945,stroke:#8ec07c,color:#ebdbb2

5.1.1 ประเภทของความสัมพันธ์

ประเภท ความหมาย ตัวอย่าง
is-a เป็นประเภทย่อยของ นก is-a สัตว์
instance-of เป็นตัวอย่างของ Tweety instance-of นก
has-part มีส่วนประกอบ รถยนต์ has-part ล้อ
has-property มีคุณสมบัติ นก has-property บินได้
causes เป็นสาเหตุของ ไฟ causes ความร้อน

5.1.2 การสืบทอด (Inheritance)

คุณสมบัติสามารถ สืบทอด (Inherit) จากคลาสแม่ไปยังคลาสลูกได้ ยกเว้นกรณีที่มีการ แทนที่ (Override)

"""
โปรแกรม Semantic Network
"""

from typing import Dict, List, Set, Optional, Any
from dataclasses import dataclass, field
from collections import defaultdict

@dataclass
class Node:
    """โหนดในเครือข่ายความหมาย"""
    name: str
    properties: Dict[str, Any] = field(default_factory=dict)
    
    def __hash__(self) -> int:
        return hash(self.name)
    
    def __eq__(self, other) -> bool:
        if isinstance(other, Node):
            return self.name == other.name
        return False

class SemanticNetwork:
    """
    เครือข่ายความหมาย (Semantic Network)
    """
    
    def __init__(self):
        self.nodes: Dict[str, Node] = {}
        self.relations: Dict[str, Dict[str, Set[str]]] = defaultdict(lambda: defaultdict(set))
    
    def add_node(self, name: str, **properties) -> Node:
        """
        เพิ่มโหนดใหม่
        
        พารามิเตอร์:
            name: ชื่อโหนด
            **properties: คุณสมบัติของโหนด
        
        คืนค่า:
            โหนดที่สร้าง
        """
        node = Node(name, properties)
        self.nodes[name] = node
        return node
    
    def add_relation(self, source: str, relation: str, target: str) -> None:
        """
        เพิ่มความสัมพันธ์
        
        พารามิเตอร์:
            source: โหนดต้นทาง
            relation: ประเภทความสัมพันธ์
            target: โหนดปลายทาง
        """
        self.relations[source][relation].add(target)
    
    def get_related(self, source: str, relation: str) -> Set[str]:
        """
        หาโหนดที่มีความสัมพันธ์กับโหนดที่ระบุ
        
        พารามิเตอร์:
            source: โหนดต้นทาง
            relation: ประเภทความสัมพันธ์
        
        คืนค่า:
            ชุดของโหนดที่มีความสัมพันธ์
        """
        return self.relations[source][relation]
    
    def get_ancestors(self, node: str, relation: str = "is-a") -> List[str]:
        """
        หาบรรพบุรุษทั้งหมดของโหนด
        
        พารามิเตอร์:
            node: โหนดที่ต้องการหาบรรพบุรุษ
            relation: ประเภทความสัมพันธ์ (ค่าเริ่มต้น: is-a)
        
        คืนค่า:
            รายการบรรพบุรุษเรียงจากใกล้ไปไกล
        """
        ancestors = []
        current = node
        visited = set()
        
        while True:
            parents = self.get_related(current, relation)
            if not parents or current in visited:
                break
            visited.add(current)
            parent = next(iter(parents))
            ancestors.append(parent)
            current = parent
        
        return ancestors
    
    def inherit_property(
        self, 
        node: str, 
        property_name: str,
        relation: str = "is-a"
    ) -> Optional[Any]:
        """
        สืบทอดคุณสมบัติจากบรรพบุรุษ
        
        พารามิเตอร์:
            node: โหนดที่ต้องการหาคุณสมบัติ
            property_name: ชื่อคุณสมบัติ
            relation: ประเภทความสัมพันธ์สำหรับการสืบทอด
        
        คืนค่า:
            ค่าคุณสมบัติ หรือ None ถ้าไม่พบ
        """
        # ตรวจสอบที่โหนดปัจจุบันก่อน
        if node in self.nodes:
            if property_name in self.nodes[node].properties:
                return self.nodes[node].properties[property_name]
        
        # สืบทอดจากบรรพบุรุษ
        for ancestor in self.get_ancestors(node, relation):
            if ancestor in self.nodes:
                if property_name in self.nodes[ancestor].properties:
                    return self.nodes[ancestor].properties[property_name]
        
        return None
    
    def query(self, subject: str, relation: str, obj: Optional[str] = None) -> bool:
        """
        สอบถามความสัมพันธ์
        
        พารามิเตอร์:
            subject: โหนดประธาน
            relation: ประเภทความสัมพันธ์
            obj: โหนดกรรม (ถ้าไม่ระบุจะถามว่ามีความสัมพันธ์นี้หรือไม่)
        
        คืนค่า:
            True ถ้าความสัมพันธ์เป็นจริง
        """
        if obj is None:
            return bool(self.get_related(subject, relation))
        
        # ตรวจสอบโดยตรง
        if obj in self.get_related(subject, relation):
            return True
        
        # ตรวจสอบผ่านการสืบทอด (สำหรับ is-a)
        if relation == "is-a":
            return obj in self.get_ancestors(subject, "is-a")
        
        return False
    
    def display(self) -> None:
        """แสดงเครือข่ายความหมาย"""
        print("=== Semantic Network ===\n")
        
        print("โหนด (Nodes):")
        for name, node in self.nodes.items():
            props = ", ".join(f"{k}={v}" for k, v in node.properties.items())
            print(f"  {name}: {{{props}}}" if props else f"  {name}")
        
        print("\nความสัมพันธ์ (Relations):")
        for source, rels in self.relations.items():
            for rel_type, targets in rels.items():
                for target in targets:
                    print(f"  {source} --[{rel_type}]--> {target}")

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # สร้างเครือข่ายความหมาย
    net = SemanticNetwork()
    
    # เพิ่มโหนดพร้อมคุณสมบัติ
    net.add_node("Animal", breathes=True, alive=True)
    net.add_node("Bird", can_fly=True, has_feathers=True)
    net.add_node("Fish", can_swim=True, has_scales=True)
    net.add_node("Sparrow", color="brown")
    net.add_node("Penguin", can_fly=False, can_swim=True)  # Override can_fly
    net.add_node("Goldfish", color="gold")
    net.add_node("Tweety", name="Tweety")
    
    # เพิ่มความสัมพันธ์ is-a
    net.add_relation("Bird", "is-a", "Animal")
    net.add_relation("Fish", "is-a", "Animal")
    net.add_relation("Sparrow", "is-a", "Bird")
    net.add_relation("Penguin", "is-a", "Bird")
    net.add_relation("Goldfish", "is-a", "Fish")
    net.add_relation("Tweety", "instance-of", "Sparrow")
    
    # แสดงเครือข่าย
    net.display()
    
    print("\n=== การสืบทอดคุณสมบัติ ===\n")
    
    # ทดสอบการสืบทอด
    print(f"Sparrow can_fly: {net.inherit_property('Sparrow', 'can_fly')}")
    print(f"Sparrow breathes: {net.inherit_property('Sparrow', 'breathes')}")
    print(f"Penguin can_fly: {net.inherit_property('Penguin', 'can_fly')}")  # Override
    print(f"Penguin can_swim: {net.inherit_property('Penguin', 'can_swim')}")
    
    print("\n=== การสอบถาม ===\n")
    
    # ทดสอบการสอบถาม
    print(f"Sparrow is-a Bird: {net.query('Sparrow', 'is-a', 'Bird')}")
    print(f"Sparrow is-a Animal: {net.query('Sparrow', 'is-a', 'Animal')}")
    print(f"Penguin is-a Fish: {net.query('Penguin', 'is-a', 'Fish')}")

5.2 กรอบ (Frames)

กรอบ (Frame) เป็นโครงสร้างข้อมูลสำหรับแทนสถานการณ์แบบแผนหรือวัตถุ พัฒนาโดย Marvin Minsky (1975)

5.2.1 โครงสร้างของ Frame

Frame: ชื่อ
  Slot1: ค่า1
  Slot2: ค่า2
  ...
  Slot_n: ค่า_n

5.2.2 ประเภทของ Slot

ประเภท คำอธิบาย ตัวอย่าง
ค่าเริ่มต้น (Default) ค่าที่ใช้เมื่อไม่มีข้อมูล จำนวนขา: 4
ค่าที่สืบทอด (Inherited) ค่าที่ได้จาก Frame แม่ สีขน: สืบทอดจาก Animal
ค่าที่คำนวณ (Computed) ค่าที่คำนวณจาก slot อื่น อายุ: current_year - birth_year
ข้อจำกัด (Constraint) เงื่อนไขที่ค่าต้องเป็นไปตาม อายุ: > 0
ขั้นตอน (Procedure) โปรแกรมที่ทำงานเมื่อ slot ถูกเข้าถึง if-needed, if-added
"""
โปรแกรม Frame-based Knowledge Representation
"""

from typing import Any, Callable, Dict, List, Optional, Set
from dataclasses import dataclass, field
from enum import Enum, auto

class SlotType(Enum):
    """ประเภทของ Slot"""
    VALUE = auto()
    DEFAULT = auto()
    INHERITED = auto()
    COMPUTED = auto()
    CONSTRAINT = auto()

@dataclass
class Slot:
    """
    Slot ใน Frame
    """
    name: str
    value: Any = None
    slot_type: SlotType = SlotType.VALUE
    default: Any = None
    if_needed: Optional[Callable] = None  # เรียกเมื่อต้องการค่า
    if_added: Optional[Callable] = None   # เรียกเมื่อเพิ่มค่า
    constraints: List[Callable] = field(default_factory=list)
    
    def get_value(self, frame: 'Frame') -> Any:
        """
        ดึงค่าของ slot
        
        พารามิเตอร์:
            frame: Frame ที่ slot นี้อยู่
        
        คืนค่า:
            ค่าของ slot
        """
        # ถ้ามีค่าอยู่แล้ว
        if self.value is not None:
            return self.value
        
        # ถ้ามีขั้นตอน if-needed
        if self.if_needed is not None:
            return self.if_needed(frame)
        
        # ถ้ามีค่าเริ่มต้น
        if self.default is not None:
            return self.default
        
        return None
    
    def set_value(self, value: Any, frame: 'Frame') -> bool:
        """
        กำหนดค่าของ slot
        
        พารามิเตอร์:
            value: ค่าที่ต้องการกำหนด
            frame: Frame ที่ slot นี้อยู่
        
        คืนค่า:
            True ถ้ากำหนดค่าสำเร็จ
        """
        # ตรวจสอบข้อจำกัด
        for constraint in self.constraints:
            if not constraint(value):
                print(f"ข้อจำกัดล้มเหลวสำหรับ slot '{self.name}'")
                return False
        
        self.value = value
        
        # เรียก if-added ถ้ามี
        if self.if_added is not None:
            self.if_added(frame, value)
        
        return True

class Frame:
    """
    Frame สำหรับแทนความรู้
    """
    
    def __init__(self, name: str, parent: Optional['Frame'] = None):
        self.name = name
        self.parent = parent
        self.slots: Dict[str, Slot] = {}
    
    def add_slot(
        self, 
        name: str, 
        value: Any = None,
        default: Any = None,
        slot_type: SlotType = SlotType.VALUE,
        if_needed: Optional[Callable] = None,
        if_added: Optional[Callable] = None,
        constraints: List[Callable] = None
    ) -> None:
        """เพิ่ม slot ใหม่"""
        self.slots[name] = Slot(
            name=name,
            value=value,
            slot_type=slot_type,
            default=default,
            if_needed=if_needed,
            if_added=if_added,
            constraints=constraints or []
        )
    
    def get(self, slot_name: str) -> Any:
        """
        ดึงค่าจาก slot
        
        พารามิเตอร์:
            slot_name: ชื่อ slot
        
        คืนค่า:
            ค่าของ slot
        """
        # ตรวจสอบที่ frame ปัจจุบัน
        if slot_name in self.slots:
            value = self.slots[slot_name].get_value(self)
            if value is not None:
                return value
        
        # สืบทอดจาก parent
        if self.parent is not None:
            return self.parent.get(slot_name)
        
        return None
    
    def set(self, slot_name: str, value: Any) -> bool:
        """
        กำหนดค่าให้ slot
        
        พารามิเตอร์:
            slot_name: ชื่อ slot
            value: ค่าที่ต้องการกำหนด
        
        คืนค่า:
            True ถ้าสำเร็จ
        """
        if slot_name not in self.slots:
            self.add_slot(slot_name)
        
        return self.slots[slot_name].set_value(value, self)
    
    def display(self, indent: int = 0) -> None:
        """แสดง frame"""
        prefix = "  " * indent
        print(f"{prefix}Frame: {self.name}")
        
        if self.parent:
            print(f"{prefix}  Parent: {self.parent.name}")
        
        print(f"{prefix}  Slots:")
        for name, slot in self.slots.items():
            value = slot.get_value(self)
            inherited = "(inherited)" if slot.value is None and value is not None else ""
            print(f"{prefix}    {name}: {value} {inherited}")

class FrameSystem:
    """
    ระบบจัดการ Frame
    """
    
    def __init__(self):
        self.frames: Dict[str, Frame] = {}
    
    def create_frame(self, name: str, parent_name: Optional[str] = None) -> Frame:
        """
        สร้าง frame ใหม่
        
        พารามิเตอร์:
            name: ชื่อ frame
            parent_name: ชื่อ frame แม่ (ถ้ามี)
        
        คืนค่า:
            Frame ที่สร้าง
        """
        parent = self.frames.get(parent_name) if parent_name else None
        frame = Frame(name, parent)
        self.frames[name] = frame
        return frame
    
    def get_frame(self, name: str) -> Optional[Frame]:
        """ดึง frame ตามชื่อ"""
        return self.frames.get(name)
    
    def display_all(self) -> None:
        """แสดง frame ทั้งหมด"""
        print("=== Frame System ===\n")
        for frame in self.frames.values():
            frame.display()
            print()

# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # สร้างระบบ Frame
    system = FrameSystem()
    
    # สร้าง Frame: Animal
    animal = system.create_frame("Animal")
    animal.add_slot("alive", default=True)
    animal.add_slot("breathes", default=True)
    animal.add_slot("num_legs", default=4)
    
    # สร้าง Frame: Bird (สืบทอดจาก Animal)
    bird = system.create_frame("Bird", "Animal")
    bird.add_slot("can_fly", default=True)
    bird.add_slot("has_feathers", default=True)
    bird.add_slot("num_legs", value=2)  # Override
    
    # สร้าง Frame: Penguin (สืบทอดจาก Bird)
    penguin = system.create_frame("Penguin", "Bird")
    penguin.add_slot("can_fly", value=False)  # Override
    penguin.add_slot("can_swim", value=True)
    penguin.add_slot("habitat", value="Antarctica")
    
    # สร้าง Instance: Tux
    tux = system.create_frame("Tux", "Penguin")
    tux.add_slot("name", value="Tux")
    tux.add_slot("age", value=3, constraints=[lambda x: x > 0])
    
    # แสดงระบบ
    system.display_all()
    
    # ทดสอบการสืบทอด
    print("=== ทดสอบการสืบทอด ===\n")
    print(f"Tux.can_fly: {tux.get('can_fly')}")
    print(f"Tux.has_feathers: {tux.get('has_feathers')}")
    print(f"Tux.alive: {tux.get('alive')}")
    print(f"Tux.num_legs: {tux.get('num_legs')}")

ผลลัพธ์:

=== Frame System ===

Frame: Animal
  Slots:
    alive: True 
    breathes: True 
    num_legs: 4 

Frame: Bird
  Parent: Animal
  Slots:
    can_fly: True 
    has_feathers: True 
    num_legs: 2 

Frame: Penguin
  Parent: Bird
  Slots:
    can_fly: False 
    can_swim: True 
    habitat: Antarctica 

Frame: Tux
  Parent: Penguin
  Slots:
    name: Tux 
    age: 3 

=== ทดสอบการสืบทอด ===

Tux.can_fly: False
Tux.has_feathers: True
Tux.alive: True
Tux.num_legs: 2

6. ออนโทโลยี (Ontologies)

6.1 ความหมายและความสำคัญ

ออนโทโลยี (Ontology) คือการกำหนดอย่างเป็นทางการของชุดแนวคิด (Concepts) และความสัมพันธ์ (Relations) ในโดเมนใดโดเมนหนึ่ง

flowchart TB
    subgraph ontology["โครงสร้างออนโทโลยี (Ontology Structure)"]
        style ontology fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["ออนโทโลยี
(Ontology)"] B["คลาส
(Classes)"] C["คุณสมบัติ
(Properties)"] D["อินสแตนซ์
(Instances)"] E["สัจพจน์
(Axioms)"] B1["ลำดับชั้น
(Hierarchy)"] C1["Object Properties"] C2["Data Properties"] D1["Individuals"] E1["Class Axioms"] E2["Property Axioms"] end A --> B A --> C A --> D A --> E B --> B1 C --> C1 C --> C2 D --> D1 E --> E1 E --> E2 style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style B fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style C fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style D fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style E fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style B1 fill:#504945,stroke:#83a598,color:#ebdbb2 style C1 fill:#504945,stroke:#83a598,color:#ebdbb2 style C2 fill:#504945,stroke:#83a598,color:#ebdbb2 style D1 fill:#504945,stroke:#83a598,color:#ebdbb2 style E1 fill:#504945,stroke:#83a598,color:#ebdbb2 style E2 fill:#504945,stroke:#83a598,color:#ebdbb2

6.2 ระดับของออนโทโลยี

ระดับ คำอธิบาย ตัวอย่าง
Upper Ontology แนวคิดทั่วไปสุด SUMO, DOLCE, BFO
Domain Ontology เฉพาะโดเมน Gene Ontology, Pizza Ontology
Task Ontology เฉพาะงาน Scheduling Ontology
Application Ontology เฉพาะแอปพลิเคชัน ออนโทโลยีของระบบเฉพาะ

6.3 ภาษา OWL (Web Ontology Language)

OWL (Web Ontology Language) เป็นภาษามาตรฐานสำหรับสร้างออนโทโลยีบนเว็บ

6.3.1 องค์ประกอบหลักของ OWL

"""
โปรแกรมจำลองการทำงานกับ OWL Ontology
"""

from typing import Dict, List, Set, Optional, Any
from dataclasses import dataclass, field
from enum import Enum, auto

class PropertyType(Enum):
    """ประเภทของ Property"""
    OBJECT = auto()      # เชื่อมระหว่าง Individuals
    DATA = auto()        # เชื่อม Individual กับ Data Value
    ANNOTATION = auto()  # ใช้สำหรับ metadata

@dataclass
class OWLClass:
    """คลาสใน OWL"""
    uri: str
    label: str
    parent: Optional['OWLClass'] = None
    equivalent_classes: Set['OWLClass'] = field(default_factory=set)
    disjoint_classes: Set['OWLClass'] = field(default_factory=set)
    
    def __hash__(self) -> int:
        return hash(self.uri)
    
    def __eq__(self, other) -> bool:
        if isinstance(other, OWLClass):
            return self.uri == other.uri
        return False

@dataclass
class OWLProperty:
    """Property ใน OWL"""
    uri: str
    label: str
    property_type: PropertyType
    domain: Optional[OWLClass] = None
    range_class: Optional[OWLClass] = None  # สำหรับ Object Property
    range_datatype: Optional[str] = None    # สำหรับ Data Property
    is_functional: bool = False
    is_transitive: bool = False
    is_symmetric: bool = False
    inverse_of: Optional['OWLProperty'] = None

@dataclass
class OWLIndividual:
    """Individual ใน OWL"""
    uri: str
    label: str
    types: Set[OWLClass] = field(default_factory=set)
    object_properties: Dict[OWLProperty, Set['OWLIndividual']] = field(default_factory=dict)
    data_properties: Dict[OWLProperty, Set[Any]] = field(default_factory=dict)

class OWLOntology:
    """
    ออนโทโลยีในรูปแบบ OWL
    """
    
    def __init__(self, uri: str, name: str):
        self.uri = uri
        self.name = name
        self.classes: Dict[str, OWLClass] = {}
        self.properties: Dict[str, OWLProperty] = {}
        self.individuals: Dict[str, OWLIndividual] = {}
    
    def add_class(
        self, 
        uri: str, 
        label: str, 
        parent_uri: Optional[str] = None
    ) -> OWLClass:
        """
        เพิ่มคลาสใหม่
        
        พารามิเตอร์:
            uri: URI ของคลาส
            label: ชื่อที่แสดง
            parent_uri: URI ของคลาสแม่
        
        คืนค่า:
            OWLClass ที่สร้าง
        """
        parent = self.classes.get(parent_uri) if parent_uri else None
        owl_class = OWLClass(uri, label, parent)
        self.classes[uri] = owl_class
        return owl_class
    
    def add_object_property(
        self,
        uri: str,
        label: str,
        domain_uri: Optional[str] = None,
        range_uri: Optional[str] = None,
        is_functional: bool = False,
        is_transitive: bool = False,
        is_symmetric: bool = False
    ) -> OWLProperty:
        """เพิ่ม Object Property"""
        prop = OWLProperty(
            uri=uri,
            label=label,
            property_type=PropertyType.OBJECT,
            domain=self.classes.get(domain_uri),
            range_class=self.classes.get(range_uri),
            is_functional=is_functional,
            is_transitive=is_transitive,
            is_symmetric=is_symmetric
        )
        self.properties[uri] = prop
        return prop
    
    def add_data_property(
        self,
        uri: str,
        label: str,
        domain_uri: Optional[str] = None,
        range_datatype: str = "string",
        is_functional: bool = False
    ) -> OWLProperty:
        """เพิ่ม Data Property"""
        prop = OWLProperty(
            uri=uri,
            label=label,
            property_type=PropertyType.DATA,
            domain=self.classes.get(domain_uri),
            range_datatype=range_datatype,
            is_functional=is_functional
        )
        self.properties[uri] = prop
        return prop
    
    def add_individual(
        self,
        uri: str,
        label: str,
        type_uris: List[str] = None
    ) -> OWLIndividual:
        """
        เพิ่ม Individual
        
        พารามิเตอร์:
            uri: URI ของ individual
            label: ชื่อที่แสดง
            type_uris: รายการ URI ของคลาสที่เป็นประเภท
        
        คืนค่า:
            OWLIndividual ที่สร้าง
        """
        types = set()
        for type_uri in (type_uris or []):
            if type_uri in self.classes:
                types.add(self.classes[type_uri])
        
        individual = OWLIndividual(uri, label, types)
        self.individuals[uri] = individual
        return individual
    
    def assert_object_property(
        self,
        subject_uri: str,
        property_uri: str,
        object_uri: str
    ) -> None:
        """กำหนดค่า Object Property"""
        subject = self.individuals.get(subject_uri)
        prop = self.properties.get(property_uri)
        obj = self.individuals.get(object_uri)
        
        if subject and prop and obj:
            if prop not in subject.object_properties:
                subject.object_properties[prop] = set()
            subject.object_properties[prop].add(obj)
    
    def assert_data_property(
        self,
        subject_uri: str,
        property_uri: str,
        value: Any
    ) -> None:
        """กำหนดค่า Data Property"""
        subject = self.individuals.get(subject_uri)
        prop = self.properties.get(property_uri)
        
        if subject and prop:
            if prop not in subject.data_properties:
                subject.data_properties[prop] = set()
            subject.data_properties[prop].add(value)
    
    def get_instances_of(self, class_uri: str, include_subclasses: bool = True) -> Set[OWLIndividual]:
        """
        หา Individuals ที่เป็นประเภทของคลาสที่ระบุ
        
        พารามิเตอร์:
            class_uri: URI ของคลาส
            include_subclasses: รวม instances ของ subclass ด้วยหรือไม่
        
        คืนค่า:
            ชุดของ OWLIndividual
        """
        target_class = self.classes.get(class_uri)
        if not target_class:
            return set()
        
        instances = set()
        
        for individual in self.individuals.values():
            for ind_type in individual.types:
                if ind_type == target_class:
                    instances.add(individual)
                    break
                elif include_subclasses:
                    # ตรวจสอบว่าเป็น subclass หรือไม่
                    current = ind_type
                    while current.parent:
                        if current.parent == target_class:
                            instances.add(individual)
                            break
                        current = current.parent
        
        return instances
    
    def display(self) -> None:
        """แสดงออนโทโลยี"""
        print(f"=== Ontology: {self.name} ===")
        print(f"URI: {self.uri}\n")
        
        print("Classes:")
        for cls in self.classes.values():
            parent_info = f" (subclass of {cls.parent.label})" if cls.parent else ""
            print(f"  - {cls.label}{parent_info}")
        
        print("\nObject Properties:")
        for prop in self.properties.values():
            if prop.property_type == PropertyType.OBJECT:
                print(f"  - {prop.label}")
        
        print("\nData Properties:")
        for prop in self.properties.values():
            if prop.property_type == PropertyType.DATA:
                print(f"  - {prop.label}: {prop.range_datatype}")
        
        print("\nIndividuals:")
        for ind in self.individuals.values():
            types = ", ".join(t.label for t in ind.types)
            print(f"  - {ind.label} ({types})")
            
            for prop, objects in ind.object_properties.items():
                for obj in objects:
                    print(f"      {prop.label} -> {obj.label}")
            
            for prop, values in ind.data_properties.items():
                for val in values:
                    print(f"      {prop.label} = {val}")

# ตัวอย่างการใช้งาน: Pizza Ontology
if __name__ == "__main__":
    # สร้างออนโทโลยี Pizza
    pizza_onto = OWLOntology(
        uri="http://example.org/pizza",
        name="Pizza Ontology"
    )
    
    # เพิ่มคลาส
    pizza_onto.add_class("pizza:Food", "Food")
    pizza_onto.add_class("pizza:Pizza", "Pizza", "pizza:Food")
    pizza_onto.add_class("pizza:Topping", "Topping", "pizza:Food")
    pizza_onto.add_class("pizza:MeatTopping", "Meat Topping", "pizza:Topping")
    pizza_onto.add_class("pizza:VegetableTopping", "Vegetable Topping", "pizza:Topping")
    pizza_onto.add_class("pizza:CheeseTopping", "Cheese Topping", "pizza:Topping")
    
    # เพิ่ม Properties
    pizza_onto.add_object_property(
        "pizza:hasTopping",
        "has topping",
        domain_uri="pizza:Pizza",
        range_uri="pizza:Topping"
    )
    
    pizza_onto.add_data_property(
        "pizza:hasCalories",
        "has calories",
        domain_uri="pizza:Food",
        range_datatype="integer"
    )
    
    pizza_onto.add_data_property(
        "pizza:hasName",
        "has name",
        domain_uri="pizza:Food",
        range_datatype="string"
    )
    
    # เพิ่ม Individuals
    pizza_onto.add_individual(
        "pizza:Margherita",
        "Margherita Pizza",
        ["pizza:Pizza"]
    )
    
    pizza_onto.add_individual(
        "pizza:Mozzarella",
        "Mozzarella",
        ["pizza:CheeseTopping"]
    )
    
    pizza_onto.add_individual(
        "pizza:Tomato",
        "Tomato",
        ["pizza:VegetableTopping"]
    )
    
    # กำหนดความสัมพันธ์
    pizza_onto.assert_object_property("pizza:Margherita", "pizza:hasTopping", "pizza:Mozzarella")
    pizza_onto.assert_object_property("pizza:Margherita", "pizza:hasTopping", "pizza:Tomato")
    pizza_onto.assert_data_property("pizza:Margherita", "pizza:hasCalories", 250)
    pizza_onto.assert_data_property("pizza:Margherita", "pizza:hasName", "Margherita")
    
    # แสดงออนโทโลยี
    pizza_onto.display()
    
    print("\n=== Query: Instances of Topping ===")
    toppings = pizza_onto.get_instances_of("pizza:Topping")
    for t in toppings:
        print(f"  - {t.label}")

6.4 เครื่องมือ Protégé

Protégé เป็นโปรแกรมแก้ไขออนโทโลยี (Ontology Editor) ที่พัฒนาโดย Stanford University

flowchart LR
    subgraph protege["คุณสมบัติหลักของ Protégé"]
        style protege fill:#282828,stroke:#98971a,color:#ebdbb2
        
        A["Protégé"]
        
        B["Class Editor
แก้ไขคลาส"] C["Property Editor
แก้ไข Properties"] D["Individual Editor
แก้ไข Individuals"] E["Reasoner
ระบบอนุมาน"] F["Visualization
แสดงกราฟ"] G["Plugin Support
ส่วนขยาย"] end A --> B A --> C A --> D A --> E A --> F A --> G style A fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style B fill:#3c3836,stroke:#83a598,color:#ebdbb2 style C fill:#3c3836,stroke:#83a598,color:#ebdbb2 style D fill:#3c3836,stroke:#83a598,color:#ebdbb2 style E fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style F fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style G fill:#3c3836,stroke:#d3869b,color:#ebdbb2

7. เครื่องมือและการประยุกต์ใช้ (Tools and Applications)

7.1 Prolog Programming

Prolog เป็นภาษาโปรแกรมเชิงตรรกะ (Logic Programming Language) ที่ใช้สำหรับงาน AI

7.1.1 ไวยากรณ์พื้นฐาน

% ข้อเท็จจริง (Facts)
human(socrates).
human(plato).
mortal(X) :- human(X).  % กฎ: ถ้า X เป็นมนุษย์ แล้ว X ต้องตาย

% ความสัมพันธ์ครอบครัว
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).

% กฎ: ปู่ย่าตายาย
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).

% กฎ: พี่น้อง
sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.

7.1.2 การใช้ PySwip (Python-Prolog Interface)

"""
โปรแกรมใช้งาน Prolog ผ่าน Python ด้วย PySwip
"""

# หมายเหตุ: ต้องติดตั้ง SWI-Prolog และ PySwip ก่อน
# pip install pyswip

try:
    from pyswip import Prolog
    
    class PrologKnowledgeBase:
        """
        ฐานความรู้ที่ใช้ Prolog เป็น backend
        """
        
        def __init__(self):
            self.prolog = Prolog()
        
        def assert_fact(self, fact: str) -> None:
            """
            เพิ่มข้อเท็จจริง
            
            พารามิเตอร์:
                fact: ข้อเท็จจริงในรูปแบบ Prolog
            """
            self.prolog.assertz(fact)
            print(f"เพิ่มข้อเท็จจริง: {fact}")
        
        def assert_rule(self, head: str, body: str) -> None:
            """
            เพิ่มกฎ
            
            พารามิเตอร์:
                head: ส่วนหัวของกฎ
                body: ส่วนเงื่อนไขของกฎ
            """
            rule = f"{head} :- {body}"
            self.prolog.assertz(rule)
            print(f"เพิ่มกฎ: {rule}")
        
        def query(self, query_string: str):
            """
            สอบถาม
            
            พารามิเตอร์:
                query_string: คำถามในรูปแบบ Prolog
            
            คืนค่า:
                รายการผลลัพธ์
            """
            return list(self.prolog.query(query_string))
    
    # ตัวอย่างการใช้งาน
    if __name__ == "__main__":
        kb = PrologKnowledgeBase()
        
        # เพิ่มข้อเท็จจริง
        kb.assert_fact("human(socrates)")
        kb.assert_fact("human(plato)")
        kb.assert_fact("human(aristotle)")
        
        # เพิ่มกฎ
        kb.assert_rule("mortal(X)", "human(X)")
        
        # สอบถาม
        print("\nใครบ้างที่ต้องตาย?")
        results = kb.query("mortal(X)")
        for result in results:
            print(f"  {result['X']}")

except ImportError:
    print("PySwip ไม่ได้ติดตั้ง กรุณาติดตั้งด้วย: pip install pyswip")
    print("และต้องติดตั้ง SWI-Prolog ด้วย")
    print("\nแสดงตัวอย่าง Prolog โดยไม่ใช้ PySwip:\n")
    
    # จำลองการทำงานของ Prolog อย่างง่าย
    class SimplePrologEmulator:
        """
        จำลองการทำงานของ Prolog แบบง่าย
        """
        
        def __init__(self):
            self.facts = {}  # predicate -> set of arguments
            self.rules = []  # list of (head, body) tuples
        
        def assertz(self, statement: str) -> None:
            """เพิ่มข้อเท็จจริงหรือกฎ"""
            if ":-" in statement:
                # เป็นกฎ
                head, body = statement.split(":-")
                self.rules.append((head.strip(), body.strip()))
                print(f"เพิ่มกฎ: {statement}")
            else:
                # เป็นข้อเท็จจริง
                # แยก predicate และ arguments
                import re
                match = re.match(r'(\w+)\(([^)]+)\)', statement)
                if match:
                    pred, args = match.groups()
                    if pred not in self.facts:
                        self.facts[pred] = set()
                    self.facts[pred].add(args)
                    print(f"เพิ่มข้อเท็จจริง: {statement}")
        
        def query(self, query_string: str):
            """สอบถามแบบง่าย"""
            import re
            match = re.match(r'(\w+)\((\w+)\)', query_string)
            if not match:
                return []
            
            pred, var = match.groups()
            results = []
            
            # ตรวจสอบข้อเท็จจริงโดยตรง
            if pred in self.facts:
                for arg in self.facts[pred]:
                    results.append({var: arg})
            
            # ตรวจสอบกฎ
            for head, body in self.rules:
                head_match = re.match(r'(\w+)\((\w+)\)', head)
                body_match = re.match(r'(\w+)\((\w+)\)', body)
                
                if head_match and body_match:
                    head_pred, head_var = head_match.groups()
                    body_pred, body_var = body_match.groups()
                    
                    if head_pred == pred:
                        # ใช้กฎ
                        if body_pred in self.facts:
                            for arg in self.facts[body_pred]:
                                results.append({var: arg})
            
            return results
    
    # ทดสอบ
    emulator = SimplePrologEmulator()
    
    emulator.assertz("human(socrates)")
    emulator.assertz("human(plato)")
    emulator.assertz("human(aristotle)")
    emulator.assertz("mortal(X) :- human(X)")
    
    print("\nใครบ้างที่ต้องตาย?")
    results = emulator.query("mortal(X)")
    for result in results:
        print(f"  {result['X']}")

7.2 ตารางเปรียบเทียบเครื่องมือ

เครื่องมือ ประเภท ภาษา การใช้งานหลัก
SWI-Prolog Logic Programming Prolog การอนุมาน, Expert Systems
PySwip Interface Python/Prolog เชื่อมต่อ Python กับ Prolog
Protégé Ontology Editor Java สร้าง/แก้ไข Ontology
OWLReady2 Ontology Library Python จัดการ OWL ใน Python
Apache Jena Semantic Web Java RDF/OWL Processing
RDFLib RDF Library Python จัดการ RDF
CLIPS Expert System Shell C Rule-based Systems

7.3 การประยุกต์ใช้งาน

flowchart TB
    subgraph applications["การประยุกต์ใช้งาน"]
        style applications fill:#282828,stroke:#d79921,color:#ebdbb2
        
        A["Knowledge Representation
& Logic"] B["ระบบผู้เชี่ยวชาญ
(Expert Systems)"] C["Semantic Web
& Knowledge Graphs"] D["การประมวลผล
ภาษาธรรมชาติ (NLP)"] E["หุ่นยนต์
(Robotics)"] F["ระบบวินิจฉัย
(Diagnosis Systems)"] B1["MYCIN
ระบบวินิจฉัยทางการแพทย์"] C1["Google Knowledge Graph
DBpedia, Wikidata"] D1["Question Answering
Chatbots"] E1["Task Planning
Scene Understanding"] F1["Fault Diagnosis
Troubleshooting"] end A --> B A --> C A --> D A --> E A --> F B --> B1 C --> C1 D --> D1 E --> E1 F --> F1 style A fill:#3c3836,stroke:#fabd2f,color:#ebdbb2 style B fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style C fill:#3c3836,stroke:#b8bb26,color:#ebdbb2 style D fill:#3c3836,stroke:#83a598,color:#ebdbb2 style E fill:#3c3836,stroke:#83a598,color:#ebdbb2 style F fill:#3c3836,stroke:#d3869b,color:#ebdbb2 style B1 fill:#504945,stroke:#b8bb26,color:#ebdbb2 style C1 fill:#504945,stroke:#b8bb26,color:#ebdbb2 style D1 fill:#504945,stroke:#83a598,color:#ebdbb2 style E1 fill:#504945,stroke:#83a598,color:#ebdbb2 style F1 fill:#504945,stroke:#d3869b,color:#ebdbb2

8. สรุป (Summary)

8.1 ประเด็นสำคัญ

การแทนความรู้และตรรกศาสตร์เป็นรากฐานสำคัญของปัญญาประดิษฐ์ ประกอบด้วยหัวข้อหลักดังนี้:

  1. ตรรกศาสตร์เชิงประพจน์ (Propositional Logic)

  2. ตรรกศาสตร์อันดับหนึ่ง (First-Order Logic)

  3. ตัวแทนฐานความรู้ (Knowledge-Based Agents)

  4. เครือข่ายความหมายและกรอบ (Semantic Networks & Frames)

  5. ออนโทโลยี (Ontologies)

8.2 แนวโน้มในอนาคต

แนวโน้ม คำอธิบาย
Neuro-Symbolic AI ผสมผสานการเรียนรู้เชิงลึกกับการอนุมานเชิงสัญลักษณ์
Knowledge Graph Embedding แปลง Knowledge Graphs เป็น vector space
Commonsense Reasoning พัฒนาความสามารถในการใช้ความรู้ทั่วไป
Explainable AI ใช้ตรรกศาสตร์เพื่ออธิบายการตัดสินใจของ AI

9. เอกสารอ้างอิง (References)

9.1 ตำราหลัก

  1. Russell, S., & Norvig, P. (2021). Artificial Intelligence: A Modern Approach (4th ed.). Pearson.

  2. Brachman, R., & Levesque, H. (2004). Knowledge Representation and Reasoning. Morgan Kaufmann.

  3. Baader, F., Calvanese, D., McGuinness, D., Nardi, D., & Patel-Schneider, P. (2007). The Description Logic Handbook (2nd ed.). Cambridge University Press.

9.2 บทความวิจัย

  1. Minsky, M. (1975). A Framework for Representing Knowledge. MIT-AI Laboratory Memo 306.

  2. Hayes, P. J. (1979). The Logic of Frames. In Frame Conceptions and Text Understanding (pp. 46-61). De Gruyter.

9.3 แหล่งข้อมูลออนไลน์

  1. Stanford Encyclopedia of Philosophy - Logic and Artificial Intelligence

  2. W3C OWL Web Ontology Language

  3. Protégé Documentation

  4. SWI-Prolog Documentation

9.4 หลักสูตรออนไลน์

  1. Stanford CS221: Artificial Intelligence

  2. MIT 6.034: Artificial Intelligence