German Research Center for Artificial Intelligence (LT–Lab, DFKI)

ترجمه: احد محمّدي خواجه
E-mail:
ae1359m@gmail.com
دانشجوي كارشناسي ناپيوسته كامپيوتر(تراكتورسازي تبريز)

عناوين متن

زبانهاي برنامه‌نويسيAI، برنامه‌نويسي تابعي ، برنامه‌نويسي تابعي در Lisp ، A- Syntax (نحو) و semantic هاي (معاني) Lisp ، ليست انواع داده ، تعريف توابع جديد ، تعريف ساختارهاي كنترلي ، تعريف توابع بازگشتي ، توابع مرتبه بالا ، ساير زبانهاي برنامه‌نويسي تابعي غير از Lisp ، برنامه‌نويسي منطقي در Prolog ، ساير روشهاي برنامه‌نويسي

واژه نامه
بندهاي برنامه Prolog
شامل مجموعه‌اي از جملات بنام بندها هستند كه براي نشان دادن داده‌ها و برنامه‌ها بكار مي‌روند.
تابع مرتبه بالا تعريف تابعي است كه اجازه مي‌دهد آرگومانها يا مقدار بازگشتي تابع، مقدار توابع باشد. نماد ساختار ليستها اغلب نشان‌دهنده نحوه استفاده از ليست ساختاري داده هستند، كه يك عنصر ليست ممكن است نماد يا ليست ديگر باشد. ليستها ساختاري مركزي Lisp هستند كه براي نشان دادن داده‌ها و برنامه‌ها بكار مي‌روند. بازگشت تكنيكي الگوريتمي براي انجام يك كار است كه يك تابع با بعضي از قسمتهاي كار خودش را فراخواني مي‌كند.
محاسبات نمادين برنامه‌نويسي AI (اساساً) شامل دستكاري نمادها است نه اعداد. اين نمادها مي‌توانند اشياء در جهان و ارتباط بين آن اشياء را نشان دهند- ساختارهاي پيچيده نمادها نياز به دانش ما از جهان دارند. واژه ساختار اساسي داده‌ها در Prolog واژه‌اي است كه مي‌تواند يك ثابت، يك متغير يا يك ساختار باشد. ساختارها موضوعات ريز محاسبات گزاره‌اي را نشان مي‌دهند و شامل يك عملگر نام و يك پارامتر ليست هستند.
زبانهاي برنامه‌نويسي هوش مصنوعي(AI) ابزار اصلي بررسي و ساخت برنامه‌هاي كامپيوتري هستند كه مي‌توانند در شبيه‌سازي فرايندهاي هوشمند مانند يادگيري،‌ استدلال و فهم اطلاعات نمادين بكار بروند. هر چند اخيراً زبان كامپيوتر اصولاً براي استفاده از كامپيوترها براي انجام محاسبات با اعداد طراحي شده بود، اما بزودي دريافتند كه رشته‌اي از بيتها نه تنها اعداد بلكه مي‌توانند اشياي دلخواه را نيز نمايش دهند. عمليات روي ويژه‌گي‌ها يا نمادها مي‌تواند با استفاده از قوانين براي ايجاد، انتساب يا دستكاري نشان داده شود. اين تصور از محاسبات نمادين بعنوان تعريف الگوريتمهايي كه هر نوع اطلاعات را پردازش مي‌كنند و بنابراين مي‌تواند براي شبيه‌سازي هوش انسان بكار برود مناسب است.
بزودي برنامه نويسي با نمادها كه نياز به سطح بالايي از چكيدگي دارند توليد مي‌شوند، غير از امكاناتي كه با زبانهاي برنامه نويسي مخصوص پردازش اعداد ممكن بود مانند فرترن

