نشان دانشگاه صنعتی شریف
سامانه‌ی پردازش و لجستیک تجارت الکترونیک
بهینه‌سازی تخصیص سفارش با برنامه‌ریزی خطی، مسیریابی ناوگان با الگوریتم ژنتیک، چیدمان سه‌بعدی بار و دستیار تحلیلی مبتنی بر هوش مصنوعی.
پروژه‌ی پایانی · درس برنامه‌نویسی پیشرفته (Advanced Programming)
دانشگاهدانشگاه صنعتی شریف — دانشکده‌ی مهندسی صنایع
موضوع پروژهموضوع 2 — سیستم پردازش و لجستیک تجارت الکترونیک (سبک دیجی‌کالا / تیپاکس)
ماژول‌های نمره‌داربرنامه‌ریزی خطی (LP/MILP) · الگوریتم ژنتیک (GA/VRPTW) · رابط کاربری تعاملی · چت‌بات تحلیلی
پشته‌ی فناوریPython · FastAPI · PuLP/CBC · NumPy · React · Three.js · Leaflet · KaTeX
نگارندهمعصومه یحیویان  ·  شماره‌ی دانشجویی: 401155565
استاد درسدکتر محمدرضا قدوسی
تاریخ تدوینمرداد 1405
این گزارش با پشتیبانی ابزارهای هوش مصنوعی تدوین شده و کلیه‌ی فرمول‌های ریاضی با موتور KaTeX رندر شده‌اند. ارقام به‌صورت لاتین و متن به فارسی با فونت وزیرمتن نمایش داده می‌شوند.

؟ فهرست مطالب

چکیده

PackUp یک سوئیت تصمیم‌گیری لجستیک برای تجارت الکترونیک است که سه مسئله‌ی هسته‌ای زنجیره‌ی تأمین را در یک معماری ماژولار حل می‌کند: (1) تخصیص بهینه‌ی سفارش از انبارهای مرکزی به مراکز توزیع با یک مدل برنامه‌ریزی خطیِ عددصحیح مختلط (حل‌شده با PuLP/CBC) که علاوه بر جواب بهینه، ارزش‌های سایه‌ای و تحلیل حساسیت را نیز محاسبه می‌کند؛ (2) مسیریابی ناوگان با پنجره‌ی زمانی (VRPTW) با یک الگوریتم ژنتیکِ خودنوشته شامل رمزگذاری تور-غول‌آسا، رمزگشای Split و اپراتورهای OX/PMX؛ و (3) چیدمان سه‌بعدیِ بار با قید تخلیه‌ی چندمقصدی. یک چت‌بات تحلیلی نتایج را به زبان طبیعی تفسیر می‌کند و می‌تواند سناریوهای «چه‌می‌شد-اگر» را زنده اجرا کند.

1 مقدمه و صورت مسئله

در تجارت الکترونیک، هزینه و کیفیتِ خدمت تا حد زیادی در «لجستیک» تعیین می‌شود: کالا باید از انبارهای مرکزی به مراکز توزیع برسد، سپس با ناوگانی محدود و در بازه‌های زمانیِ توافق‌شده به درِ منزل مشتری تحویل شود و در هر وانت به‌گونه‌ای چیده شود که در هر توقف بدون جابه‌جاییِ بقیه قابل تخلیه باشد. این پروژه سه لایه‌ی تصمیم را به‌صورت یکپارچه مدل و حل می‌کند.

1.1. تعریف رسمیِ موضوع (موضوع 2)

مسئله‌ی خطی (LP/MILP)

تخصیصِ سفارشات از انبارهای مرکزی به مراکز توزیعِ منطقه‌ای جهت حداقل‌سازیِ کل هزینه‌های حمل‌ونقل.

مسئله‌ی NP-Hard (GA)

مسیریابیِ ناوگانِ تحویلِ کالا دربِ منزل با پنجره‌ی زمانی (VRPTW) و ظرفیتِ محدودِ وانت‌بارها.

1.2. چرا دو پارادایمِ حل متفاوت؟

مسئله‌ی تخصیص یک برنامه‌ی خطیِ عددصحیح مختلط است که با متغیرهای پیوسته‌ی جریان و متغیرهای دودوییِ فعال‌سازیِ مسیر مدل می‌شود؛ برای این دسته، حل‌گرهای دقیق (شاخه‌وکران) جوابِ بهینه‌ی سراسری و اطلاعاتِ دوگان (ارزش سایه‌ای) می‌دهند. در مقابل، مسیریابیِ VRPTW از خانواده‌ی مسائلِ NP-Hard است؛ فضای جواب فاکتوریل رشد می‌کند و حلِ دقیق برای 50 مشتری عملی نیست. بنابراین از یک فراابتکارِ تکاملی (الگوریتم ژنتیک) استفاده می‌کنیم که در زمانِ معقول به جوابی نزدیک‌به‌بهینه می‌رسد.

داده‌ی محکِ واقع‌گرایانه

سناریوی نمونه بر پایه‌ی جغرافیای واقعیِ ایران ساخته شده است: 3 انبار مرکزی (تهران، کرج، قم) و 8 مرکز توزیع (تهران‌شرق، تهران‌غرب، اصفهان، شیراز، مشهد، تبریز، رشت، اهواز) برای LP، و 50 مشتریِ تهران با پنجره‌های زمانیِ متفاوت برای GA. فاصله‌ها با فرمول Haversine و هزینه‌ها با نرخ‌نامه‌ی مستند محاسبه می‌شوند.

1.3. اهدافِ نمره‌دار و پوششِ آن‌ها

