การแทนความรู้ (Knowledge Representation) เป็นสาขาหนึ่งของปัญญาประดิษฐ์ที่มุ่งเน้นการพัฒนาวิธีการแสดงความรู้ในรูปแบบที่คอมพิวเตอร์สามารถเข้าใจและประมวลผลได้ การแทนความรู้ที่ดีจะช่วยให้ระบบ AI สามารถ:
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
| ประเภท | ลักษณะ | ตัวอย่าง | ข้อดี | ข้อเสีย |
|---|---|---|---|---|
| ตรรกศาสตร์ (Logic-based) | ใช้กฎเชิงตรรกะ | Propositional Logic, FOL | แม่นยำ, พิสูจน์ได้ | ไม่ยืดหยุ่น |
| กฎ (Rule-based) | ใช้กฎ IF-THEN | Production Rules | เข้าใจง่าย | ยากในการจัดการ |
| โครงสร้าง (Structured) | ใช้โครงสร้างข้อมูล | Frames, Scripts | จัดระเบียบดี | ซับซ้อน |
| เครือข่าย (Network-based) | ใช้กราฟ | Semantic Networks | มองเห็นได้ | ขาดความหมายทางรูปนัย |
| ความน่าจะเป็น (Probabilistic) | ใช้ความน่าจะเป็น | Bayesian Networks | จัดการความไม่แน่นอน | คำนวณซับซ้อน |
วากยสัมพันธ์ กำหนดกฎเกณฑ์ในการสร้างประโยคที่ถูกต้องตามหลักไวยากรณ์
องค์ประกอบพื้นฐานของตรรกศาสตร์เชิงประพจน์:
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
อรรถศาสตร์ กำหนดความหมายและค่าความจริงของประโยค
การตีความ (Interpretation) คือฟังก์ชันที่กำหนดค่าความจริง (True/False) ให้กับตัวแปรประพจน์แต่ละตัว
สำหรับประพจน์ P และ Q ที่มีการตีความ I:
| ตัวเชื่อม | สัญลักษณ์ | ชื่อ | ความหมาย |
|---|---|---|---|
| นิเสธ | ¬ | NOT | ไม่ใช่ |
| และ | ∧ | AND | และ |
| หรือ | ∨ | OR | หรือ |
| เงื่อนไข | → | IMPLIES | ถ้า...แล้ว |
| เงื่อนไขสองทาง | ↔ | IFF | ก็ต่อเมื่อ |
| 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 |
สัจนิรันดร์ (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
กฎ Modus Ponens เป็นกฎการอนุมานพื้นฐานที่สำคัญที่สุด:
คำอธิบาย:
ตัวอย่าง:
คำอธิบาย:
Resolution เป็นกฎการอนุมานที่ใช้กันอย่างแพร่หลายในระบบพิสูจน์ทฤษฎีบทอัตโนมัติ
คำอธิบาย:
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 - พิสูจน์สำเร็จ!
CNF คือการเชื่อม (conjunction) ของอนุประโยค โดยแต่ละอนุประโยคเป็นการแยก (disjunction) ของ literals
ตัวอย่าง: (P ∨ Q) ∧ (¬P ∨ R) ∧ (¬Q ∨ ¬R)
DNF คือการแยก (disjunction) ของ conjunctions
ตัวอย่าง: (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)}")
ตรรกศาสตร์อันดับหนึ่ง (First-Order Logic - FOL) หรือเรียกอีกอย่างว่า ตรรกศาสตร์เชิงภาคแสดง (Predicate Logic) ขยายขอบเขตจากตรรกศาสตร์เชิงประพจน์โดยเพิ่มความสามารถในการ:
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
ตัวบ่งปริมาณสากล (∀) หมายถึง "สำหรับทุก" หรือ "ทั้งหมด"
คำอธิบาย: สำหรับทุกค่า x, P(x) เป็นจริง
ตัวอย่าง:
ตัวบ่งปริมาณมีอยู่ (∃) หมายถึง "มีอย่างน้อยหนึ่ง" หรือ "มีอยู่"
คำอธิบาย: มีอย่างน้อยหนึ่งค่า x ที่ P(x) เป็นจริง
ตัวอย่าง:
| กฎ | สูตร | คำอธิบาย |
|---|---|---|
| นิเสธของ ∀ | ¬∀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) | ไม่สามารถสลับลำดับได้ |
การรวมเป็นหนึ่ง (Unification) เป็นกระบวนการหาการแทนที่ (Substitution) ที่ทำให้สองนิพจน์เท่ากัน
การแทนที่ (Substitution) θ = {x₁/t₁, x₂/t₂, ...} คือการแทนที่ตัวแปร xᵢ ด้วยเทอม tᵢ
ตัวรวม (Unifier) ของสองนิพจน์ E₁ และ E₂ คือการแทนที่ θ ที่ทำให้ E₁θ = E₂θ
ตัวรวมทั่วไปที่สุด (Most General Unifier - MGU) คือตัวรวมที่มีการแทนที่น้อยที่สุด
"""
โปรแกรม 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}
การอนุมานแบบโซ่ไปข้างหน้า เริ่มจากข้อเท็จจริงที่มีอยู่ แล้วใช้กฎเพื่อสรุปข้อเท็จจริงใหม่
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
ลักษณะสำคัญ:
การอนุมานแบบโซ่ย้อนกลับ เริ่มจากเป้าหมาย แล้วค้นหากฎที่สามารถพิสูจน์เป้าหมายได้
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
ลักษณะสำคัญ:
| คุณลักษณะ | 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
ตัวแทนฐานความรู้ (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
| ส่วนประกอบ | หน้าที่ | คำอธิบาย |
|---|---|---|
| Knowledge Base (KB) | เก็บความรู้ | ชุดของประโยคในภาษาแทนความรู้ |
| Inference Engine | อนุมาน | ใช้กฎการอนุมานเพื่อหาข้อสรุปใหม่ |
| TELL | เพิ่มความรู้ | เพิ่มประโยคใหม่เข้าไปใน KB |
| ASK | สอบถาม | สอบถามว่าประโยคใดเป็นจริงหรือไม่ |
"""
โปรแกรม 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")
เครือข่ายความหมาย คือกราฟที่แสดงความรู้โดยใช้โหนด (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
| ประเภท | ความหมาย | ตัวอย่าง |
|---|---|---|
| is-a | เป็นประเภทย่อยของ | นก is-a สัตว์ |
| instance-of | เป็นตัวอย่างของ | Tweety instance-of นก |
| has-part | มีส่วนประกอบ | รถยนต์ has-part ล้อ |
| has-property | มีคุณสมบัติ | นก has-property บินได้ |
| causes | เป็นสาเหตุของ | ไฟ causes ความร้อน |
คุณสมบัติสามารถ สืบทอด (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')}")
กรอบ (Frame) เป็นโครงสร้างข้อมูลสำหรับแทนสถานการณ์แบบแผนหรือวัตถุ พัฒนาโดย Marvin Minsky (1975)
Frame: ชื่อ
Slot1: ค่า1
Slot2: ค่า2
...
Slot_n: ค่า_n
| ประเภท | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| ค่าเริ่มต้น (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
ออนโทโลยี (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
| ระดับ | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| Upper Ontology | แนวคิดทั่วไปสุด | SUMO, DOLCE, BFO |
| Domain Ontology | เฉพาะโดเมน | Gene Ontology, Pizza Ontology |
| Task Ontology | เฉพาะงาน | Scheduling Ontology |
| Application Ontology | เฉพาะแอปพลิเคชัน | ออนโทโลยีของระบบเฉพาะ |
OWL (Web Ontology Language) เป็นภาษามาตรฐานสำหรับสร้างออนโทโลยีบนเว็บ
"""
โปรแกรมจำลองการทำงานกับ 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}")
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
Prolog เป็นภาษาโปรแกรมเชิงตรรกะ (Logic Programming Language) ที่ใช้สำหรับงาน AI
% ข้อเท็จจริง (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.
"""
โปรแกรมใช้งาน 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']}")
| เครื่องมือ | ประเภท | ภาษา | การใช้งานหลัก |
|---|---|---|---|
| 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 |
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
การแทนความรู้และตรรกศาสตร์เป็นรากฐานสำคัญของปัญญาประดิษฐ์ ประกอบด้วยหัวข้อหลักดังนี้:
ตรรกศาสตร์เชิงประพจน์ (Propositional Logic)
ตรรกศาสตร์อันดับหนึ่ง (First-Order Logic)
ตัวแทนฐานความรู้ (Knowledge-Based Agents)
เครือข่ายความหมายและกรอบ (Semantic Networks & Frames)
ออนโทโลยี (Ontologies)
| แนวโน้ม | คำอธิบาย |
|---|---|
| Neuro-Symbolic AI | ผสมผสานการเรียนรู้เชิงลึกกับการอนุมานเชิงสัญลักษณ์ |
| Knowledge Graph Embedding | แปลง Knowledge Graphs เป็น vector space |
| Commonsense Reasoning | พัฒนาความสามารถในการใช้ความรู้ทั่วไป |
| Explainable AI | ใช้ตรรกศาสตร์เพื่ออธิบายการตัดสินใจของ AI |
Russell, S., & Norvig, P. (2021). Artificial Intelligence: A Modern Approach (4th ed.). Pearson.
Brachman, R., & Levesque, H. (2004). Knowledge Representation and Reasoning. Morgan Kaufmann.
Baader, F., Calvanese, D., McGuinness, D., Nardi, D., & Patel-Schneider, P. (2007). The Description Logic Handbook (2nd ed.). Cambridge University Press.
Minsky, M. (1975). A Framework for Representing Knowledge. MIT-AI Laboratory Memo 306.
Hayes, P. J. (1979). The Logic of Frames. In Frame Conceptions and Text Understanding (pp. 46-61). De Gruyter.
Stanford Encyclopedia of Philosophy - Logic and Artificial Intelligence
W3C OWL Web Ontology Language
Protégé Documentation
SWI-Prolog Documentation
Stanford CS221: Artificial Intelligence
MIT 6.034: Artificial Intelligence