حول المشروع (شرح علمي تفصيلي)
هذه الصفحة تُوثّق الفكرة العلمية للنظام وتحويله من MATLAB إلى نظام ويب، وتشرح بالتفصيل آلية عمل خدمات الحساب (ANFIS/XAI) مع المراجع.
0) الفكرة العلمية للمشروع
ANFIS + XAIيبني المشروع نظاماً لتقدير كلفة صيانة الطرق اعتماداً على نموذج ANFIS (Adaptive Neuro-Fuzzy Inference System) من نوع Sugeno FIS، ثم يضيف طبقة تفسير (XAI) لتوضيح “لماذا” أعطى النموذج هذه النتيجة، وليس فقط “كم” هي الكلفة.
نموذج ANFIS قُدّم أساساً بواسطة Jang (1993) كنظام يدمج الشبكات العصبية مع منطق ضبابي (FIS) باستخدام تعلم هجين (Hybrid Learning) لبناء mapping بين المدخلات والمخرجات انطلاقاً من بيانات تدريب وقواعد if-then. أمّا Sugeno FIS فهو مناسب للنمذجة لأنه ينتج مخرجات على شكل دوال (غالباً خطية) في consequents مما يدعم interpolation داخل فضاء المدخلات.
1) شرح HTS Service بالتفصيل
HTSفي هذا المشروع، HTS ليس اسماً لمعيار عالمي جاهز، بل هو “Proxy” هندسي (مؤشر بديل) لشدة الظروف الحرارية عبر الزمن. الفكرة: نجمع عدد الأيام شديدة الحرارة (فوق 40°C) خلال نافذة زمنية تمثل عمر الرصف قبل تاريخ الصيانة. كلما زاد التعرض الحراري عبر السنوات، زادت احتمالية تدهور خصائص الأسفلت (مثل التخدد rutting والتشوه).
- • pavementAgeCode: كود عمر الرصف (1/2/3).
- • maintenanceDate: تاريخ الصيانة (نستخرج منه سنة الصيانة).
- • HeatDay table: مخزن سنوي days_above_40.
نحسب سنة البداية startYear ثم نجمع days_above_40 من (startYear + 1) إلى maintenanceYear:
startYear = maintenanceYear - yearsSpan
HTS = Σ_{y = startYear + 1 إلى maintenanceYear} days_above_40(y)
هذا يعادل منطق Laravel: whereBetween(year, [startYear+1, maintenanceYear]) ثم sum(days_above_40).
لأن مصادر بحثية تشير إلى أنه عند تجاوز الحرارة المحيطة 40°C قد تصل حرارة سطح الرصف إلى نطاق 65–75°C، وهذا يرفع مخاطر التخدد (rutting) والتشوه وانخفاض قدرة التحمل. لذلك “عدد الأيام فوق 40” يعد مؤشراً مبسطاً لكن ذا معنى لشدة التعرض الحراري عبر الزمن، خصوصاً لمناخ العراق/كربلاء.
- • مرجع يذكر نطاق 65–75°C عند >40°C ambient وارتباطه بالـ rutting. — MDPI (2025)
- • وصف evalfis/منطق تقييم FIS (يهمنا لأن HTS يدخل لاحقاً للـ ANFIS). — MathWorks evalfis
تنويه بحثي: HTS هنا Proxy مدروس وليس “اسم معيار عالمي”. الهدف: تمثيل شدة المناخ بحرارة/زمن بشكل رقمي قابل للإدخال للنموذج.
2) شرح AnfisService (حساب الكلفة) بالتفصيل العلمي
ANFISهذه الخدمة هي قلب المشروع: تنفّذ نفس pipeline الذي كان موجوداً في MATLAB. الفكرة الأساسية: (1) نُجري تحويلات على المدخلات (Log + Normalization) لتصبح مناسبة للنموذج، (2) نقيّم نظام Sugeno FIS (evalfis concept) لإنتاج yNorm، (3) نرجع yNorm إلى نطاقه الأصلي (Reverse normalization) ثم نُطبّق inverse log لإخراج الكلفة بالدينار.
نستخدم log10(x + 1) لتقليل تشتت القيم الكبيرة وتقريب التوزيع (تقليل skew) ولتحسين الاستقرار العددي قبل التطبيع والتقييم داخل النموذج. هذا شائع عندما تكون قيم المدخلات واسعة المدى.
x_log = log10(x + 1)
ملاحظة تنفيذية: الدالة log10_safe تحمي من قيم سالبة غير متوقعة حتى لا يتعطل التنفيذ.
بعد log، نطبّق تطبيعاً مطابقاً لإعدادات MATLAB (PS_in). في MATLAB، mapminmax يستطيع أن يعيد Process Settings (PS) ويُعاد استخدام نفس PS لاحقاً لتطبيع بيانات جديدة بنفس الطريقة، وهذا يضمن أن بيئة PHP تطبّق نفس التحويلات تماماً.
- • PS_in.gain / xoffset / ymin / yrange تُستخدم لتحويل كل عنصر إلى النطاق المُستهدف.
- • أنت خزّنت هذه القيم في config(anfis.ps_in.*) لضمان الثبات.
توثيق mapminmax في MathWorks يوضح فكرة تطبيع البيانات وإرجاع إعدادات PS لإعادة الاستخدام. — MathWorks mapminmax
هنا يتم تقييم نظام Sugeno FIS: تُحسب درجات الانتماء (membership) لكل قاعدة، ثم firing strengths (قوة تفعيل القواعد) وفق عامل AND (مثل prod)، ثم تُحسب مخرجات consequents (غالباً خطية)، وبعدها تُجمع بطريقة Sugeno لإنتاج yNorm. هذا مكافئ لمفهوم evalfis في MATLAB.
- • توثيق Sugeno FIS. — MathWorks sugfis
- • توثيق evalfis (تقييم FIS وإرجاع نتائج) - نستخدمه كمفهوم مرجعي. — MathWorks evalfis
بعد yNorm، نرجع الخرج إلى نطاقه الحقيقي باستخدام PS_out (Reverse mapminmax)، فينتج outLog. ثم نطبّق inverse log للحصول على الكلفة النهائية:
outLog = reverse_mapminmax(yNorm, PS_out)
cost = (10 ^ outLog) - 1
بهذا أنت فعلياً أنجزت: Log → mapminmax → Sugeno eval → reverse mapminmax → inverse log، وهي سلسلة مطابقة للـ MATLAB.
القيمة البحثية هنا أنك لم “تعِد تدريب” النموذج في الويب، بل نقلت (conversion) نموذجاً مدرباً من MATLAB إلى PHP، مع الحفاظ على نفس التحويلات والمعلمات (fis + PS settings). هذا يجعل المقارنة MATLAB vs PHP ممكنة بدقة.
Jang (1993) يشرح معمارية ANFIS والتعلم الهجين وبناء mapping من بيانات التدريب. — Jang 1993 PDF
3) شرح CostGaugeService بالتفصيل العلمي
Gaugeبعد الحصول على الكلفة الكلية (Total Cost)، نحتاج إلى تصنيفها بطريقة عادلة قابلة للمقارنة بين مشاريع مختلفة المساحات. لذلك استخدمنا مؤشر A = Cost per m² (كلفة لكل متر مربع). هذا أسلوب شائع كـ normalization أو parametric indicator حتى تكون المقارنات معقولة.
A = TotalCost / Area (IQD per m²)
الخدمة تتحقق أولاً أن المساحة > 0 ثم تحسب A وتطابقها مع ranges موجودة في config(cost_gauge.ranges).
- • إذا A ضمن [min, max) نختار هذا الرينج.
- • إذا A أقل من أول رينج → أول رينج.
- • إذا A أعلى من آخر رينج → آخر رينج.
- • النتيجة ترجع label_key + label + range_used + كل ranges حتى ترسم Gauge.
مفهوم كلفة لكل متر مربع/وحدة مساحة يستخدم في تقديرات البناء/المشاريع كمعيار parametric للتطبيع والمقارنة. — RAIC CHOP (Cost Planning)
4) شرح SensitivityService بالتفصيل (OAT + Perturbation)
XAIهذه الخدمة تُخرج “نسبة تأثير” لكل من 7 مدخلات (مختارة من أصل 13). المنهج المتّبع هو One-At-a-Time (OAT): نغيّر عامل واحد فقط كل مرة ونراقب تغيّر خرج النموذج. هذه طريقة حساسية محلية (local) وبسيطة وواضحة للمستخدم.
1) Base cost:
C0 = f(x)
2) For each feature i:
- If continuous: test (xi - 10%) and (xi + 10%)
- If categorical: test all allowed values (except current)
3) Max absolute impact:
Δi = max | f(x_test) - C0 |
4) Impact percentage:
Impact%i = (Δi / C0) * 100
5) Sort descending -> bar chart + top influencers
بالنهاية نرتّب النتائج تنازلياً حسب impact_percent ونأخذ أعلى top_n حتى ندعم تفسير ExplanationService.
- • واضح للمستخدم النهائي: “غيّرت هذا العامل فقط فصار الفرق كذا”.
- • سريع وقابل للتطبيق بدون تدريب جديد.
- • مناسب كتفسير محلي Instance-based (لكل مشروع).
- • قد لا تلتقط تداخلات العوامل (feature interactions) لأننا نغيّر عامل واحد فقط.
- • تعتمد على حجم perturbation (مثلاً ±10%).
هذه الحدود معروفة علمياً في تحليل الحساسية، لكنها تبقى مقبولة جداً للشرح والتفسير المحلي داخل نظام ويب.
- • مفهوم OAT و“perturbations typically occur one at a time”. — Razavi et al., 2021 (ScienceDirect)
- • وصف حساسية “each input feature is perturbed one-at-a-time”. — Naik et al., 2021 (Springer)
- • طرق XAI model-agnostic المعتمدة على perturbation ومراقبة تغير التنبؤ. — Wikle et al., 2022 (PMC)
5) شرح ExplanationService بالتفصيل (Rule/Template-based NLG)
NLGهذه الخدمة هي طبقة “اللغة” فوق الأرقام: تحوّل نتائج الحساب إلى تفسير مفهوم ومهني. علمياً هذا يسمى Data-to-Text / Natural Language Generation (NLG). طريقتك هنا Rule/Template-based: تستخدم قوالب جاهزة + قواعد اختيار الأسباب حسب أعلى المؤثرات.
- • Gauge: التصنيف + قيمة A (كلفة/م²).
- • Sensitivity: top_influencers + debug_payload (اتجاه التأثير، delta...).
- • inputsAssoc: القيم الحالية للمدخلات حتى نشرح “الحالة الحالية”.
- min_influence_pct: أقل نسبة تأثير لقبول السبب
- max_reasons: الحد الأعلى لعدد الأسباب
- نمر على top_influencers:
إذا pct >= minPct -> نولد سبب (AR + EN)
- إذا ماكو أسباب قوية -> fallback sentence
الخدمة أيضاً تُحدد اتجاه التأثير (increase/decrease/neutral) بالاعتماد على delta = cost_after_change - base_cost، وتستخدم ذلك لصياغة جملة هندسية توضح هل القيمة الحالية أقل/أعلى كلفة من بدائلها ضمن نطاق الاختبار.
- • ثبات الصياغة الرسمية (مناسب للأكاديميا والتقارير).
- • قابل للتدقيق: نعرف بالضبط من أين جاءت كل جملة (debug payload).
- • قابل للصيانة: تغيير قالب أو قاعدة أسهل من تدريب نموذج لغوي.
- • يدعم لغتين بسهولة (AR/EN).
- • تعريف NLG (تحويل بيانات إلى نص). — IBM (NLG)
- • ورقة عن Template-Based NLG وتطبيقه. — IAENG PDF
- • نقاش علمي حول قيمة Template-based NLG (ليس بالضرورة أدنى). — van Deemter et al. PDF
Implementation & System Conversion (فصل التحويل من MATLAB إلى Web)
فصل بحثي- • UI Layer: صفحات إدخال/نتائج/تقارير + مخططات Plotly.
- • Service Layer: HtsService, AnfisService, CostGaugeService, SensitivityService, ExplanationService.
- • Data Layer: Projects/Calculations + HeatDay (HTS) + configs للـ PS settings.
- • Report Layer: توليد PDF (ملخص + أسباب + مخططات).
User Inputs
↓
(1) HTS ← HeatDay(year → days_above_40)
↓
Build ordered13 (V1..V13)
↓
(2) ANFIS predictCost → TotalCost
↓
(3) Gauge A = TotalCost/Area → label/range
↓
(4) Sensitivity OAT → impact% + top influencers
↓
(5) Explanation NLG → summary + reasons
↓
UI Charts + PDF Report
هنا توثّق ما تم في MATLAB أثناء التدريب: نوع البيانات، عدد العينات، تقسيم Train/Validation، واختيار membership functions، وعدد القواعد، وخطأ التدريب (MSE/RMSE) على التدريب.
ملاحظة: تدريب ANFIS يتم وفق ما يشرحه Jang 1993 (Hybrid learning).
- • نفس 13 مدخل تُمرّر إلى MATLAB وPHP.
- • مقارنة output النهائي (Cost) بعد inverse log.
- • حساب فرق مطلق/نسبي: |PHP − MATLAB| و %Error.
توثيق صحة HTS يكون بإظهار: (1) مثال تاريخ صيانة، (2) startYear حسب الكود، (3) السنوات المشمولة، (4) مجموع days_above_40، مع لقطة من جدول HeatDay أو query output.
ضمن التقرير، سنضع Screenshots لأوامر CLI التي نفذتها لاختبار الخدمات (مثل anfis:test-gauge وغيرها) ولنوضح أن النتائج ثابتة مع نفس المدخلات.
أثبت أن التصنيف يعتمد على A (Cost/m²) وليس فقط TotalCost، واذكر رينجات الكونفگ ولماذا تم اختيارها (حسب سياق الدراسة/المشروع).
- • Log: نفس المعادلة log10(x+1).
- • PS_in: نفس gain/xoffset/ymin/yrange.
- • fis: نفس ملف الـ .fis (Sugeno rules).
- • PS_out: نفس reverse normalization.
- • Inverse log: (10^outLog) - 1.
هذه المراجع ليست “تحويلك أنت”، لكنها أمثلة رسمية على مفهوم نشر/استضافة تطبيقات MATLAB كويب، وتفيد كفكرة عامة في فصل التحويل. — MathWorks Web App Server
المصادر (References)
روابطExample Walkthrough (مثال واحد خطوة بخطوة)
مثالهذا مثال واحد يوضح مرور البيانات عبر الخدمات الخمس: HTS → ANFIS → Gauge → Sensitivity → Explanation. الأرقام هنا لشرح المنطق، أما قيمة ANFIS الدقيقة فتتحدد بحسب PS settings وملف الـ FIS .
نفترض مشروع صيانة لطريق في كربلاء بتاريخ صيانة محدد ومساحة معقولة، مع كود عمر رصف متوسط. الهدف هو توضيح كيف تنتقل القيم داخل النظام.
بما أن كود عمر الرصف = 2، إذن نافذة السنوات = 12 سنة. سنة الصيانة = 2024.
yearsSpan = 12
maintenanceYear = 2024
startYear = 2024 - 12 = 2012
HTS = sum(days_above_40) from (2013 .. 2024)
نفترض أن مجموع الأيام فوق 40°C من 2013 إلى 2024 حسب جدول HeatDay يساوي: 980 يوم.
هذا الرقم يدخل لاحقاً كواحد من مدخلات نموذج ANFIS (ضمن ordered13) حسب الترتيب .
ندخل 13 قيمة مرتبة ordered13 (V1..V13). سنعرض مثالاً مبسطاً لثلاث قيم فقط لشرح التحويلات، ثم نوضح كيف تُستنتج الكلفة.
Assume three raw inputs (subset):
V3 (Area) = 12000
V7 (HTS) = 980
V9 (Traffic) = 2 (categorical code as numeric)
Step A) log10(x+1):
log10(12000+1) ≈ 4.079
log10(980+1) ≈ 2.992
log10(2+1) ≈ 0.477
Step B) mapminmax apply (0..1):
xNorm = applyVector(xLog, PS_in) // exact values depend on PS_in in your config
Step C) Sugeno eval:
yNorm = evaluateSugeno(xNorm) // depends on FIS (.fis rules & parameters)
Step D) reverse output normalization:
outLog = reverseScalar(yNorm, PS_out)
Step E) inverse log:
cost = (10^outLog) - 1
الأرقام الدقيقة لـ xNorm/yNorm/outLog تعتمد على PS_in/PS_out وملف الـ FIS لديك، لذلك هذا مثال توضيحي للمنهج وليس رقمك النهائي.
لإكمال المثال end-to-end سنفترض أن ANFIS أعطى الكلفة الكلية التالية لهذا المشروع: 540,000,000 دينار.
نحسب A = TotalCost / Area حتى نقارن بين المشاريع بشكل عادل.
A = 540,000,000 / 12,000
= 45,000 IQD/m²
بعدها الخدمة تطابق A مع ranges الموجودة في config(cost_gauge.ranges) لتحديد (واطئة/متوسطة/عالية...) ولون الرينج.
هنا سنعرض مثالين صغيرين داخل نفس المثال: عامل continuous (±10%) وعامل categorical (تجربة قيم). الفكرة: نأخذ أكبر فرق ونحوّله إلى نسبة.
BaseCost = 540,000,000. نختبر Area=10,800 و Area=13,200 ونقيس الفرق.
Base cost C0 = 540,000,000
Test low (Area -10%): newCost = 575,000,000 → diff = 35,000,000
Test high (Area +10%): newCost = 510,000,000 → diff = 30,000,000
Δ = max(diff) = 35,000,000
Impact% = (Δ / C0) * 100
= (35,000,000 / 540,000,000) * 100
≈ 6.48%
نفترض RoadType الحالي = 2. نجرب القيم [1,3] ونختار أكبر فرق.
Base cost C0 = 540,000,000
Current RoadType = 2
Test RoadType = 1 → newCost = 520,000,000 → diff = 20,000,000
Test RoadType = 3 → newCost = 610,000,000 → diff = 70,000,000
Δ = 70,000,000
Impact% = (70,000,000 / 540,000,000) * 100
≈ 12.96%
هذه الأرقام مثال لشرح الحساب. داخل النظام الحقيقي، newCost يأتي من predictCost بعد تعديل قيمة العامل.
نفترض أن الـ Gauge صنّف الحالة “متوسطة” وأن أعلى مؤثرين هما RoadType (≈12.96%) وArea (≈6.48%). هنا يظهر كيف تتحول هذه النتائج إلى Summary + Reasons وفق قوالب ثابتة واتجاه التأثير.
التكلفة التقديرية ضمن مستوى (متوسطة)، وقيمة المؤشر A ≈ 45,000 دينار/م². الكلفة الكلية المقدّرة ≈ 540,000,000 دينار. بشكل عام، هذا التصنيف يتوافق مع تأثير خصائص الطريق والأحمال والبيئة على عمق التدخل المطلوب.
—
• (Road Type) — approx. impact 12.96%.
Changing this factor increased the cost compared to the current state.
(Δ ≈ 70,000,000 IQD).
• (Area) — approx. impact 6.48%.
Changing this factor affected the cost within the tested ±10% range.
(Δ ≈ 35,000,000 IQD).
لاحظ أن صياغة الجمل تأتي من: (1) label العامل من الكونفگ، (2) impact% من Sensitivity، (3) direction من debug_payload، ثم قالب Template ثابت.