بخش ارزیابیبارمتحققِ آن در PackUp
مدل‌سازی مهندسی صنایع3فرمول‌بندیِ کاملِ LP و GA در همین گزارش (بخش‌های 3 و 4)
کدنویسی ماژول LP4backend/app/lp — مدل FCTP، دوگان، حساسیت، تورنادو
کدنویسی ماژول GA4backend/app/ga — تور-غول‌آسا، Split، OX/PMX، جست‌وجوی محلی
رابط کاربری (APP)3برنامه‌ی React با نمودار، نقشه و صحنه‌ی سه‌بعدی
چت‌بات هوشمند6backend/app/chat — 5 ابزارِ زنده روی نتایج

2 معماری سامانه

سامانه بر پایه‌ی برنامه‌نویسیِ ماژولار و جداسازیِ صریحِ «منطقِ نمره‌دار» از «رابط» طراحی شده است. کلِ ماژول‌های نمره‌دار (LP، GA، چت‌بات) در پایتون و در بک‌اند پیاده شده‌اند؛ رابط کاربری یک برنامه‌ی React است که تنها از طریق یک API قراردادی با بک‌اند سخن می‌گوید.

رابط کاربری — React / TypeScript تخصیص (LP)نقشه · دوگان · تورنادو مسیریابی (GA)همگرایی · شبیه‌سازی بارگیری سه‌بعدیThree.js چت‌باتاستریم SSE داشبورد · راهنما · موتور i18n دوزبانه (fa/en) لایه‌ی کلاینت API + حافظه‌ی جلسهrunStore — خروجیِ هر ماژول ورودیِ ماژولِ بعد می‌شودو زمینه‌ی چت‌بات را می‌سازد HTTP · SSE بک‌اند — Python / FastAPI ماژول LP — PuLP / CBCحل MILP · دوگان · حساسیت · تورنادو ماژول GA — NumPy (خودنوشته)Split · OX/PMX · 2-opt · کار پس‌زمینه + SSE ماژول چت‌بات — google-genaiفراخوانیِ خودکارِ 5 ابزار + تزریق زمینه اسکیماهای Pydantic + هسته‌ی قطعیبذر ثابت 1404 — هر اجرا تکرارپذیر
شکل 1 — معماریِ کلانِ سامانه: جداسازیِ منطقِ نمره‌دارِ پایتونی از رابطِ React، با لایه‌ی حافظه‌ی جلسه که ماژول‌ها را زنجیر می‌کند.

2.1. جریانِ داده و تصمیم — سه ماژول، یک زنجیره

ارزشِ سامانه در «اتصالِ» ماژول‌هاست نه در تک‌تکِ آن‌ها. شکلِ زیر نشان می‌دهد داده‌ی سفارش از کجا وارد می‌شود، هر ماژول چه خروجیِ مشخصی به ماژولِ بعدی تحویل می‌دهد، و در انتها چه شاخصِ تصمیمِ مدیریتی تولید می‌شود. پیکانِ چین‌دارِ سمتِ راست، حلقه‌ی بازخوردِ «چه‌می‌شد‌اگر» است: چت‌بات می‌تواند مدل را با ورودیِ جدید دوباره حل کند و کلِ زنجیره را به‌روز کند.

ورودی‌های مسئلهسفارش‌ها (وزن · حجم · پنجره‌ی زمانی) · ظرفیت انبارها · تقاضای مراکز توزیع · نرخ‌نامه‌ی حمل1تخصیص سفارشMILP — PuLP/CBCورودی: ظرفیت، تقاضا، هزینه‌ی مسیرخروجی: جریان بهینه + ارزش سایه‌ای2مسیریابی ناوگانVRPTW — الگوریتم ژنتیکورودی: سفارش‌های هر مرکز، ظرفیت وانتخروجی: توالی توقف‌ها و زمان‌بندی3چیدمان سه‌بعدی بارموتور بارچین — قید LIFOورودی: بسته‌های هر مسیر به‌ترتیب توقفخروجی: پلان بارگیری + پرشدگیتقاضای هر مرکزبار هر وانت به‌ترتیبهزینه‌ی شبکهمسافت و ناوگانبهره‌وری فضاشاخص‌های تصمیم مدیریتیهزینه‌ی کل لجستیک · هزینه به‌ازای هر سفارش · مسافت · تعداد ناوگان · پرشدگی · انتشار CO2چت‌بات تحلیلیتفسیر نتایج به زبان مدیریتی + اجرای «چه‌می‌شد‌اگر» با حل مجدد واقعی مدل‌هابازخورد چه‌می‌شد‌اگرهمه‌ی مراحل روی داده‌ی یک جلسه اجرا می‌شوند؛ تغییر ورودی در هر مرحله، مراحل بعدی را به‌روز می‌کند.
شکل 2 — جریانِ داده و تصمیم: از ورودیِ سفارش‌ها تا شاخص‌های مدیریتی. جهتِ جریان راست‌به‌چپ است.

2.2. خروجیِ نهایی: شاخص‌های تصمیمِ مدیریتی

زنجیره‌ی بالا در انتها به چهار عددی می‌رسد که یک مدیرِ عملیات با آن‌ها تصمیم می‌گیرد. این اعداد مشتقِ مستقیمِ خروجیِ حل‌گرهایند و در داشبوردِ برنامه نیز دقیقاً به همین شکل نمایش داده می‌شوند؛ بنابراین گزارش و سامانه یک عدد واحد را روایت می‌کنند.