I-زبانهاي برنامه نويسي AI
در AI خودكار كردن يا برنامه‌نويسي همه جنبه‌هاي شناخت انساني بوسيله بنيادهاي شناخت علمي روشهاي نمادين و غير نمادين AI، پردازش زبان طبيعي، ديد كامپيوتري و سيستمهاي تكامل يا سازگار مطرح مي‌شود. لازم است دامنه مسئله‌هاي خيلي پيچيده در ابتداي مرحله برنامه‌نويسي يك مسئله AI معين، مشخص شود كه كافي نيست. تنها بوسيله تعامل و افزايش اصلاحات خصوصيات بسيار دقيق ممكن است. در حقيقت مسئله‌هاي معمول AI به بسياري از زمينه‌هاي خاص گرايش دارند، بنابراين روشهاي ذهني بايد بوسيله توليد و آزمايش روشها بطور تجربي توسعه يابند(مشهور به نمونه سازي سريع). در اينصورت برنامه‌نويسي AI بطور قابل توجهي با روشهاي استاندارد مهندسي نرم‌افزار متفاوت بوده زيرا برنامه‌نويسي معمولا از يك مشخصات رسمي با جزئيات شروع مي‌شود. در برنامه‌نويسي AI پياده‌سازي در واقع جزئي از پردازش مشخصات مسئله است. به اقتضاي طبيعت مسئله‌هاي AI برنامه‌نويسي AI مزاياي بسياري دارد اگر زبانهاي برنامه نويسي، برنامه‌نويسAI را آزاد بگذارند و در بسياري از ساختارهاي فني محدود نكنند (مانند ساختار انواع داده‌اي جديد سطح پايين، دستيابي دستي به حافظه). ترجيحاً سبك برنامه‌نويسي اعلاني براي استفاده در ساختارهاي پيش‌ساخته داده‌اي سطح بالا(مانند ليستها و درختها) و عمليات(مانند تطبيق الگوها) مناسب است، بنابراين محاسبات نمادين سطح خلاصه‌سازي بيشتري نسبت به آنچه كه با زبانهاي دستوري استاندارد مانند فرترن، پاسكال يا C امكان‌پذير خواهد بود را پشتيباني مي‌كند. البته طبقه‌بندي خلاصه سازي آسان نيست،‌ زيرا تدوين برنامه‌هاي AI روي كامپيوترهاي استاندارد وان نيومن نمي‌تواند به كارآمدي زبانهاي دستوري باشد. هر چند يك مسئله مسلم AI فهم آن است (حداقل جزئيات) امكان دارد با تنظيم مجدد آن به شكل خصوصيات جزئي شده با بكار بردن يك زبان دستوري پياده‌ سازي مجدد شود. با توجه به نيازمنديهاي محاسبات نمادين و برنامه‌نويسي AI دو الگوي جديد برنامه‌نويسي كه به سبك دستوري پيشنهاد مي‌شوند بوجود مي‌‌آيد: سبك برنامه‌نويسي تابعي و منطقي. هر دو بر مبناي رياضيات طرح‌ريزي شده‌اند، يعني نظريه توابع بازگشتي و منطق رسمي. اولين زبان برنامه‌نويسي AI كاربردي كه هنوز هم بطور گسترده استفاده مي‌شود زبان برنامه‌نويسي Lisp است كه در اواخر دهه 1950 توسط جان مك كارتي توسعه يافته است. Lisp برمبناي نظريه توابع رياضي و خلاصه‌سازي Lambda است. تعدادي از كاربردهاي مهم و موثرAI در Lisp نوشته شده است. كه ما بعضي از جزئيات اين زبان برنامه‌نويسي را در اين مقاله شرح خواهيم داد. در اوايل دهه 1970 يك الگوي برنامه‌نويسي جديد بنام برنامه‌نويسي منطقي بر اساس محاسبات گزاره‌اي بوجود آمد. اولين و مهمترين زبان برنامه‌نويسي منطقي Prolog است كه توسط آلن كالمرار، رابرت كوالسكي و فيليپ راسل توسعه يافته است. مسئله‌ها در prolog بصورت حقايق، بديهيات و قوانين منطقي براي استنباط حقايق جديد بيان مي‌شوند. Prolog با قانون رياضي در محاسبات گزاره‌اي و نتايج نظري بدست آمده در زمينه اثبات قضيه خودكار در اواخر دهه 1960 بنا نهاده شده است.


II- برنامه نويسي تابعي
يك تابع رياضي نگاشتي از يك مجموعه (دامنه) به مجموعه ديگر(برد) است. تعريف يك تابع توصيف اين نگاشت است كه يا بطور صريح بوسيله شمارش و يا بطور ضمني بوسيله يك عبارت است. تعريف يك تابع بوسيله نام تابع كه بدنبال آن ليستي از پارامترها در داخل پرانتز قرار دارند و به دنبال آن نيز عبارت توصيفي نگاشت است مشخص مي شود مانند:


