Di artikel terakhir Saya memulai cerita saya tentang komponen pemodelan bahasa hybrid. Ini adalah sekumpulan konsep-objek yang dihubungkan oleh hubungan logis. Saya berhasil berbicara tentang cara utama mendefinisikan konsep, warisan, dan mendefinisikan hubungan di antara mereka. Alasan yang mendorong saya untuk mulai mendesain bahasa hybrid, dan fiturnya, dapat ditemukan di publikasi saya sebelumnya tentang topik ini. Tautan ke mereka dapat ditemukan di akhir artikel ini.
Dan sekarang saya mengusulkan untuk terjun ke dalam beberapa nuansa pemrograman logika. Karena bahasa komponen pemodelan memiliki bentuk logika deklaratif, maka akan diperlukan untuk menyelesaikan masalah seperti mendefinisikan semantik dari operator negasi, memperkenalkan elemen logika tingkat tinggi dan menambahkan kemampuan untuk bekerja dengan variabel logika. Dan untuk melakukan ini, Anda harus berurusan dengan masalah teoretis seperti asumsi keterbukaan / tertutupnya dunia, penyangkalan sebagai penolakan, semantik model yang stabil, dan semantik yang beralasan. Dan juga dengan bagaimana kemungkinan logika tingkat tinggi diimplementasikan dalam bahasa pemrograman logis lainnya.
Mari kita mulai dengan variabel boolean
Dalam kebanyakan bahasa pemrograman logika, variabel digunakan sebagai penunjukan simbolik (placeholder) dari pernyataan arbitrer. Mereka terjadi pada posisi argumen predikat dan menghubungkan predikat satu sama lain. Misalnya, dalam aturan bahasa Prolog berikut, variabel memainkan peran objek X dan Y , dihubungkan oleh relasi: saudara laki-laki , orang tua , laki - laki dan ketidaksamaan:
brothers(X,Y) :- parent(Z,X), parent(Z,Y), male(X), male(Y), X\=Y.
Dalam komponen pemodelan, peran argumen istilah terutama dimainkan oleh atribut konsep:
concept brothers (person1, person2) FROM parent p1 (child = person1), parent p2 (child = person2), male(person: person1), male(person: person2) WHERE p1.parent = p2.parent AND person1 != person2
Mereka bisa diakses dengan namanya secara langsung, seperti di SQL. Meskipun sintaksis yang diusulkan terlihat lebih rumit dibandingkan dengan Prolog, dalam kasus sejumlah besar atribut, opsi ini akan lebih nyaman, karena menekankan struktur objek.
Namun dalam beberapa kasus, akan tetap nyaman untuk mendeklarasikan variabel boolean yang tidak akan disertakan dalam atribut konsep mana pun, tetapi pada saat yang sama digunakan dalam ekspresi relasi. Misalnya, jika subekspresi memiliki bentuk yang kompleks, Anda dapat memecahnya menjadi bagian-bagian komponennya dengan menautkannya ke variabel boolean. Selain itu, jika subekspresi digunakan beberapa kali, Anda dapat mendeklarasikannya hanya sekali dengan mengaitkannya dengan variabel. Dan di masa mendatang, gunakan variabel sebagai ganti ekspresi. Untuk membedakan variabel boolean dari atribut konsep dan variabel komponen komputasi, mari kita putuskan bahwa nama variabel Boolean harus dimulai dengan simbol $ .
Sebagai contoh, kita dapat menganalisis konsep yang menentukan kepemilikan sebuah titik ke sebuah cincin, yang dijelaskan oleh jari-jari eksternal dan internal. Jarak dari titik ke pusat cincin dapat dihitung satu kali, dihubungkan ke variabel, dan dibandingkan dengan jari-jarinya:
relation pointInRing between point p, ring r where $dist <= r.rOuter and $dist >= r.rInner and $dist = Math.sqrt((p.x – r.x) * (p.x – r.x) + (p.y – r.y) * (p.y – r.y))
Pada saat yang sama, jarak ini sendiri memiliki peran tambahan dan tidak akan menjadi bagian dari konsep.
Penyangkalan.
Sekarang mari kita lihat masalah yang lebih kompleks - implementasi operator negasi dalam komponen pemodelan. Sistem pemrograman logika biasanya menyertakan, selain operator negasi boolean, aturan negasi sebagai penolakan. Ini memungkinkan Anda untuk mencetak bukan p jika penurunan p gagal . Dalam sistem representasi pengetahuan yang berbeda, baik makna maupun algoritma aturan inferensi negasi mungkin berbeda.
Pertama, perlu dijawab pertanyaan tentang hakikat sistem pengetahuan ditinjau dari kelengkapannya. Dalam sistem yang menganut "asumsi dunia terbuka" , basis pengetahuan dianggap tidak lengkap, sehingga pernyataan yang hilang dianggap tidak diketahui. Bukan pernyataan pdapat menjadi keluaran hanya jika basis pengetahuan secara eksplisit menyimpan pernyataan bahwa pSalah. Penolakan seperti itu disebut kuat. Pernyataan yang hilang dianggap tidak diketahui, bukan salah. Contoh sistem pengetahuan yang menggunakan asumsi tersebut adalah Semantic WEB. Ini adalah jaringan semantik global yang dapat diakses publik yang dibentuk atas dasar World Wide Web. Informasi di dalamnya, menurut definisi, tidak lengkap - tidak sepenuhnya digital dan diterjemahkan ke dalam bentuk yang dapat dibaca mesin, didistribusikan di antara node yang berbeda dan terus ditambahkan. Misalnya, jika di Wikipedia, dalam sebuah artikel tentang Tim Berners-Lee, pencipta World Wide Web dan penulis konsep Semantic Web, tidak ada yang dikatakan tentang preferensi kulinernya, maka ini tidak berarti bahwa dia tidak memilikinya, artikel itu tidak lengkap.
Asumsi sebaliknya adalah "asumsi bahwa dunia ini tertutup".... Diyakini bahwa dalam sistem seperti itu basis pengetahuannya lengkap, dan pernyataan yang hilang di dalamnya dianggap tidak ada atau salah. Kebanyakan database mengikuti asumsi ini. Jika database tidak memiliki catatan tentang transaksi atau tentang pengguna, maka kami yakin bahwa transaksi seperti itu tidak ada, dan pengguna tidak terdaftar di sistem (setidaknya keseluruhan logika sistem didasarkan pada fakta bahwa mereka tidak ada).
Basis pengetahuan yang lengkap memiliki kelebihan. Pertama, tidak perlu menyandikan informasi yang tidak diketahui - logika dua nilai (benar, salah) sudah cukup daripada tiga nilai (benar, salah, tidak diketahui). Kedua, Anda dapat menggabungkan operator negasi Boolean dan memeriksa turunan pernyataan dari basis pengetahuan menjadi satu operator negasi sebagai penolakan(negasi sebagai kegagalan). Ini akan mengembalikan true tidak hanya jika pernyataan bahwa pernyataan itu salah disimpan, tetapi juga jika tidak ada informasi tentang itu di basis pengetahuan sama sekali. Misalnya,
aturan
p <— not q
akan menyimpulkan bahwa q salah (karena tidak ada pernyataan bahwa itu benar) dan p benar.
Sayangnya, semantik penyangkalan sebagai penolakan tidak begitu jelas dan lebih kompleks dari yang terlihat. Dalam sistem pemrograman logis yang berbeda, maknanya memiliki karakteristik tersendiri. Misalnya, dalam kasus definisi siklik:
p ← not q q ← not p
resolusi SLDNF klasik (SLD + Negasi sebagai Kegagalan) yang digunakan dalam bahasa Prolog akan gagal. Keluaran dari pernyataan p membutuhkan keluaran dari q , dan q - dalam p , prosedur keluaran akan jatuh ke dalam loop tak terbatas. Dalam Prolog, definisi semacam itu dianggap tidak valid dan basis pengetahuannya dianggap tidak konsisten.
Pada saat yang sama, pernyataan ini tidak menjadi masalah bagi kami. Secara intuitif, kita memahami dua aturan ini yang mengatakan bahwa p dan qmemiliki arti yang berlawanan, jika salah satunya benar, maka yang lainnya salah. Oleh karena itu, diharapkan operator negasi sebagai penolakan dapat bekerja dengan aturan tersebut, sehingga konstruksi program logis lebih alami dan dapat dimengerti oleh seseorang.
Selain itu, konsistensi basis pengetahuan tidak selalu dapat dicapai. Sebagai contoh, terkadang definisi aturan sengaja dipisahkan dari fakta sehingga perangkat aturan yang sama dapat diterapkan pada kumpulan fakta yang berbeda. Dalam kasus ini, tidak ada jaminan bahwa aturan akan sesuai dengan semua kemungkinan fakta. Kadang-kadang juga dapat diterima bahwa aturan itu sendiri tidak konsisten, misalnya, jika dibuat oleh pakar yang berbeda.
Kampanye yang paling terkenal, memungkinkan untuk memformalkan kesimpulan logis di bawah definisi siklik dan inkonsistensi program adalah "Semantik berkelanjutan» (semantik model stabil) dan "semantik wajar» (Semantik yang didirikan dengan baik).
Aturan inferensi dengan semantik model persisten didasarkan pada asumsi bahwa beberapa operator negasi dalam suatu program dapat diabaikan jika tidak konsisten dengan program lainnya. Karena terdapat beberapa himpunan bagian yang konsisten dari kumpulan aturan awal, masing-masing dapat ada beberapa solusi. Misalnya, dalam definisi di atas, inferensi bisa dimulai dengan aturan pertama ( p ← bukan q ), buang detik ( q ← bukan p ) dan dapatkan solusi {p, bukan q} . Kemudian lakukan hal yang sama untuk yang kedua dan dapatkan {q, bukan p} . Solusi keseluruhan akan menjadi sekumpulan solusi alternatif yang digabungkan. Misalnya, dari aturan:
person(alex) alive(X) ←person(X) male(X) ←person(X) AND NOT female(X) female(X) ←person(X) AND NOT male(X)
kita dapat menampilkan dua opsi jawaban: {person (alex), hidup (alex), pria (alex)} dan {person (alex), hidup (alex), wanita (alex)} .
Semantik yang masuk akal dimulai dengan asumsi yang sama, tetapi berusaha menemukan satu solusi parsial umum yang memenuhi semua subset aturan konsensual alternatif. Solusi parsial berarti nilai "benar" atau "salah" akan ditampilkan hanya untuk sebagian fakta, dan nilai sisanya akan tetap tidak diketahui. Jadi, dalam deskripsi fakta dalam program, logika dua nilai digunakan, dan dalam proses inferensi, tiga nilai. Untuk aturan yang dipertimbangkan di atas, arti dari p dan qtidak akan diketahui. Tapi, misalnya, untuk
p ← not q q ←not p r ← s s
kita dapat dengan yakin menyimpulkan bahwa r dan s adalah benar, meskipun p dan q tetap tidak diketahui.
Misalnya, dari contoh alex, kita mungkin menyimpulkan {person (alex), hidup (alex)} , sedangkan pernyataan male (alex) dan female {alex} tetap tidak diketahui.
Dalam SQL, negasi boolean ( TIDAK ) dan pemeriksaan derivabilitas ( TIDAK ADA) dipisahkan. Operator ini berlaku untuk jenis argumen yang berbeda: NOT membalikkan nilai boolean, dan EXISTS / NOT EXISTS memeriksa kekosongan pada hasil kueri bertingkat, jadi tidak masuk akal untuk menggabungkannya. Semantik operator negasi dalam SQL sangat sederhana dan tidak dirancang untuk bekerja dengan kueri tidak konsisten yang rekursif atau kompleks; dengan keahlian SQL khusus, kueri dapat dikirim ke rekursi tak terbatas. Tetapi konstruksi logis yang kompleks jelas berada di luar cakupan tradisional SQL, sehingga tidak memerlukan semantik operator negasi yang canggih.
Sekarang mari kita coba memahami semantik operator negasi dari komponen pemodelan bahasa hybrid yang dirancang.
Pertama, komponen pemodelan dirancang untuk mengintegrasikan sumber data yang berbeda. Mereka bisa sangat bervariasi dan bisa lengkap atau tidak lengkap. Oleh karena itu, operator pemeriksa derivasi sangat dibutuhkan.
Kedua, bentuk konsep komponen pemodelan lebih mirip dengan kueri SQL daripada aturan pemrograman logika. Konsep ini juga memiliki struktur yang kompleks, sehingga pencampuran dalam satu operator negasi Boolean dan pengecekan penurunan konsep tidak masuk akal. Negasi boolean hanya masuk akal untuk diterapkan pada atribut, variabel, dan hasil ekspresi - bisa salah atau benar. Lebih sulit untuk menerapkannya pada suatu konsep, mungkin terdiri dari atribut yang berbeda dan tidak jelas mana di antara mereka yang harus bertanggung jawab atas kesalahan atau kebenaran konsep secara keseluruhan. Konsep tersebut dapat diturunkan dari data awal secara keseluruhan, dan bukan atribut individualnya. Tidak seperti SQL, di mana struktur tabelnya tetap, struktur konsep bisa fleksibel, konsep mungkin tidak memiliki atribut yang diperlukan dalam komposisinya sama sekali,oleh karena itu, Anda juga perlu memeriksa keberadaan atribut tersebut.
Oleh karena itu, masuk akal untuk memperkenalkan operator terpisah untuk setiap jenis negasi yang tercantum di atas. Kepalsuan atribut dapat diperiksa menggunakan operator Boolean NOT tradisional , apakah konsep berisi atribut menggunakan fungsi DEFINED bawaan , dan hasil menyimpulkan konsep dari data asli menggunakan fungsi EXISTS . Tiga operator terpisah lebih dapat diprediksi, dimengerti, dan lebih mudah digunakan daripada operator negation-as-failure yang kompleks. Jika perlu, mereka dapat digabungkan menjadi satu operator dengan satu cara atau lainnya yang masuk akal untuk setiap kasus tertentu.
Ketiga, pada saat ini, komponen pemodelan dilihat sebagai alat untuk membuat ontologi tingkat aplikasi kecil. Bahasanya tidak mungkin membutuhkan ekspresi logis khusus dan aturan inferensi canggih yang dapat mengatasi definisi rekursif dan inkonsistensi logis dari program. Oleh karena itu, penerapan aturan inferensi kompleks yang didasarkan pada semantik model persisten atau semantik yang diarde tampaknya tidak disarankan, setidaknya pada tahap ini. Resolusi SLDNF klasik sudah cukup.
Sekarang mari kita lihat beberapa contoh.
Suatu konsep dapat diberi konotasi negatif jika atribut tertentu memiliki makna yang menunjukkannya. Negasi atribut memungkinkan Anda menemukan entitas seperti itu secara eksplisit:
concept unfinishedTask is task t where not t.completed
Fungsi pemeriksaan ambiguitas atribut akan mudah dilakukan jika entitas konsep dapat memiliki struktur yang berbeda:
concept unassignedTask is task t where not defined(t.assignedTo) or empty(t.assignedTo)
Fungsi memeriksa deducibility sebuah konsep tidak tergantikan saat bekerja dengan definisi rekursif dan struktur hierarki:
concept minimalElement is element greater where not exists(element lesser where greater.value > lesser.value)
Dalam contoh ini, pemeriksaan keberadaan item yang lebih kecil dilakukan sebagai subkueri. Saya berencana untuk mempertimbangkan secara rinci pembuatan kueri bersarang di publikasi berikutnya.
Elemen logika orde tinggi
Dalam logika orde pertama, variabel hanya dapat mencocokkan kumpulan objek dan hanya muncul pada posisi argumen predikat. Dalam logika tingkat tinggi, mereka juga bisa sesuai dengan kumpulan relasi dan muncul di posisi nama predikat. Dengan kata lain, logika orde pertama memungkinkan kita untuk membuat pernyataan bahwa beberapa relasi benar untuk semua atau beberapa objek. Dan logika tingkat tinggi adalah untuk menggambarkan hubungan antar hubungan.
Misalnya, kita dapat membuat pernyataan bahwa beberapa orang adalah saudara laki-laki, saudara perempuan, anak atau orang tua, paman atau bibi, dll.:
Brother(John, Joe). Son(John, Fred). Uncle(John, Alex).
Tetapi untuk membuat pernyataan hubungan, dalam logika urutan pertama, kita perlu membuat daftar semua pernyataan di atas, menggabungkannya menggunakan operasi OR:
ⱯX,ⱯY(Brother(X, Y) OR Brother(Y, X) OR Son(X, Y) OR Son(Y, X) OR Uncle(X, Y) OR Uncle(Y, X) → Relative(X, Y)).
Logika orde kedua memungkinkan Anda membuat pernyataan tentang pernyataan lain. Misalnya, seseorang dapat langsung menyatakan bahwa hubungan saudara laki-laki, saudara perempuan, orang tua dan anak, paman dan keponakan adalah hubungan kekerabatan:
RelativeRel(Brother). RelativeRel(Son). RelativeRel(Uncle). ⱯX,ⱯY(ⱻR(RelativeRel(R) AND (R(X, Y) OR R(Y, X))) → Relative(X, Y)).
Kami berpendapat bahwa jika untuk setiap X dan Y ada beberapa relasi R , yang merupakan relasi antara kerabat RelativeRel , dan X dan Y memenuhi relasi ini, maka X dan Y adalah kerabat. Argumen relasi bisa berupa relasi lain, dan variabel bisa diganti dengan nama relasi.
Logika orde ketiga memungkinkan Anda membangun pernyataan tentang pernyataan tentang pernyataan, dan seterusnya, logika orde tinggi- tentang pernyataan dari setiap tingkat bersarang. Logika tingkat tinggi jauh lebih ekspresif, tetapi juga jauh lebih kompleks. Dalam praktiknya, sistem pemrograman logis hanya mendukung beberapa elemennya, yang terutama terbatas pada penggunaan variabel dan ekspresi arbitrer pada posisi predikat.
Dalam Prolog, elemen logika semacam itu diimplementasikan menggunakan beberapa meta-predikat bawaan, yang argumennya merupakan predikat lain. Yang utama adalah panggilan predikat yang memungkinkan Anda menambahkan predikat secara dinamis ke daftar target aturan saat ini. Argumen pertamanya diperlakukan sebagai tujuan, dan sisanya sebagai argumennya. Prolog akan mencari basis pengetahuan untuk predikat yang cocok dengan argumen pertama dan menambahkannya ke daftar target saat ini. Contoh dengan kerabat akan terlihat seperti ini:
brother(john, jack). sister(mary, john). relative_rel(brother). relative_rel(sister). relative(X, Y) :- relative_rel(R), (call(R, X, Y); call(R, Y, X)).
Prolog juga mendukung predikat findall (Template, Goal, Bag) , bagof (Template, Goal, Bag) , setof (Template, Goal, Set) , dll., Yang memungkinkan Anda menemukan semua solusi goal Goal yang sesuai dengan template Template dan menyatukan (link) daftar mereka dengan hasil Bag (atau Set ). Prolog memiliki predikat bawaan current_predicate , klausa, dan lainnya untuk menemukan predikat di basis pengetahuan. Anda juga dapat memanipulasi predikat dan atributnya di basis pengetahuan - menambah, menghapus, dan menyalinnya.
Bahasa HiLog mendukung logika urutan yang lebih tinggi pada tingkat sintaks. Alih-alih meta-predikat khusus, ini memungkinkan istilah arbitrer (seperti variabel) untuk digunakan secara langsung dalam posisi nama predikat. Aturan untuk menentukan kerabat akan berbentuk:
relative(X, Y) :- relative_rel(R), (R(X, Y); R(Y, X)).
Sintaks ini lebih deklaratif, ringkas, mudah dipahami, dan natural dibandingkan dengan Prolog. Pada saat yang sama, HiLog tetap merupakan varian sintaksis Prolog, karena semua konstruksi sintaksis HiLog dapat diubah menjadi ekspresi logika urutan pertama menggunakan panggilan meta-predikat .
HiLog dianggap memiliki sintaks urutan yang lebih tinggi tetapi semantik urutan pertama . Artinya, saat membandingkan variabel yang merepresentasikan aturan atau fungsi, hanya namanya yang diperhitungkan, bukan implementasinya. Ada juga bahasa yang mendukung semantik tingkat tinggi, seperti λ-Prolog, yang memungkinkan untuk terlibat dalam proses inferensi juga implementasi aturan dan fungsi. Tapi logika seperti itu dan algoritma inferensi jauh lebih rumit.
Sekarang mari beralih ke fungsionalitas logika tingkat tinggi dari komponen pemodelan . Untuk sebagian besar tugas pemrograman meta praktis, Prolog dan HiLog sudah cukup. HiLog memiliki sintaks yang lebih alami, jadi masuk akal untuk menganggapnya sebagai dasar. Untuk dapat menggunakan ekspresi arbitrer pada posisi nama konsep dan atributnya serta untuk membedakannya dari variabel, pemanggilan fungsi, dan konstruksi lainnya, kami memperkenalkan operator khusus untuk menentukan nama secara dinamis :
< >
Ini memungkinkan Anda mengevaluasi nilai ekspresi dan menggunakannya sebagai nama konsep, alias, atau nama atribut, bergantung pada konteksnya. Jika operator ini menggantikan nama konsep di bagian FROM dan nilai ekspresinya ditentukan, maka semua konsep dengan nama yang ditentukan akan ditemukan dan pencarian logis dilakukan untuknya:
concept someConcept ( … ) from conceptA a, <a.conceptName> b where …
Jika nilai ekspresi tidak ditentukan, misalnya, ekspresi adalah variabel boolean yang tidak terkait dengan nilai , maka prosedur akan menemukan semua konsep yang sesuai dan mengaitkan nilai variabel dengan namanya:
concept someConcept is <$conceptName> where …
Kita dapat mengatakan bahwa dalam konteks bagian FROM , operator untuk menentukan nama memiliki semantik logika .
Selain itu, operator <> dapat digunakan dan klausa WHERE pada posisi nama alias konsep atau nama atribut:
concept someConcept ( … ) from conceptA a, conceptB b where conceptB.<a.foreignKey> = a.value ...
Ekspresi di klausa WHERE bersifat deterministik, yaitu, tidak menggunakan penelusuran logis untuk menemukan nilai yang tidak diketahui untuk argumennya. Ini berarti ekspresi conceptB. <A.foreignKey> = a.value akan dievaluasi hanya setelah entitas dari konsep a ditemukan , dan atribut foreignKey dan nilainya dikaitkan dengan nilai. Oleh karena itu, kita dapat mengatakan bahwa dalam konteks klausa FROM , pernyataan nama memiliki semantik fungsional .
Mari pertimbangkan beberapa kemungkinan aplikasi logika orde tinggi.
Contoh paling jelas di mana logika tingkat tinggi akan nyaman adalah penyatuan di bawah satu nama dari semua konsep yang memenuhi kondisi tertentu. Misalnya memiliki atribut tertentu. Jadi konsep titik bisa dianggap semua konsep yang menyertakan koordinat x dan y :
concept point is <$anyConcept> a where defined(a.x) and defined(a.y)
Pencarian Boolean akan mengikat variabel $ anyConcept dengan semua nama konsep yang dideklarasikan (kecuali tentu saja) yang memiliki atribut koordinat.
Contoh yang lebih kompleks adalah mendeklarasikan hubungan umum yang berlaku untuk banyak konsep. Misalnya, hubungan orang tua-anak transitif antara konsep:
relation ParentRel between <$conceptName> parent, <$conceptName> child where defined(parent.id) and defined(child.parent) and ( parent.id = child.parent or exists( <$conceptName> intermediate where intermediate.parent = parent.id and ParentRel(intermediate, child) ))
Variabel $ conceptName digunakan di ketiga konsep induk, anak, dan perantara, yang berarti namanya harus sama.
Logika tingkat tinggi membuka kemungkinan untuk pemrograman generik dalam arti bahwa Anda dapat membuat konsep dan hubungan umum yang dapat diterapkan ke banyak konsep yang memenuhi kondisi tertentu tanpa terikat pada nama spesifiknya.
Selain itu, substitusi nama dinamis akan nyaman dalam kasus di mana atribut dari satu konsep adalah referensi ke nama konsep lain atau atributnya, atau ketika data sumber tidak hanya berisi fakta, tetapi juga strukturnya. Misalnya, data sumber bisa menyertakan deskripsi skema dokumen XML atau tabel dalam database. Data asli juga dapat mencakup informasi tambahan tentang fakta, misalnya tipe data, format atau nilai default, kondisi validasi atau beberapa aturan. Selain itu, data awal dapat mendeskripsikan model dari sesuatu, dan komponen pemodelan akan bertanggung jawab untuk membangun metamodel. Bekerja dengan teks bahasa alami juga mengasumsikan bahwa data sumber tidak hanya mencakup pernyataan, tetapi juga pernyataan tentang pernyataan.Dalam semua kasus ini, logika tingkat pertama tidak akan cukup dan diperlukan bahasa yang lebih ekspresif.
Sebagai contoh sederhana, pertimbangkan kasus ketika data menyertakan beberapa objek, serta aturan untuk memvalidasi atribut objek ini sebagai entitas terpisah:
fact validationRule {objectName: “someObject”, attributeName: “someAttribute”, rule: function(value) {...}}
Hasil validasi dapat digambarkan dengan konsep sebagai berikut:
concept validationRuleCheck ( objectName = r.objectName, attributeName = r.attrName, result = r.rule(o.<r.attrName>) ) from validationRule r, <r.objectName> o where defined(o.<r.attrName>)
Logika tingkat tinggi membuka beberapa kemungkinan yang cukup menarik untuk pemrograman umum dan meta. Kami hanya dapat mempertimbangkan ide umumnya. Area ini cukup kompleks dan membutuhkan penelitian yang mendalam di masa depan. Baik dari sudut pandang memilih desain bahasa yang nyaman, dan masalah kinerjanya.
kesimpulan
Dalam proses mengerjakan komponen pemodelan, saya harus berurusan dengan masalah pemrograman logika yang agak spesifik, seperti bekerja dengan variabel boolean, semantik operator negasi, dan elemen logika tingkat tinggi. Jika semuanya ternyata cukup sederhana dengan variabel, maka tidak ada pendekatan tunggal yang mapan untuk implementasi operator negasi dan logika tingkat tinggi, dan ada beberapa solusi yang memiliki karakteristik, kelebihan dan kekurangan mereka sendiri.
Saya mencoba memilih solusi yang mudah dipahami dan praktis dalam praktiknya. Saya lebih suka membagi operator negasi monolitik sebagai penolakan menjadi tiga operator negasi Boolean yang terpisah, memeriksa deducibility sebuah konsep dan keberadaan atribut dalam suatu objek. Jika perlu, ketiga operator ini dapat digabungkan untuk mendapatkan semantik negasi yang diperlukan untuk setiap kasus tertentu. Untuk aturan negasi inferensi, saya memutuskan untuk menggunakan resolusi SLDNF standar sebagai dasar. Meskipun tidak mampu menangani pernyataan rekursif yang tidak konsisten, jauh lebih mudah untuk memahami dan menerapkan daripada alternatif yang lebih canggih seperti semantik model persisten atau semantik beralasan.
Logika urutan yang lebih tinggi diperlukan untuk umum dan meta-pemrograman. Yang saya maksud dengan pemrograman generik adalah kemampuan untuk membangun konsep baru dari berbagai macam konsep anak tanpa terikat pada nama spesifik dari konsep anak tertentu. Yang saya maksud dengan meta-pemrograman adalah kemampuan untuk menggambarkan struktur beberapa konsep dengan bantuan konsep lain. Saya memutuskan untuk menggunakan bahasa HiLog sebagai model untuk elemen logika tingkat tinggi dari komponen pemodelan. Ini memiliki sintaks yang fleksibel dan nyaman yang memungkinkan Anda menggunakan variabel pada posisi nama predikat, serta semantik yang sederhana dan jelas.
Artikel berikutnya yang saya rencanakan untuk meminjam dari dunia SQL: kueri dan agregasi bersarang. Saya juga akan berbicara tentang jenis konsep lain yang tidak menggunakan inferensi, tetapi entitas dihasilkan secara langsung menggunakan fungsi yang diberikan. Dan bagaimana Anda dapat menggunakannya untuk mengubah tabel, array, dan array asosiatif ke dalam format objek dan memasukkannya ke dalam proses inferensi logis (dengan analogi dengan operasi SQL UNNEST, yang mengubah array ke format tabel).
Teks lengkap dalam gaya ilmiah dalam bahasa Inggris tersedia di sini .
Tautan ke publikasi sebelumnya:
Merancang bahasa pemrograman multi-paradigma. Bagian 1 - Untuk apa ini?
Kami merancang bahasa pemrograman multi-paradigma. Bagian 2 - Perbandingan pembangunan model di PL / SQL, LINQ dan GraphQL Kami
merancang bahasa pemrograman multi-paradigma. Bagian 3 - Tinjauan bahasa representasi pengetahuan Kami
merancang bahasa pemrograman multi-paradigma. Bagian 4 - Konstruksi Dasar Bahasa Pemodelan