شاخص‌های تصمیم مدیریتی — خروجی سناریوی نمونه164.6میلیون تومانهزینه‌ی کل لجستیک3,292,691تومانهزینه به‌ازای هر سفارش297.6کیلومترمسافت تحویل7دستگاهناوگان به‌کاررفتهترکیب هزینهشبکه‌ی تأمین (LP) — 154.8M (94%)شبکه‌ی تأمین (LP)توزیع آخرین‌مایل — 9.9M (6%)آخرین‌مایل = 297.6 کیلومتر × 12,000 تومان + 7 وسیله × 900,000 تومان (فرضِ نرخ، قابل بازبینی)هزینه‌ی هر سفارش = 164,634,570 ÷ 50 سفارش = 3,292,691 تومانهر عدد مستقیماً از خروجیِ حل‌گرها می‌آید؛ با تغییرِ ورودی، همین شاخص‌ها بلافاصله به‌روز می‌شوند.ردپای کربن: 103.7 کیلوگرم CO2 در این اجرا
شکل 3 — شاخص‌های مدیریتی و ترکیبِ هزینه برای سناریوی نمونه (خروجیِ واقعیِ حل‌گرها).

2.1. اصولِ طراحی

3 ماژول برنامه‌ریزی خطی (LP/MILP) — تخصیص سفارش

این ماژول تعیین می‌کند هر مرکز توزیع، تقاضای خود را از کدام انبار و به چه میزان تأمین کند تا کل هزینه‌ی شبکه کمینه شود. مدل از نوع مسئله‌ی حمل‌ونقل با هزینه‌ی ثابت (Fixed-Charge Transportation Problem) است که هم هزینه‌ی متغیرِ حمل و هم هزینه‌ی ثابتِ فعال‌سازیِ هر مسیر را در بر می‌گیرد.

3.1. مجموعه‌ها و پارامترها

نمادتعریفنمادتعریف
$i \in I$انبارهای مرکزی$c_{ij}$هزینه‌ی حملِ هر واحد در مسیر (i,j)
$j \in J$مراکز توزیع$f_{ij}$هزینه‌ی ثابتِ فعال‌سازیِ مسیر (i,j)
$S_i$ظرفیتِ عرضه‌ی انبار i$u_{ij}$سقفِ حملِ مسیر (اختیاری)
$D_j$تقاضای مرکز j$\pi$جریمه‌ی هر واحد کمبودِ پوشش

3.2. متغیرهای تصمیم

$$ x_{ij} \ge 0 \quad\text{(مقدار جریان از i به j)} \qquad y_{ij} \in \{0,1\} \quad\text{(فعال‌بودن مسیر)} \qquad z_{j} \ge 0 \quad\text{(کمبودِ مرکز j)} $$

متغیرِ کمکیِ کمبود $z_j$ تضمین می‌کند مدل همیشه شدنی بماند؛ اگر عرضه کفافِ تقاضا را ندهد، کمبود با جریمه‌ی $\pi$ در تابع هدف ظاهر می‌شود و پیام روشنی به کاربر می‌دهد به‌جای «ناشدنی» شدنِ مدل.

3.3. تابع هدف

$$ \min \; Z \;=\; \underbrace{\sum_{(i,j)} c_{ij}\, x_{ij}}_{\text{هزینه‌ی متغیرِ حمل}} \;+\; \underbrace{\sum_{(i,j)} f_{ij}\, y_{ij}}_{\text{هزینه‌ی ثابتِ مسیر}} \;+\; \underbrace{\pi \sum_{j} z_{j}}_{\text{جریمه‌ی کمبود}} $$
رابطه‌ی (1) — کمینه‌سازیِ مجموعِ هزینه‌ی متغیر، هزینه‌ی ثابتِ فعال‌سازی و جریمه‌ی کمبود.

3.4. قیود

$$ \sum_{j} x_{ij} \;\le\; S_i \qquad \forall i \in I \tag{2 — ظرفیت عرضه} $$ $$ \sum_{i} x_{ij} \;+\; z_j \;\ge\; D_j \qquad \forall j \in J \tag{3 — پوشش تقاضا} $$ $$ x_{ij} \;\le\; M_{ij}\, y_{ij}, \quad M_{ij} = \min\!\left(S_i,\, D_j,\, u_{ij}\right) \tag{4 — پیوندِ فعال‌سازی} $$ $$ x_{ij} \ge 0,\quad z_j \ge 0,\quad y_{ij} \in \{0,1\} \tag{5 — دامنه‌ها} $$

قیدِ (4) یک Big-M سفت است: به‌جای یک مقدارِ بزرگِ دلخواه، از کوچک‌ترین کرانِ ممکن ($\min$ ظرفیت، تقاضا و سقفِ مسیر) استفاده می‌شود تا شکافِ آزادسازیِ خطی کم و حل سریع‌تر شود. این قید جریان را تنها روی مسیرهای «فعال» ($y_{ij}{=}1$) مجاز می‌کند و هزینه‌ی ثابت را واقعی می‌سازد.

3.5. مشتق‌سازیِ پارامترها از جغرافیا

$$ d_{ij} = 1.3 \times \mathrm{Haversine}(\text{انبار}_i,\, \text{مرکز}_j) \qquad c_{ij} = d_{ij} \cdot r \qquad f_{ij} = F_0 + F_{100}\cdot\frac{d_{ij}}{100} $$
ضریبِ 1٫3 برای پیچ‌وخمِ جاده؛ نرخِ $r{=}45$ تومان بر واحد-کیلومتر، $F_0{=}500{,}000$ و $F_{100}{=}30{,}000$ تومان (فرضِ نرخِ حملِ خردِ 1404؛ در برنامه قابلِ ویرایش).

3.6. روشِ حل و ارزشِ سایه‌ای (دوگان)