آلونسو چارچ توابع بي نام را با استفاده از نمادLambda معرفي مي كند. يك عبارت Lambda پارامترها و نگاشت تابع را با استفاده از عملگر X مشخص مي كند, مانند λ (X)X X X آن خودش تابع است, بنابراين شرح بكار رفته در مثال تابع بي نام با يك آرگومان مشخص است. براي مثال:(λ (X) X X X)(4).
برنامه نويسي در يك زبان تابعي شامل ساختمان تعريف توابع و بكاربردن كامپيوتر براي ارزيابي عبارات است. يعني بكاربردن توابع با آرگومانهاي واقعي. كار اصلي برنامه نويسي پس از ساخت يك تابع براي يك مساله خاص تركيب توابع تعريف شده قبلي با توجه به اصول رياضي است. كار اصلي كامپيوتر ارزيابي توابع فراخواني شده و چاپ حاصل مقادير تابع است. در اين روش كامپيوتر مشابه يك كامپيوتر جيبي معمولي بكار مي رود البته بسيار انعطاف پذيرتر و قدرتمندتر. يك خاصيت برنامه نويسي تابعي اين است كه اگر عبارت به خوبي مقداردهي شود آنگاه ترتيب انجام ارزيابي كامپيوتر در نتايج ارزيابي تاثيري ندارد. بنابراين نتيجه ارزيابي يك عبارت تنها مقدار آن است. بدين معني است كه در يك زبان تابعي ناب اثرات جانبي وجود ندارد. اثرات جانبي در مدل موقعيت هاي حافظه به متغيرها متصل شده اند.بنابراين در يك زبان برنامه نويسي ناب در مفهوم زبانهاي دستوري متغير وجود ندارد. روشهاي اصلي كنترل جريان، بازگشت (تكرار) و عبارات شرطي هستند. اين كاملاً با زبانهاي دستوري در مفهوم اساسي كنترل ترتيب و تكرار متفاوت است. برنامه نويسي تابعي نيز خصوصيات توابع مرتبه بالا را پشتيباني مي كند. تابع مرتبه بالا تعريف تابعي است كه اجازه مي دهد آرگومانها يا مقدار بازگشتي تابع, مقدار توابع باشند. همه اين جوانب با هم مخصوصاً آخري از اصلي ترين مزاياي سبك برنامه نويسي تابعي در برابر سبك برنامه نويسي دستوري هستند. خلاصه برنامه نويسي تابعي سطح بالايي از درجه پيمانه اي بودن را فراهم مي كند. وقتي يك مسئله با تقسيم آن به مجموعه اي از زير مسئله ها تعريف مي شود, موضوع اصلي روشهايي است كه مي توان زير مسئله ها را به يكديگر چسباند. بنابراين براي افزايش قابليت پيمانه اي بودن يك مسئله مفهومي, ابتدا بايد نوع جديدي از چسب در زبان برنامه نويسي فراهم شود- قدرت اصلي برنامه نويسي تابعي .
X يك عدد حقيقي است cube(X) ≡ X X X , where X is a real number.
III- برنامه نويسي تابعي در Lisp
Lisp اولين زبان برنامه نويسي تابعي است: آن براي پشتيباني محاسبات نمادين با استفاده از ليستهاي پيوندي بعنوان ساختار مركزي داده ها ابداع شده بود ( Lisp يعني پردازشگر ليست). جان مك كارتي دريافت كه روشهاي كنترل جريان توابع رياضي (بازگشت و تكرار) وسيله نظري مناسبي براي انجام محاسبات نمادين هستند. علاوه براين مفاهيم خلاصه سازي تابعي و كاربرد تابعي تعريف شده در محاسبات Lambda , سطح بالايي از خلاصه سازي موردنياز براي مسئله هاي AI مشخص شده را فراهم مي كنند.


