مولد التوافق الخطي (LCG): كيف يولّد الكمبيوتر أرقامًا "عشوائية"؟
مولد التوافق الخطي (Linear Congruential Generator أو اختصارًا LCG) هو أبسط خوارزمية لتوليد أعداد "شبه عشوائية" داخل الكمبيوتر. الكمبيوتر آلة حتمية لا تعرف العشوائية الحقيقية، لذا يبدأ من رقم واحد تختاره أنت (يُسمى البذرة) ثم يطبّق عليه معادلة حسابية متكرّرة تُنتج سلسلة أرقام تبدو عشوائية رغم أنها محسوبة بالكامل. لهذا نسمّيها "شبه عشوائية" (pseudo-random): لو بدأت من نفس البذرة حصلت على نفس السلسلة تمامًا في كل مرة.
الفكرة كلها تقوم على معادلة واحدة تُطبَّق على الرقم السابق لتخرج الرقم التالي، وهذا ما يجعل LCG سريعًا جدًا وخفيفًا على الذاكرة، ولا يزال يُدرّس في مواد الخوارزميات كنقطة بداية لفهم مولّدات الأرقام.
المعادلة الأساسية
يعمل المولّد وفق العلاقة التالية:
X(n+1) = (a · X(n) + c) mod m
والرموز تعني:
- X(n): الرقم الحالي في السلسلة.
- X(0): البذرة (seed)، وهي نقطة الانطلاق التي تحدّدها أنت.
- a: معامل الضرب (multiplier).
- c: معامل الإضافة (increment).
- m: الموديولوس (modulus)، وهو الحدّ الذي نأخذ باقي القسمة عليه.
عملية mod m (باقي القسمة) هي التي "تلفّ" الأرقام لتبقى دائمًا ضمن المجال بين 0 و m−1، وهي مصدر السلوك الذي يبدو عشوائيًا.
مثال عملي بالأرقام
لنأخذ قيمًا صغيرة لنراها بأعيننا: a = 5، c = 3، m = 16، والبذرة X(0) = 7.
- X(1) = (5 × 7 + 3) mod 16 = 38 mod 16 = 6
- X(2) = (5 × 6 + 3) mod 16 = 33 mod 16 = 1
- X(3) = (5 × 1 + 3) mod 16 = 8 mod 16 = 8
- X(4) = (5 × 8 + 3) mod 16 = 43 mod 16 = 11
وهكذا نحصل على السلسلة 6, 1, 8, 11... بأرقام تبدو غير مترابطة رغم أن كل خطوة محسوبة بدقة. لاحظ أن المجال محصور بين 0 و15 لأن m = 16.
كيف تختار المعاملات؟ (وهنا يقع أغلب المبتدئين في الخطأ)
جودة السلسلة تتوقّف كليًا على اختيار a وc وm. اختيار سيئ يجعل الأرقام تتكرّر بسرعة أو تظهر أنماطًا واضحة. القاعدة العملية التي يستند إليها المبرمجون هي نظرية هَل–دوبيل (Hull–Dobell)، التي تضمن أطول دورة ممكنة (أي أن يمرّ المولّد على كل قيمة من 0 إلى m−1 قبل أن يعيد نفسه) عند تحقّق ثلاثة شروط:
- أن يكون c وm أوليَّين نسبيًا (قاسمهما المشترك الأكبر = 1).
- أن يكون (a − 1) قابلًا للقسمة على كل عامل أوّلي لـ m.
- أن يكون (a − 1) قابلًا للقسمة على 4 إذا كان m قابلًا للقسمة على 4.
عمليًا يُختار m قوةً للعدد 2 (مثل 2³²) لأن باقي القسمة عليه يصبح مجرد اقتطاع للبِتات، وهو أسرع عملية يقوم بها المعالج. ومن أشهر المجموعات الجاهزة القيم a = 1664525 وc = 1013904223 وm = 2³² المأخوذة من مرجع Numerical Recipes.
تحذير من فخ شائع: عندما يكون m قوةً للعدد 2، تكون البِتات المنخفضة (الأقل قيمة) ضعيفة عشوائيًا وتتكرّر بدورة قصيرة جدًا. لذلك لا تأخذ العدد الفردي/الزوجي من آخر بِت، بل استخدم البِتات العليا إذا احتجت مجالًا صغيرًا.
أين يُستخدم LCG؟ ومتى يجب تجنّبه؟
| الاستخدام | مناسب؟ | السبب |
|---|---|---|
| الألعاب والمحاكاة البسيطة | نعم | سريع وخفيف والجودة كافية |
| توزيع عناصر أو اختبارات | نعم | يكفي للأغراض غير الحسّاسة |
| بحوث إحصائية دقيقة | بحذر | قد تظهر ارتباطات خفية بين الأرقام |
| التشفير وكلمات المرور والمفاتيح | لا إطلاقًا | يمكن التنبّؤ به بالكامل بعد رصد عدد قليل من المخرجات |
هذه نقطة جوهرية كثيرًا ما تُذكر خطأً: LCG غير آمن للتشفير. بما أن المعادلة معروفة، يستطيع مهاجم يرى بضعة أرقام من المخرجات أن يستنتج المعاملات ويتنبّأ بكل الأرقام القادمة. لأي استخدام أمني (توليد مفاتيح، رموز تحقّق، كلمات مرور) استعمل مولّدًا آمنًا تشفيريًا (CSPRNG) مثل الدوال المخصّصة للأمان في لغتك مثل secrets في بايثون أو crypto في جافاسكريبت.
للمحاكاة الجادّة والحاجة إلى جودة أعلى، هناك بدائل أفضل مثل Mersenne Twister (المستخدم افتراضيًا في بايثون)، وعائلة xorshift، ومولّد PCG الحديث الذي يبني على فكرة LCG نفسها لكنه يضيف خطوة خلط تحسّن جودة الأرقام بشكل ملحوظ.
الأسئلة الشائعة
هل الأرقام الناتجة عشوائية فعلًا؟ لا، إنها حتمية بالكامل. تُسمّى "شبه عشوائية" لأنها تجتاز اختبارات إحصائية معيّنة لكنها قابلة للتكرار تمامًا عند تثبيت البذرة.
ما فائدة تثبيت البذرة (seed)؟ تثبيت البذرة يجعل النتائج قابلة للتكرار، وهو أمر مفيد جدًا في اختبار البرامج وتصحيح الأخطاء ومقارنة نتائج المحاكاة، لأنك تحصل على نفس السلسلة في كل تشغيل.
ما أقصى طول ممكن للسلسلة قبل أن تكرّر نفسها؟ أقصى دورة ممكنة هي m، وتتحقّق فقط عند استيفاء شروط نظرية هَل–دوبيل. الاختيار السيئ للمعاملات قد يقصّر الدورة إلى بضع خطوات.
هل يصلح LCG لتوليد كلمة مرور قوية؟ لا. لا تستخدمه في أي سياق أمني إطلاقًا، فهو قابل للتنبّؤ. استعمل دائمًا مولّدًا مصمَّمًا للأمان (CSPRNG).