مدل با کتابخانه‌ی PuLP ساخته و با حل‌گرِ CBC (شاخه‌وکران) حل می‌شود. برای استخراجِ ارزشِ سایه‌ای، پس از یافتنِ جوابِ صحیحِ بهینه، متغیرهای دودویی $y_{ij}$ تثبیت شده و مدل یک‌بار دیگر به‌صورتِ یک برنامه‌ی خطیِ محض حل می‌شود؛ آنگاه ضریبِ دوگانِ هر قید، ارزشِ سایه‌ایِ آن است.

نکته‌ی فنیِ کلیدی

در بازحلِ دوگان، جمله‌ی Big-M از قیدِ تقاضا حذف می‌شود؛ در غیر این‌صورت ضریبِ دوگانِ تقاضا به‌جای هزینه‌ی نهاییِ واقعی، برابرِ جریمه‌ی کمبود $\pi$ می‌شد. این جزئیات تفاوتِ یک ارزشِ سایه‌ایِ درست با یک عددِ گمراه‌کننده است.

تفسیرِ اقتصادی طبق قضیه‌ی مکملی (Complementary Slackness): قیدِ فعال (با لختیِ صفر) ارزشِ سایه‌ایِ ناصفر دارد و گلوگاه است؛ قیدِ غیرفعال ارزشِ سایه‌ایِ صفر دارد. ارزشِ سایه‌ایِ ظرفیتِ یک انبار یعنی «صرفه‌جوییِ هر واحد ظرفیتِ اضافه»، و ارزشِ سایه‌ایِ تقاضا یعنی «هزینه‌ی نهاییِ سرویسِ یک واحدِ تقاضای بیشتر».

3.7. تحلیلِ حساسیت و نمودارِ تورنادو

دو تحلیلِ پس‌ازبهینه ارائه می‌شود: (الف) حساسیتِ تک‌پارامتری که یک پارامتر را در بازه‌ی $\pm 20\%$ می‌چرخاند و اثرش را بر هزینه‌ی کل رسم می‌کند؛ (ب) تحلیلِ تورنادو که همه‌ی پارامترها را هم‌زمان $\pm\delta$ تکان داده و بر اساسِ بزرگیِ اثرشان بر هزینه رتبه‌بندی می‌کند تا پرتأثیرترین اهرم شناسایی شود.

3.8. شبکه‌ی حل‌شده — تصویرِ جوابِ بهینه

شکلِ زیر همان مدلِ ریاضیِ بالا را در قالبِ جوابِ واقعی نشان می‌دهد: کدام انبار کدام مرکز را و با چه مقداری تغذیه می‌کند. ضخامتِ هر خط با مقدارِ جریان متناسب است و نوارِ زیر هر انبار، درصدِ بهره‌برداری از ظرفیت را نشان می‌دهد. انبارِ قم با ۱۰۰٪ بهره‌برداری گلوگاهِ شبکه است — همان قیدی که ارزشِ سایه‌ایِ آن در بخشِ بعد تفسیر می‌شود.

انبارهای مرکزی (عرضه)مراکز توزیع (تقاضا)180016003001100800600900900700تهران (چیتگر)4800 / 5000 — 96%کرج1400 / 3000 — 47%قم2500 / 2500 — 100%گلوگاه — ۱۰۰٪تهران‌شرقتقاضا 1800تهران‌غربتقاضا 1600اصفهانتقاضا 1200شیرازتقاضا 900مشهدتقاضا 1100تبریزتقاضا 800رشتتقاضا 600اهوازتقاضا 700ضخامت هر خط با مقدار جریان متناسب است؛ عدد روی خط، تعداد واحدِ تخصیص‌یافته است.
شکل 4 — شبکه‌ی تخصیصِ حل‌شده: ۹ مسیرِ فعال از ۳ انبار به ۸ مرکز توزیع.

3.8. نتایجِ عددی — سناریوی ایران

154.76M
هزینه‌ی کل (تومان)
9
مسیر فعال (از 24)
قم
گلوگاهِ شبکه
~80ms
زمان حل
یافتهمقدارتفسیر
ارزشِ سایه‌ایِ ظرفیتِ قم6,527 تومان/واحدگلوگاه؛ هر واحد ظرفیتِ اضافه در قم بیشترین صرفه‌جویی را دارد
ظرفیتِ آزادِ کرج53% بلااستفادهکم‌بهره‌ورترین انبار — ظرفیتِ رزرو
پرتأثیرترین اهرمِ تورنادوتقاضای مشهد (±19.9M)حساس‌ترین پارامترِ هزینه در کلِ شبکه
چه‌می‌شد-اگر: قم +20% ظرفیتصرفه‌جوییِ 2,592,299 تومانهزینه از 154.76M به 152.17M کاهش می‌یابد
جمع‌بندیِ ماژول LP

مدل نه‌تنها جوابِ بهینه بلکه دلیلِ اقتصادیِ آن را می‌دهد: کدام انبار گلوگاه است، سرمایه‌گذاری کجا بیشترین بازده را دارد و کدام پارامتر حساس‌ترین است. این ماژول با 47 آزمونِ پایتون پوشش داده شده است.

4 ماژول الگوریتم ژنتیک (GA) — مسیریابی VRPTW

این ماژول مسیرِ ناوگانِ تحویلِ درِ منزل را بهینه می‌کند به‌گونه‌ای که هر مشتری دقیقاً یک‌بار در پنجره‌ی زمانیِ خود سرویس شود و بارِ هر وانت از ظرفیتِ وزنی و حجمی فراتر نرود. چون این مسئله NP-Hard است، از یک الگوریتمِ ژنتیکِ خودنوشته (بدونِ کتابخانه‌ی آماده) استفاده می‌شود.

4.1. فرمول‌بندی VRPTW

