ما معنى Pseudo-Random Number Generator في الخوارزميات؟ شرح مبسّط للمولد شبه العشوائي
مولّد الأرقام شبه العشوائية (Pseudo-Random Number Generator أو اختصاراً PRNG) هو خوارزمية رياضية تُنتج سلسلة أرقام تبدو عشوائية لكنها في الحقيقة محسوبة بالكامل من قيمة بداية تُسمى البذرة (seed). كلمة "شبه" هنا هي المفتاح: لا توجد عشوائية حقيقية داخل الحاسوب، بل عملية حسابية حتمية إذا عرفت مدخلها استطعت التنبؤ بكل مخرجاتها. لهذا السبب، إذا أعطيت المولّد نفس البذرة، حصلت على نفس السلسلة تماماً في كل مرة وعلى أي جهاز.
هذا السلوك ليس عيباً بل ميزة مقصودة، وهو ما يجعل الـ PRNG حجر أساس في الخوارزميات وهياكل البيانات، من ترتيب القوائم إلى المحاكاة والتشفير.
لماذا يُسمى "شبه" عشوائي؟
الحاسوب جهاز حتمي: يعطي نفس النتيجة لنفس المدخلات. أما العشوائية الحقيقية فتحتاج مصدر "ضوضاء" فيزيائي (حرارة، توقيت نقرات، تشويش إلكتروني). المولّد شبه العشوائي يتحايل على ذلك بمعادلة تأخذ الرقم الحالي وتنتج الرقم التالي، فتظهر سلسلة موزّعة بشكل جيد ويصعب على العين تمييز نمطها، لكنها مكرَّرة ومحدّدة سلفاً.
خاصيتان مهمتان لكل مولّد:
- الدورة (Period): عدد الأرقام قبل أن تبدأ السلسلة بتكرار نفسها. المولّدات الجيدة لها دورة هائلة.
- جودة التوزيع: أن تكون الأرقام منتشرة بالتساوي بلا تحيّز واضح.
كيف يعمل عبر البذرة (seed)
الفكرة أبسط مما تبدو. تبدأ بقيمة أولية (البذرة)، ثم تطبّق معادلة تحويل بشكل متكرر:
- اختر بذرة ابتدائية، مثلاً من ساعة النظام أو رقم تحدده يدوياً.
- مرّر البذرة عبر معادلة المولّد لإنتاج الرقم الأول.
- استخدم مخرجات هذه الخطوة كمدخل للخطوة التالية، وهكذا.
- كرّر لإنتاج السلسلة كاملة.
من أشهر العائلات التاريخية المولّد الخطي التطابقي (LCG) لبساطته، وMersenne Twister الذي كان الافتراضي في بايثون ولغات كثيرة، وحديثاً عائلات أسرع وأفضل مثل PCG وxoshiro/xoroshiro، بل أضافت جافا منذ الإصدارات الأخيرة واجهة RandomGenerator تتيح اختيار خوارزميات محدثة بدل المولّد القديم.
نصيحة عملية: تثبيت البذرة يدوياً (seed) ليس ترفاً. إنه ما يجعل نتائج تجربتك أو اختباراتك قابلة لإعادة الإنتاج؛ يعيد زميلك تشغيل الكود فيحصل على نفس الأرقام بالضبط، وهو أمر حاسم في التصحيح والأبحاث العلمية.
PRNG مقابل المولّد الحقيقي والمولّد الآمن تشفيرياً
الخلط بين هذه الأنواع الثلاثة هو الفخّ الأكبر. الجدول التالي يوضح الفرق:
| المعيار | PRNG عادي | مولّد آمن تشفيرياً (CSPRNG) | مولّد حقيقي (TRNG) |
|---|---|---|---|
| المصدر | معادلة + بذرة | معادلة قوية + بذرة عالية الإنتروبيا | ضوضاء فيزيائية |
| قابلية التنبؤ | ممكنة إذا عُرفت البذرة | يُصعّب التنبؤ عملياً | غير قابلة للتنبؤ |
| السرعة | سريع جداً | أبطأ قليلاً | الأبطأ عادة |
| الاستخدام | محاكاة، ألعاب، خوارزميات | كلمات مرور، مفاتيح، رموز | توليد مفاتيح حساسة |
القاعدة الذهبية: لا تستخدم مولّداً عادياً في أي شيء أمني. لتوليد كلمة مرور أو رمز تحقق أو مفتاح تشفير استخدم الأدوات المخصّصة: secrets في بايثون، أو SecureRandom في جافا، أو crypto.randomBytes في Node.js. المولّد العادي سريع لكنه قابل للتخمين لمن يعرف البذرة أو يراقب مخرجاته.
أين يظهر في الخوارزميات وهياكل البيانات
هنا تكمن قيمته الحقيقية في هذا المجال تحديداً:
- الترتيب العشوائي: في QuickSort يُختار العنصر المحوري عشوائياً لتفادي أسوأ الحالات وتحسين الأداء المتوسط.
- الخلط (Shuffling): خوارزمية Fisher-Yates لخلط قائمة بشكل عادل تعتمد كلياً على مولّد جيد.
- هياكل بيانات احتمالية: مثل قوائم التخطّي (Skip Lists) والأشجار العشوائية (Treaps) وفلاتر Bloom، التي توازن بين السرعة والذاكرة عبر قرارات عشوائية.
- الخوارزميات الاحتمالية: طرق مونت كارلو ولاس فيغاس لحل مسائل يصعب حلها بدقة تامة.
- المحاكاة والاختبار: توليد بيانات اختبار ضخمة أو نمذجة أنظمة واقعية.
أخطاء شائعة يقع فيها المبتدئون
- انحياز باقي القسمة (Modulo bias): تقليص المجال بـ
rand() % nيجعل بعض الأرقام أكثر ظهوراً من غيرها. استخدم دوال المجال المخصّصة في لغتك بدلاً من ذلك. - بذرة ضعيفة: الاعتماد على الوقت وحده كبذرة يجعل السلسلة متوقعة، وقد يعطي بذرتين متطابقتين لعمليتين انطلقتا في نفس اللحظة.
- إساءة استخدام المولّد الأمني: إما استخدام مولّد عادي في التشفير (خطر)، أو استخدام المولّد الأمني البطيء في محاكاة ضخمة (هدر للأداء). لكل مكان أداته.
الأسئلة الشائعة
هل الأرقام "شبه العشوائية" عشوائية فعلاً؟ لا. هي محسوبة بالكامل من البذرة، لكنها موزّعة جيداً بحيث تبدو عشوائية لمعظم الاستخدامات غير الأمنية.
لماذا أحصل على نفس الأرقام عند كل تشغيل؟ لأنك على الأرجح تستخدم نفس البذرة الثابتة. غيّر البذرة (أو اتركها تُشتق من مصدر متغيّر) للحصول على سلسلة مختلفة، أو ثبّتها عمداً إذا أردت نتائج قابلة للتكرار.
هل يصلح PRNG لتوليد كلمات مرور؟
لا. استخدم مولّداً آمناً تشفيرياً (CSPRNG) مثل secrets أو SecureRandom؛ المولّد العادي قابل للتخمين.
ما الفرق بين البذرة والدورة؟ البذرة هي نقطة البداية التي تحدد أي سلسلة ستُنتج، أما الدورة فهي طول السلسلة قبل أن تعيد تكرار نفسها.