Lisp در سال 1958 توسط مك كارتي ابداع شد و اولين نگارش محيط برنامه نويسي Lisp در سال 1960 آماده شد كه شامل يك مفسر, يك كامپايلر و مكانيسم تخصيص و بازپسگيري حافظه پويا بود (بعنوان مجموعه فضاي هرز شناخته شده است). يكسال بعد اولين زبان استاندارد با نام Lisp1.5 معرفي شد. پس از آن تعدادي از نسخه ها و محيط هاي برنامه نويسي Lisp توسعه يافته اند. مانند MacLisp، FranzLisp، InterLisp، CommonLisp، Scheme هر چند آنها در بعضي جزئيات خاص متفاوتند ولي هسته Syntax (نحو) و Semantic (معني) آنها اساساً يكسان است. هسته را در جاي ديگر معرفي خواهيم كرد. پر استفاده ترين نسخه‌هاي Lisp ، Common Lisp و scheme هستند. در اين مقاله ما Common Lisp را براي نشان دادن جنبه هاي مختلف Lisp با مثالهاي معمولي انتخاب كرده ايم. هرچند مثالها نيز به راحتي مي توانند در نسخه هاي ديگر Lisp سازگار شوند.
Syntax .A. (نحو) و semantics (معاني) Lisp
1. عبارات نمادين: عناصر نحوي Lisp عبارات نمادين ناميده مي شوند (كه به صورتS-expressionsشناخته شده‌اند). داده ها و توابع (يعني برنامه هاي Lisp ) بصورت عبارات نمادين نشان داده شده اند كه مي توانند اتم ها يا ليست ها باشند. اتم ها كلمه اي شبيه اشيا‌ هستند. اتم‌ها وابسته به نوع كاراكترهايي كه براي شكل دادن يك اتم مجازند مي توانند به انواع مختلفي تقسيم شوند. انواع اصلي عبارتنداز:

Numbers:1 234-43.14159265358979 -7.5 6.02E+23
Symbols:SymbolSym23another-one t false NILBLUE

Strings: ”This is a string””977?” ”setq””He said: \” I’m here.\” ”

توضيح اينكه هرچند نماد خاصي مثل BLUE استفاده مي‌شود چون مفهوم مشخص براي برنامه‌نويسي دارد، اما بزودي Lisp تنها ترتيبي از حروف يا تنها يك نماد است. ليستها بندي شبيه اشياء هستند. يك ليست شامل يك پرانتز باز( دنباله‌اي از اعداد دلخواه كه بوسيله فاصله خالي از هم جدا مي‌شوند) و يك پرانتز بسته هستند. هر عنصر ليست مي‌تواند يك اتم يا ليست باشد. اينها مثالهايي از ليستها هستند:
(This is a list) ((this) ((too))) () (((((((())))))))

(a b c d) (john mary tom) (loves john ?X)


(* (+ 3 4) 8) (append (a b c) (1 2 3))


(defun member (elem list)


(if (eq elem (first list)) T


(member elem (rest list))))

توضيح اينكه در بسياري از مثالها عناصر ليست خود ليستها هستند.چنين ليستهايي، ليستهاي تو در تو ناميده مي‌شوند. در مورد تو در تويي محدوديتي وجود ندارد. براي مثال يكي از قويترين Lisp ها را شرح مي‌دهيم: پيچيده‌ترين اشياء را به راحتي مي‌توان نوشت. تنها چيزي كه در نظر گرفته مي‌شود درستي عدد داخل پرانتزهاست. مهم توضيح اين است كه معني وابسته به يك ليست نمايش ويژه يا اتم در ليست نمايش وارد نمي‌شود. به اين معني كه همه عبارات نمادين كه در بالا توصيف شده است از لحاظ نحو برنامه‌هاي Lisp را اصلاح مي‌كنند ولي الزاماً از لحاظ معني (semantic) برنامه‌ها رااصلاح نمي‌كنند.

حلقه خواندن- محاسبه- چاپ چگونه مي‌تواند مفسر Lisp را فعال كرده و براي محاسبه عبارات نمادين و بنابراين اجراي واقعي برنامه‌هاي Lisp بكار برود؟
مسئله‌‌هاي Prolog بصورت حقايق، بديهيات و قوانين منطقي براي استنباط حقايق جديد بيان مي‌‌ شوند . Prolog با قانون رياضي در محاسبات گزاره‌ اي و ونتايج نظري بدست آمده در زمينه اثبات قضيه خودكار در اواخر دهه1960 بنا شده است. مفسر Lisp در واقع بعنوان يك تابع معمولاً بنام eval و جزئي از هر محيط برنامه‌‌‌نويسي Lisp است تعريف شده است (مانند تابعي كه پيش‌ساخته نام دارد). آن بوسيله فراخواني حلقه خواندن- محاسبه- چاپ در يك سيستم Lisp جاسازي مي‌شود، وقتي يك عبارت نمادين توسط كاربر داده مي‌‌ شود ابتدا به داخل سيستم Lisp خوانده مي‌شود( خواندن هم يك تابع پيش‌ساخته است). سپس مفسر Lisp كه via نام دارد تابع eval را فراخواني مي‌كند تا عبارت نمادين را محاسبه و نتيجه عبارت نمادين را با چاپ در دستگاه كاربر برگرداند ( شگفت‌آورنيست گفتن اينكه چاپ هم يك تابع پيش‌‌ساخته است). وقتي سيستم Lispدر كامپيوتر شروع به اجرا مي‌‌شود اين حلقه خواندن- محاسبه- چاپ بطور خودكار شروع به اجرا كرده و بوسيله علامت ويژه اعلان Lisp در ابتداي خط جديد به كاربر علامت مي‌دهد در اين مقاله ما علامت سئوا ل (?) را به عنوان اعلان Lisp بكار خواهيم برد. براي مثال:
( 4 3 +) ?