$$ \min \; \Big(\, K,\;\; \sum_{k=1}^{K} \sum_{(a,b)\in r_k} d_{ab} \,\Big) \quad\text{(کمینه‌سازیِ لغوی)} $$
رابطه‌ی (6) — اول کمینه‌سازیِ تعدادِ وانتِ K، سپس کمینه‌سازیِ مسافتِ کل.

قیود: هر مشتری دقیقاً یک‌بار سرویس شود؛ بارِ هر مسیر از ظرفیتِ وزنی $Q_w$ و حجمی $Q_v$ فراتر نرود؛ و زمانِ شروعِ سرویس در پنجره‌ی زمانی بماند:

$$ \sum_{c \in r_k} w_c \le Q_w,\quad \sum_{c \in r_k} v_c \le Q_v \qquad e_i \;\le\; t_i \;\le\; \ell_i \quad \forall i \tag{7 — ظرفیت و پنجره‌ی زمانی} $$

در هر توقف، رسیدنِ زودتر از $e_i$ به انتظار می‌انجامد (مجاز) و رسیدنِ دیرتر از $\ell_i$ نقضِ قید است. کمینه‌سازیِ لغوی با یک جریمه‌ی وانت در تابعِ برازش پیاده می‌شود: $\text{fitness} = \lambda_{\text{veh}}\!\cdot\! K + \sum d + \text{جریمه‌ها}$.

4.2. طراحیِ کروموزوم: تور-غول‌آسا + رمزگشای Split

هر کروموزوم یک جایگشتِ ساده از مشتری‌ها است (یک «تورِ غول‌آسا» بدونِ مرزِ وانت). این جایگشت با یک رمزگشای بهینه به مسیرها تقسیم می‌شود — روشِ Split (پرینس، 2004) که با برنامه‌ریزیِ پویا روی یک گرافِ کمکی، کوتاه‌ترین مسیر از گرهِ 0 تا n را می‌یابد و بدین‌ترتیب بهترین برشِ همان جایگشت به وانت‌ها را می‌دهد:

$$ P(0)=0,\qquad P(j) = \min_{\,0 \le i < j} \Big[\, P(i) + \text{cost}\big(\text{مسیرِ } \sigma_{i+1..j}\big) \,\Big] $$
رابطه‌ی (8) — رمزگشای Split: هزینه‌ی هر یالِ (i→j) برابرِ جریمه‌ی وانت + مسافت + جریمه‌ی نقضِ TW/ظرفیت (نسخه‌ی relaxed تا برازش همیشه تعریف‌شده بماند).

این جداسازیِ «رمزگذاری از رمزگشایی» مزیتِ بزرگی دارد: اپراتورهای ژنتیک روی یک جایگشتِ ساده کار می‌کنند (بی‌دردسر)، و ساختارِ پیچیده‌ی مسیرها به‌صورتِ بهینه از خودِ جایگشت استخراج می‌شود.

۱. کروموزوم: تور غول‌آسا (بدون تفکیک وانت)123456789یک جایگشتِ ساده از مشتریان — فضای جست‌وجوی پیوسته و بدون قیدِ ظرفیترمزگشایی Split (پرینز): برشِ بهینه با برنامه‌ریزی پویا۲. سه مسیرِ شدنی با رعایتِ ظرفیت و پنجره‌ی زمانیD123وانت 1D456وانت 2D789وانت 3خطِ چین: بازگشت به دپو. هر برش یک وانت است؛ تعدادِ وانت خروجیِ Split است نه ورودیِ کاربر.
شکل 5 — از کروموزوم تا مسیرهای شدنی: یک جایگشتِ ساده با رمزگشای Split به چند مسیرِ سازگار با ظرفیت و پنجره‌ی زمانی تبدیل می‌شود.

4.3. اپراتورهای تکاملی

اپراتورنقش
OX (Order Crossover)تقاطعِ ترتیب‌محور؛ برشی از والدِ اول را حفظ و بقیه را به‌ترتیبِ والدِ دوم پر می‌کند — پیوستگیِ توالی را نگه می‌دارد.
PMX (Partially-Mapped)تقاطعِ نگاشتِ جزئی؛ ساختارِ موقعیتی را با یک نگاشتِ دوسویه حفظ می‌کند.
جهش (سه‌گانه)جابه‌جایی، درج و وارونه‌سازیِ زیربخش — تنوعِ جمعیت را حفظ می‌کند.
2-opt (جست‌وجوی محلی)الگوریتمِ ممتیک: بازآراییِ یال‌ها با انتقالِ بین‌مسیری برای بهبودِ محلیِ بهترین‌ها.
سه درسِ معماریِ کلیدی

(1) جست‌وجوی محلی باید جریمه‌های تطبیقیِ جاری را ببیند نه ثابت؛ (2) تطبیقِ جریمه بر مبنای «شدنی‌بودنِ بهترین جواب» انجام شود نه نسبتِ جمعیت؛ (3) یک آرشیوِ جداگانه از بهترین جوابِ شدنی با معیارِ (وانت، مسافت) نگه‌داری شود تا نوسانِ جریمه نتیجه را نپراند.

4.4. همگرایی و اعتبارسنجیِ جهانی

بهترین هزینه نسل جواب نهایی بهترینِ نسل میانگینِ جمعیت
شکل 6 — نمودارِ همگراییِ نمونه (طرح‌واره): بهترین هزینه هرگز صعود نمی‌کند و پس از چند ده نسل به یک سطحِ پایدار می‌رسد. در برنامه، این نمودار به‌صورتِ زنده هنگام اجرا رسم می‌شود.

برای اعتبارسنجیِ جهانی، الگوریتم روی نمونه‌های استانداردِ Solomon اجرا شد و فاصله تا بهترین جوابِ شناخته‌شده (BKS) اندازه‌گیری شد:

نمونهفاصله تا BKSتعداد وانت
Solomon C101-25+0.3%برابرِ BKS
Solomon R101-25+0.2%8 = BKS

4.5. نتایجِ عددی — سناریوی تهران

50
مشتری
7
وانت
297.6
مسافت کل (km)
86%
میانگین پرشدگی حجمی
جمع‌بندیِ ماژول GA

جوابِ کاملاً شدنی برای 50 مشتری در کمتر از یک دقیقه، با پوششِ همه‌ی پنجره‌های زمانی و قیود ظرفیت؛ نتیجه با بذرِ ثابت تکرارپذیر و روی محکِ جهانیِ Solomon معتبر است. این ماژول با آزمون‌های اختصاصیِ همگرایی و بنچمارک پوشش داده شده است.

5 یکپارچگی مسیر و چیدمان سه‌بعدی بار

فراتر از حداقلِ خواسته‌ی موضوع، خروجیِ مسیریابی به یک موتور چیدمان سه‌بعدیِ بار متصل می‌شود: توقفِ k-امِ مسیر به بسته‌های همان مشتری نگاشت می‌شود و بسته‌ها با قیدِ دسترس‌پذیریِ چندمقصدی چیده می‌شوند تا در هر توقف بدونِ جابه‌جاییِ بقیه قابلِ تخلیه باشند (تخلیه‌ی LIFO).

5.1. وزنِ حجمی و صورت‌حساب

$$ W_v = \frac{L \times W \times H}{5000} \qquad\qquad W_{\text{bill}} = \sum_{p} \max\!\big(W_p,\; W_{v,p}\big) \qquad\qquad \eta = \frac{V_{\text{used}}}{V_{\text{total}}} $$
رابطه‌ی (9) — وزنِ حجمی (ابعاد به سانتی‌متر)، وزنِ صورت‌حساب (بیشینه‌ی وزنِ واقعی و حجمیِ هر بسته)، و نرخِ پرشدگیِ حجمی.

این فرمول‌ها مستقیماً منطقِ «پرداخت بر اساس فضا»ی سرویس‌های حملِ اشتراکی (مانند باکس‌لاینِ تیپاکس) را مدل می‌کنند: مشتری بابتِ فضایی که واقعاً اشغال می‌کند هزینه می‌دهد، و بارِ سبک اما حجیم بر مبنای وزنِ حجمی قیمت‌گذاری می‌شود. کاربر می‌تواند از کاتالوگِ 12 کارتنِ استانداردِ تیپاکس یا جعبه‌ی سفارشی بسته اضافه کند و اثرش را بر پرشدگی و وزنِ صورت‌حساب زنده ببیند.

قیدِ دسترس‌پذیریِ چندمقصدی (LIFO)

بسته‌های توقف‌های آخر، عقب‌تر یا پایین‌تر بار می‌شوند تا هنگامِ رسیدن به توقفِ زودتر، بدونِ برداشتنِ سایرِ بسته‌ها قابلِ تخلیه باشند. موتور این قید را تضمین و پایداریِ جانبی و شکنندگیِ هر بسته را نیز بررسی می‌کند.

6 چت‌بات تحلیلی هوشمند

چت‌بات یک تحلیل‌گرِ فارسیِ نتایج است که به خروجیِ همان جلسه متصل می‌شود. برخلافِ یک دستیارِ عمومی، این بات ابزارهای واقعی اجرا می‌کند: برای پرسش‌های «چه‌می‌شد-اگر» مدل را دوباره حل می‌کند و پاسخ را با اعدادِ واقعیِ قبل/بعد می‌دهد.

6.1. معماری

6.2. ابزارهای زنده (اجرای مجددِ مدل‌ها)

ابزارکارکرد
run_lp_whatifتغییرِ ظرفیت/تقاضا و بازحلِ MILP؛ پاسخ با هزینه‌ی قبل/بعد
rank_cost_driversتحلیلِ تورنادو — رتبه‌بندیِ پرتأثیرترین اهرم‌های هزینه
explain_shadow_priceتفسیرِ ارزشِ سایه‌ایِ یک قید با داده‌ی دقیق
get_route_detailجزئیاتِ توالیِ توقف‌های یک وانت + نمایشِ نقشه‌ی درون‌گفتگو
run_ga_quickاجرای سریعِ مسیریابی با بذرِ متفاوت برای سنجشِ حساسیت
نمونه‌ی تعاملِ زنده (راستی‌آزمایی‌شده)

پرسش: «اگر ظرفیتِ انبار قم 20% بیشتر شود چه می‌شود؟» — بات ابزارِ run_lp_whatif را صدا زد، مدل را واقعاً بازحل کرد و پاسخ داد: هزینه‌ی کل از 154.76M به 152.17M تومان کاهش می‌یابد (صرفه‌جوییِ 2,592,299 تومان)، و جدولِ قبل/بعد را نمایش داد. این عدد دقیقاً با محاسبه‌ی مستقلِ پنلِ «مقایسه‌ی سناریو» هم‌خوان است.

رابط چت‌بات تحلیلی
شکل 7 — رابطِ چت‌بات (طراحیِ الهام‌گرفته از ChatGPT): پاسخِ دستیار بدونِ حباب و با کنتراستِ بالا، پیامِ کاربر در حبابِ متمایز، راست‌چینِ صحیحِ فارسی با ترکیبِ درستِ واژه‌های لاتین و فرمول‌ها.

6.3. دو نمونه‌ی واقعی از گفتگو

