Universal ("untuk semua") dan existential ("ada satu") adalah quantifier yang mengubah boolean logic menjadi alat penalaran tentang koleksi data — berkaitan langsung dengan all() / any() di Python, list comprehension dengan filter, dan spec/assertion testing.

Setelah di episode 5 kita menguasai logika proposisional — AND, OR, NOT, XOR, NAND, truth table, dan short-circuit evaluation — pada episode ini kita naik level ke logika predikat: logika yang berurusan dengan koleksi objek, bukan satu pernyataan tunggal. Di sinilah quantifier masuk: universal (∀, "untuk semua") dan existential (∃, "ada satu").
Mengapa quantifier penting? Karena dalam programming, kita sering perlu memverifikasi properti terhadap koleksi data — "apakah semua elemen memenuhi kondisi?", "apakah ada setidaknya satu yang memenuhi?", "apakah tepat satu yang unik?". Python menyediakan all() dan any() yang secara langsung merepresentasikan quantifier ini. Memahami logika formal di baliknya membuat kalian bisa menulis validasi yang lebih presisi dan membaca spesifikasi formal dengan lebih percaya diri.
∀x P(x) artinya: "untuk semua x dalam domain, P(x) bernilai benar." Jika ada satu saja yang salah, seluruh pernyataan universal salah.
# Domain: list angka
angka = [2, 4, 6, 8, 10]
# ∃x P(x): "semua angka genap?"
semua_genap = all(x % 2 == 0 for x in angka)
print(f"Semua genap? {semua_genap}") # True
# Tambahkan angka ganjil — hasil berubah
angka_dengan_ganjil = [2, 4, 5, 8, 10]
semua_genap_lagi = all(x % 2 == 0 for x in angka_dengan_ganjil)
print(f"Semua genap? {semua_genap_lagi}") # False — satu counterexample cukupNegasi dari "untuk semua" adalah "ada yang tidak":
icon="iPython" title="Negasi universal"
angka = [2, 4, 5, 8, 10]
# Negasi: ¬∀x P(x) ≡ ∃x ¬P(x)
# "Tidak semua genap" ≡ "Ada yang tidak genap"
tidak_semua_genap = not all(x % 2 == 0 for x in angka)
ada_ganjil = any(x % 2 != 0 for x in angka)
print(f"Tidak semua genap: {tidak_semua_genap}") # True
print(f"Ada ganjil: {ada_ganjil}") # True
print(f"Sama? {tidak_semua_genap == ada_ganjil}") # True — secara logika identik∃x P(x) artinya: "ada setidaknya satu x dalam domain yang membuat P(x) bernilai benar." Cukup satu yang benar, seluruh pernyataan existential benar.
users = [
{"name": "Alice", "role": "admin", "active": True},
{"name": "Bob", "role": "user", "active": False},
{"name": "Charlie", "role": "editor", "active": True},
]
# ∃x: "apakah ada admin aktif?"
ada_admin_aktif = any(u["role"] == "admin" and u["active"] for u in users)
print(f"Ada admin aktif? {ada_admin_aktif}") # True
# ∃x: "apakah ada user yang nonaktif?"
ada_nonaktif = any(not u["active"] for u in users)
print(f"Ada nonaktif? {ada_nonaktif}") # True
# ∃!x: "apakah ada tepat satu admin?" — uniqueness
admin_count = sum(1 for u in users if u["role"] == "admin")
tepat_satu_admin = admin_count == 1
print(f"Tepat satu admin? {tepat_satu_admin}") # TruePerbedaan intuitif antara kedua quantifier:
| Quantifier | Simbol | Python | Kapan Salah | Kapan Benar |
|---|---|---|---|---|
| Universal | ∀ | all() | Satu counterexample | Semua memenuhi |
| Existential | ∃ | any() | Tidak ada yang memenuhi | Setidaknya satu |
| Unique Existential | ∃! | sum() == 1 | 0 atau >1 | Tepat satu |
data = [True, True, True, True]
print(f"all({data}) = {all(data)}") # True — semua True
print(f"any({data}) = {any(data)}") # True — setidaknya satu True
data = [False, True, False, False]
print(f"all({data}) = {all(data)}") # False — ada yang False
print(f"any({data}) = {any(data)}") # True — setidaknya satu True
data = [False, False, False, False]
print(f"all({data}) = {all(data)}") # False — semua False
print(f"any({data}) = {any(data)}") # False — tidak ada TrueNegasi universal dan existential saling berkaitan — De Morgan's law berlaku:
¬∀x P(x) ≡ ∃x ¬P(x) — "tidak semua" ≡ "ada yang tidak"¬∃x P(x) ≡ ∀x ¬P(x) — "tidak ada" ≡ "semua tidak"data = [2, 4, 5, 8, 10]
# Negasi universal → existential
assert not all(x % 2 == 0 for x in data) == any(x % 2 != 0 for x in data)
# Negasi existential → universal
assert not any(x > 100 for x in data) == all(x <= 100 for x in data)
print("De Morgan's law verified!")Quantifier adalah fondasi dari spec-based testing — menulis asumsi tentang data:
def test_user_data(users):
"""Spec: semua user punya id, nama, dan email."""
# ∀ user: user.id is not None
assert all(u.get("id") is not None for u in users), "Semua user harus punya id"
# ∀ user: len(user.name) > 0
assert all(len(u.get("name", "")) > 0 for u in users), "Nama tidak boleh kosong"
# ∀ user: "@" in user.email
assert all("@" in u.get("email", "") for u in users), "Email harus valid"
# ∃ user: user.role == "admin"
assert any(u.get("role") == "admin" for u in users), "Minimal ada satu admin"
print("All specs passed!")
# Data valid
users = [
{"id": 1, "name": "Alice", "email": "alice@test.com", "role": "admin"},
{"id": 2, "name": "Bob", "email": "bob@test.com", "role": "user"},
]
test_user_data(users)Ketika kalian menulis list comprehension dengan filter, kalian sebenarnya menggunakan quantifier secara implisit:
products = [
{"name": "Laptop", "price": 12000000, "stock": 5},
{"name": "Mouse", "price": 150000, "stock": 0},
{"name": "Keyboard", "price": 750000, "stock": 12},
{"name": "Monitor", "price": 3500000, "stock": 0},
{"name": "Webcam", "price": 500000, "stock": 3},
]
# ∃: apakah ada produk dengan harga > 10 juta?
mahal = any(p["price"] > 10_000_000 for p in products)
# ∀: apakah semua produk yang tersedia (stock > 0) harganya < 5 juta?
produk_tersedia = [p for p in products if p["stock"] > 0]
semua_murah = all(p["price"] < 5_000_000 for p in produk_tersedia)
# Filter: hanya produk yang tersedia dan murah
produk_bagus = [
p for p in products
if p["stock"] > 0 and p["price"] < 5_000_000
]
print(f"Ada produk > 10 juta? {mahal}")
print(f"Semua produk tersedia < 5 juta? {semua_murah}")
print(f"Produk bagus: {[p['name'] for p in produk_bagus]}")SQL secara langsung menggunakan quantifier:
-- ∃: apakah ada user yang pernah order?
SELECT EXISTS (SELECT 1 FROM orders);
-- ∀: apakah semua user di tabel roles ada di tabel users?
SELECT NOT EXISTS (
SELECT 1 FROM roles r
WHERE NOT EXISTS (SELECT 1 FROM users u WHERE u.role = r.name)
);
-- IN: ∃x ∈ set
SELECT * FROM users WHERE role IN ('admin', 'editor');Tip
Ketika menulis validasi atau testing, tanyakan diri kalian: apakah saya perlu ∀ (semua harus memenuhi) atau ∃ (setidaknya satu memenuhi)? Menggunakan all() ketika seharusnya any() (atau sebaliknya) adalah bug logika yang sulit dideteksi.
Inti yang harus dibawa pulang:
all() di Python; salah jika ada satu counterexample.any() di Python; benar jika setidak satu memenuhi.all() / any().EXISTS, IN, dan subquery adalah implementasi quantifier dalam database.Di episode 7 selanjutnya kita akan mempelajari sets (himpunan) — operasi union, intersection, difference, dan complement, beserta Venn diagram. Quantifier yang baru kalian kuasai bekerja secara natural dengan himpunan — ∀x ∈ S dan ∃x ∈ S adalah quantifier di atas domain himpunan!