هر وقت سيستم Lisp اجرا شود حلقه خواندن- محاسبه- چاپ فعال خواهد بود.
عبارت نمادين ( 4 3 + ) كه بوسيله هكر Lisp وارد شده است بوسيله مفسر Lisp بصورت فراخواني تابع جمع تفسير شده و نتيجه عبارت نمادين در ابتداي خط جديد 7 چاپ مي‌‌شود ارزيابي مفسر Lisp مطابق سه قانون زير انجام مي‌‌شود:


(john mary tom) وابسته است آنگاه ارزيابي *names* آن ليست را نتيجه مي‌دهد. اگر نماد color را به نماد green وابسته كنيم آنگاه green بعنوان مقدار color برگردانده مي‌‌شود.
به بيان ديگر نمادها بعنوان متغيرهايي كه به مقاديري متصل(باند) شده‌اند تفسير مي‌‌شوند.

‌ ولي بطور كل آرگومانها قبل از اينكه توابع مقادير آنها را استفاده كنند ارزيابي مي‌شوند. اولويت ارزيابي ترتيبي از آرگومانها از چپ به راست است. يك آرگو‌مان ممكن است يك اتم يا يك ليست باشد،‌درهر حالت بعنوان يك فراخواني تابع تفيسر شده و مفسر Lisp براي ارزيابي آن فراخواني مي‌شود. براي مثال، ارزيابي زير در سيستم Lisp يك تابع به حساب مي‌آيد:
?(max 4 (min 9 8) 7 5) 2. Semantics (معاني): هسته هر سيستم برنامه‌نويسي Lisp مفسر است كه كارش محاسبه مقدار براي يك عبارات نمادين داده شده است. اين فرآيند ارزيابي نام دارد. نتيجه يا مقدار يك عبارت نمادين، يك عبارت نمادين است. كه بعد از كامل شدن ارزيابي برگردانده شده است. توضيح اينكه در واقع Lispداراي Semantics (معاني) عملياتي است كه با يك تعريف رياضي دقيق از نظريه تابع بازگشتي بدست مي‌آيد. 1- يكساني: يك عدد،‌ يك رشته يا نمادهاي t و nil خودشان را ارزيابي مي‌كنند (بر مي‌گردانند) به اين معني كه ارزش عدد 3،3 و ارزش رشته ”house”، رشته ”house”است. نمادt مقدار t برمي‌گرداند كه به معناي true تفسير مي‌شود وnil ، nil به معني false برمي‌‌گرداند 3- ليستها: هر ليست بعنوان يك فراخواني تابع تفسير مي‌‌شود. مفسر اول ليست دلالت بر تابعي دارد كه بايد براي بقيه عناصر( بالقوه خالي)‌ كه آرگومانهاي آن تابع را نشان مي‌دهند بكار رود. در واقع آرگومانهاي يك تابع قبلا بصورت نمادهاي پيشوندي مشخص مي‌‌شوند. اين مزيت را دارد كه توابع به سادگي مي‌توانند با تعداد دلخواهي آرگومان مشخص و استفاده شوند. ليست خالي ( ) داراي عبارت نمادين nil بعنوان مقدارش مي‌باشد. توضيح اينكه نماد nil در واقع داراي دو معني است: يك نمايش مقدار منطقي false و ديگري نمايش ليست خالي. هر چند ممكن است اين يك بيت فرد بنظر برسد، ولي در واقع در Lisp مشكلي در شناسايي مفهوم nil بكاررفته وجود ندارد.
7 2- نمادها: ارزيابي يك نماد عبارت نمادين مربوط به آن را برمي‌‌‌گرداند. ( چگونگي‌ اش را در زير نشان خواهيم داد) بنابراين اگر ما فرض كنيم نماد‌ *names* به ليست