دو نماگرفتِ زیر مستقیماً از سامانه‌ی زنده روی ap.packup.ir گرفته شده‌اند و دو توانِ متفاوتِ دستیار را نشان می‌دهند: بازگوییِ صوریِ مدل و گزارشِ عملیاتیِ یک مسیرِ حل‌شده.

پاسخ چت‌بات با فرمول‌بندی ریاضی مدل تخصیص
شکل 8 — پرسشِ «تابع هدف و قیدهای مدل تخصیص را با فرمول بنویس»: دستیار فرمول‌بندیِ کامل را با KaTeX رندر می‌کند — تابعِ هدف، قیدِ ظرفیت، قیدِ تقاضا، قیدِ نامنفی‌بودن و تعریفِ نمادها. توجه کنید که فرمول‌ها در متنِ راست‌چین به‌درستی چپ‌به‌راست چیده شده‌اند.
پاسخ چت‌بات با جدول توالی توقف‌های وانت ۱
شکل 9 — پرسشِ «مسیر وانت ۱ را نشان بده»: دستیار ابزارِ get_route_detail را صدا می‌زند و توالیِ هفت توقف را با زمانِ رسیدن، زمانِ انتظار و شروعِ سرویس برمی‌گرداند — همه از جوابِ واقعیِ الگوریتم ژنتیک، نه از حافظه‌ی مدل.
چرا این دو پاسخ ارزشِ تحلیلی دارند

پاسخِ دوم فقط داده را بازنمی‌گوید؛ آن را تشخیص می‌دهد. دستیار از همان جدول نتیجه می‌گیرد که قیدِ فعالِ وانت ۱ حجم است نه وزن (پرشدگیِ حجمی 93.2٪ در برابر وزنیِ 41.1٪) — یعنی بارِ این مسیر «چگالیِ پایین» دارد — و اینکه 503.1 دقیقه از 666.1 دقیقه‌ی مأموریت صرفِ انتظارِ پشتِ پنجره‌ی زمانی می‌شود.

اقدامِ پیشنهادی‌اش هم عددی است: تعویقِ 100 تا 150 دقیقه‌ای زمانِ خروج از انبار، با اثرِ تخمینیِ کاهشِ حدود 60٪ از زمانِ معطلی. این دقیقاً همان چیزی است که یک شاخصِ خام نمی‌دهد: عدد به‌علاوه‌ی علت به‌علاوه‌ی کارِ بعدی.

7 رابط کاربری و تجربه‌ی کاربر

رابط یک برنامه‌ی تک‌صفحه‌ای React با شش صفحه است: داشبورد، تخصیصِ سفارش، مسیریابی، بارگیریِ سه‌بعدی، چت‌بات و راهنما. تجربه‌ی کاربر بر «سادگیِ ورودِ اطلاعات» و «رسمِ نمودارهای تحلیلیِ خروجی» متمرکز است — دو شاخصِ صریحِ ارزیابی.

7.1. ورودِ ساده‌ی داده

7.2. نمودارها و مصورسازیِ تحلیلی

کیفیتِ ساختاری

کلِ رابط دوزبانه (fa/en)، راست‌چین/چپ‌چینِ خودکار، واکنش‌گرا (از 320 پیکسل) و دارای دارک‌مودِ سه‌حالته است. آیکن‌ها برداری (lucide) و بدونِ هیچ ایموجی هستند؛ اعداد در متنِ راست‌چین با ایزوله‌سازیِ جهت نمایش داده می‌شوند.

* نمایی از برنامه

تصاویر زیر از اجرای زنده‌ی برنامه روی سناریوی نمونه گرفته شده‌اند: نقشه‌ی تعاملی، نمودار تحلیلی، مسیرهای بهینه و صحنه‌ی سه‌بعدیِ چیدمان بار.

* کاتالوگِ ناوگانِ سه‌بعدی

سامانه کاتالوگی از ۲۲ وسیله‌ی نقلیه‌ی واقعیِ ایرانی دارد — از موتورِ پیک تا کشنده‌ی تریلی. هر وسیله با ابعادِ واقعیِ اتاقِ بار، ظرفیتِ وزنی، و مدلِ سه‌بعدیِ اختصاصی (پلاکِ ایرانی، جلوپنجره، چراغ‌های خودتاب، چرخ‌های لایه‌ای) در موتورِ چیدمانِ بارچین رندر می‌شود. کاربر وسیله را دستی برمی‌گزیند یا «انتخابِ خودکار»، کوچک‌ترین وسیله‌ی جاگیرِ بار را پیشنهاد می‌دهد و بار را همان‌جا با رعایتِ قیدِ تخلیه‌ی LIFO می‌چیند.

کشنده و کانتینر ۴۰ فوت
شکل 14 تا 20 — نمونه‌هایی از ۲۲ وسیله‌ی ناوگان (بالا: وانت‌ها تا کامیونت و یخچالی؛ پایین: کشنده + کانتینرِ ۴۰ فوت، 26000kg · 73.5m³). هر مدل با محورهای XYZ و چیدمانِ بارِ بهینه نمایش داده می‌شود؛ اختلافِ مقیاسِ اتاقِ بار مبنای «انتخابِ خودکارِ وسیله» است.

8 راستی‌آزمایی، آزمون و کیفیت

کیفیت با آزمون‌های خودکار و گیت‌های ساختاری تضمین می‌شود. منطقِ نمره‌دار به‌صورتِ توابعِ خالص از رابط جدا شده تا مستقل و دقیق آزموده شود.

50
آزمونِ بک‌اند (pytest)
104
آزمونِ فرانت (vitest)
mypy(strict) · ruff
i18n · no-emoji · build
حوزهپوششِ آزمون
LPبهینه‌ی دستی 2×2، تعادلِ قیود، مکملی، کمبود، رگرسیونِ حساسیت و تورنادو
GAصحتِ اپراتورها، رمزگشای Split، قطعیتِ بذر، شدنی‌بودنِ تهران، فاصله تا BKS روی Solomon
چت‌باتابزارها بدونِ تماسِ واقعی با مدل، اعتبارسنجی، استریمِ endpoint
منطقِ فرانتتخصیصِ ناوگان، تورنادو، شبیه‌سازی، پارسِ بسته، ویرایشِ سناریو — همه توابعِ خالص

8.1. مرورِ متخاصمِ چندعاملی

علاوه بر آزمون‌ها، تغییراتِ کلیدی با یک فرایندِ مرورِ متخاصمِ چندعاملی بازبینی شدند: عامل‌های مستقل به‌دنبالِ باگ می‌گشتند و یافته‌ها با عامل‌های راستی‌آزمای دیگر تأیید یا رد می‌شدند. این فرایند چند باگِ واقعی (از جمله یک باگِ نامرئیِ سرریزِ چیدمان و یک باگِ جهتِ فلش) را پیش از تحویل شناسایی و اصلاح کرد.

* استقرارِ زنده و خطِ CI/CD

برنامه فقط لوکال نیست؛ به‌صورتِ زنده و عمومی روی نشانیِ https://packup.ir مستقر است و از هر جا در دسترس است.

حلِ چالشِ دسترسیِ Gemini

API گوگل از آی‌پیِ ایران بسته است. برای آن‌که چت‌بات بدونِ هیچ VPN برای کاربر و استاد کار کند، برنامه روی یک سرورِ اروپایی (آمستردام) مستقر شد؛ چون تماس با Gemini سمتِ سرور انجام می‌شود، آی‌پیِ سرور مجاز است و پاسخ می‌گیرد. نکته‌ی مهندسیِ ظریف: بلاکِ گوگل بر پایه‌ی اعتبارِ آی‌پیِ دیتاسنتر است نه صرفاً کشور — یک آی‌پیِ اولِ اروپایی بلاک بود و با جابه‌جایی به آی‌پیِ تمیز حل شد. مدلِ فعال: gemini-3.5-flash.

پشته‌ی استقرار

کدِ کامل روی گیت‌هاب؛ اجرا با Docker Compose (بک‌اندِ FastAPI + فرانتِ nginx)؛ گواهیِ HTTPSِ خودکار (Let's Encrypt) با ریورس‌پروکسیِ Caddy که استریمِ SSE را سالم عبور می‌دهد. یک خطِ CI/CD (GitHub Actions) روی هر تغییر، آزمون‌های بک‌اند (ruff · mypy · pytest) و فرانت (typecheck · i18n · build · ۱۰۴ آزمون) را اجرا و در صورتِ سبزشدن، برنامه را خودکار روی سرور منتشر می‌کند.

محدودیتِ شناخته‌شده: پردازنده‌ی سرورِ اقتصادی (Burstable) حدودِ سه برابر کندتر از یک هسته‌ی دسکتاپ است، پس همگراییِ الگوریتم ژنتیک روی سرور کندتر از لوکال دیده می‌شود — این محدودیتِ سخت‌افزار است و با پینِ ترد‌های محاسباتی تا حدی بهبود یافت.

9 جمع‌بندی و کارهای آینده

PackUp نشان می‌دهد که سه پارادایمِ متفاوتِ بهینه‌سازی — برنامه‌ریزیِ خطیِ دقیق، فراابتکارِ تکاملی و چیدمانِ هندسی — چگونه می‌توانند در یک معماریِ ماژولار و یک تجربه‌ی کاربریِ یکپارچه کنار هم بنشینند و یک دستیارِ تصمیمِ واقعی بسازند، نه صرفاً یک ماشین‌حساب. مدلِ LP دلیلِ اقتصادیِ جواب را می‌دهد، GA مسیرِ عملیاتی را می‌سازد، موتورِ چیدمان بارگیریِ اجرایی را تضمین می‌کند و چت‌بات همه را به زبانِ مدیر ترجمه می‌کند.

9.1. کارهای آینده

وضعیتِ تحویل

ماژول‌های LP، GA و رابط کاربری کامل و آزموده هستند (154 آزمونِ سبز در مجموع). گزارشِ حاضر فرمول‌بندیِ ریاضیِ کامل را پوشش می‌دهد. کدِ چت‌بات کامل است و برای اجرای زنده تنها به یک کلیدِ معتبرِ مدلِ زبانی نیاز دارد. کلِ سامانه با docker compose به‌صورتِ محلی اجرا می‌شود و آماده‌ی استقرار است.

10 مراجع

  1. Prins, C. (2004). A simple and effective evolutionary algorithm for the vehicle routing problem. Computers & Operations Research, 31(12).
  2. Solomon, M. M. (1987). Algorithms for the vehicle routing and scheduling problems with time window constraints. Operations Research, 35(2).
  3. Mitchell, S., et al. PuLP: A Linear Programming Toolkit for Python. COIN-OR Foundation.
  4. مستندِ رسمیِ پروژه — درسِ برنامه‌نویسی پیشرفته، دانشکده‌ی مهندسی صنایع، دانشگاه صنعتی شریف (موضوع 2).
  5. تعرفه‌ی رسمیِ بسته‌بندیِ تیپاکس — tipaxco.com/value-added-services/packingexpress (مرجعِ ابعاد و قیمتِ کارتن‌ها).
  6. سرویسِ ارسالِ بین‌شهریِ تیپاکس — tipaxco.com/services/intercity (عواملِ تعرفه: وزنِ حجمی، مسافت، ارزش، خدماتِ جانبی).