يوضّح هذا المثال كيفية استخدام سمات الانتقال لتحديد أولويات المسارات التي يتم فيها إجراء عمليات استلام وتسليم قريبة من بعضها بواسطة المركبة نفسها في فترة زمنية واحدة. لمزيد من المعلومات عن سمات الانتقال، راجِع Model Business Logic with Transition Attributes.
في هذا المثال:
- عمليات تسليم الشحنات "أ" و"ب" و"ج" قريبة من بعضها البعض على الطريق نفسه.
- سيتم إجراء عمليات تسليم إضافية في وقت لاحق.
- لا تتضمّن عمليات التسليم مُدد تسليم محدّدة.
- بغض النظر عن جدول الزيارات، يجب أن تسير المركبة على هذا الطريق مرتين: مرة في الصباح في طريقها من المستودع، ومرة في المساء في طريق العودة.
- تكون المسافة الإجمالية للسفر ومدة الرحلة على المسار هي نفسها دائمًا، بغض النظر عن وقت تنفيذ الخطوات A وB وC.

في هذه الحالة، وبالنسبة إلى طلب يستخدم فقط التكلفة لكل ساعة والتكلفة لكل كيلومتر، يمكن التعامل مع النقطتين A وB في الصباح ومع النقطة C في المساء، وستكون تكلفة الحلّ هي نفسها كما لو تم التعامل مع النقاط الثلاث في الوقت نفسه.
التكلفة لكل كيلومتر مع حدّ أقصى
لتجميع الزيارات القريبة، عليك أولاً اختيار مسافة حدّية. هذه هي الحد الأقصى للمسافة بين زيارتَين تعتبرهما متجاورتَين. يستخدم هذا المثال حدًا أدنى يبلغ 100 متر، وهو ما يعادل تقريبًا مربعًا سكنيًا واحدًا في منطقة حضرية. يمكنك زيادة الحدّ أو خفضه بما يتناسب مع احتياجات نشاطك التجاري والإعدادات المفضّلة للسائقين.
لتجميع الزيارات القريبة من بعضها البعض ضمن مسافة 100 متر، عليك ضبط تكلفة عالية على أول 100 متر من كل انتقال وتكلفة أقل لأي أمتار إضافية من الانتقال. بما أنّ أول 100 متر هي الأغلى تكلفة، يحقّق المحسِّن أكبر قدر من التوفير من خلال استخدام انتقالات أقصر من حد الـ 100 متر، حتى لو كان ذلك يعني إطالة المسافة الإجمالية للمسار.
لإعداد التكاليف، عليك إضافة إدخال جديد إلى
ShipmentModel.transition_attributes
بالسمات التالية:
- لمطابقة جميع الانتقالات المحتملة، اختَر علامة غير مستخدَمة في أي مكان في النموذج، مثل
UNUSED_TAG. اضبطTransitionAttributes.excluded_src_tagوTransitionAttributes.excluded_dst_tagعلى هذه العلامة. - اضبط
TransitionAttributes.distance_limitمع تحديد الحدّ الأدنى للمسافة والتكاليف:- اضبط
DistanceLimit.soft_max_metersعلى الحدّ المحدّد. - اضبط
DistanceLimit.cost_per_kilometer_below_soft_maxعلى التكلفة لكل كيلومتر أقل من الحدّ الأدنى. - اضبط
DistanceLimit.cost_per_kilometer_above_soft_maxعلى التكلفة لكل كيلومتر فوق الحدّ.
- اضبط
{
"model": {
"transitionAttributes": [
{
"excluded_dst_tag": "UNUSED_TAG",
"excluded_src_tag": "UNUSED_TAG",
"distanceLimit": {
"softMaxMeters": 100,
"costPerKilometerBelowSoftMax": 50,
"costPerKilometerAboveSoftMax": 1,
}
}
]
}
}
يجب عدم استخدام العلامة #unused_tag# مع أي شحنات أو مركبات لمطابقة جميع حالات الانتقال المحتملة. لمزيد من المعلومات، يُرجى الاطّلاع على كيفية مطابقة جميع طلبات الزيارات.
طريقة عمل التكلفة المرتفعة التي تقلّ عن الحدّ
يوضّح هذا القسم كيف تؤثّر التكلفة التي تقلّ عن الحدّ الأدنى أو تتجاوزه في التكلفة الإجمالية للحلول المختلفة في سيناريو المثال.
الحلّ 1: تنفيذ A وB في طريق الذهاب، وC في طريق العودة
في هذا الحلّ، يتم تقسيم الشحنات إلى عمليتَي عبور لهذا الطريق. يتم تسليم اثنتَين منهما في عملية الاجتياز الأولى، ويتم تسليم المتبقية في عملية الاجتياز الثانية. هناك 5 انتقالات:
| الانتقال | المسافة | أقل من الحدّ الأدنى | تجاوز الحدّ | ||
|---|---|---|---|---|---|
| المسافة | التكلفة | المسافة | التكلفة | ||
| depot →A | 1,000 متر | 100 متر | 5 | 900 متر | 0.9 |
| A→B | 50 مترًا | 50 مترًا | 2.5 | 0 متر | 0 |
| B→other | 1030 مترًا | 100 متر | 5 | 930 مترًا | 0.93 |
| غير ذلك→C | 1,000 متر | 100 متر | 5 | 900 متر | 0.9 |
| C→depot | 1080 متر | 100 متر | 5 | 980 مترًا | 0.98 |
| المجموع | 450 مترًا | 22.5 | 3710 متر | 3.71 | |
يتم احتساب التكلفة الإجمالية من خلال جمع التكلفتَين لكل كيلومتر:
- تكلفة الكيلومتر الواحد تحت الحدّ الأدنى (50) مضروبة في إجمالي المسافة المقطوعة تحت الحدّ الأدنى (450 مترًا = 0.45 كيلومتر)
- التكلفة لكل كيلومتر فوق الحدّ (1) مضروبة في إجمالي المسافة المقطوعة فوق الحدّ (3710 متر = 3.71 كيلومتر).
وبالتالي، تكون التكلفة الإجمالية 0.45 * 50 + 3.71 * 1 = 22.5 + 3.71 = 26.21.
الحلّ 2: تنفيذ الخطوات أ، ب، ج في طريق الذهاب، وعدم تنفيذ أي خطوات في طريق العودة
في هذا الحلّ، على عكس الحلّ 1، يتم تسليم جميع الشحنات الثلاث "كمجموعة" خلال رحلة واحدة على الطريق. في عملية التنقّل الأخرى، لا تتوقّف المركبة على الإطلاق. مرة أخرى، هناك 5 انتقالات، ولكن تختلف مدتها وتركيبتها:
| الانتقال | المسافة | أقل من الحدّ الأدنى | تجاوز الحدّ | ||
|---|---|---|---|---|---|
| المسافة | التكلفة | المسافة | التكلفة | ||
| depot →A | 1,000 متر | 100 متر | 5 | 900 متر | 0.9 |
| A→B | 50 مترًا | 50 مترًا | 2.5 | 0 متر | 0 |
| B→C | 30 مترًا | 30 مترًا | 1.5 | 0 متر | 0 |
| C→other | 1,000 متر | 100 متر | 5 | 900 متر | 0.9 |
| other→depot | 2080 متر | 100 متر | 5 | 1980 مترًا | 1.98 |
| المجموع | 380 متر | 19 | 3780 مترًا | 3.78 | |
باستخدام العملية الحسابية نفسها كما في الحلّ 1، تكون التكلفة الإجمالية 0.38 * 50 + 3.78 * 1 = 19 + 3.78 = 22.78، ويكون إجراء جميع الزيارات في فترة زمنية واحدة أقل تكلفة من إجرائها في مجموعتين. يمكنك تعزيز هذا التأثير من خلال زيادة DistanceLimit.cost_per_kilometer_below_soft_max.
سبب عدم فعالية التكلفة المنخفضة لكل كيلومتر تحت الحدّ الأدنى
بما أنّك تفضّل الرحلات القصيرة على الرحلات الطويلة، قد تميل إلى تحديد تكلفة عالية لكل كيلومتر للرحلات الطويلة، وتحديد تكلفة منخفضة لكل كيلومتر للرحلات القصيرة. ولكن هذا يؤدي في الواقع إلى تأثير معاكس، فبما أنّ أول 100 متر من الانتقال هي الأرخص، يستخدم المحسِّن هذه الأمتار "الرخيصة" بأكبر قدر ممكن من التأثير من خلال تفضيل عمليات الانتقال التي تبلغ 100 متر أو أكثر.
يمكنك الاطّلاع على هذا التأثير في نموذجي الحلّ. إذا بدّلت التكلفة لكل كيلومتر بين ما هو أقل من الحدّ وما هو أعلى منه، ستتغير تكاليف المسار على النحو التالي:
| التكلفة المرتفعة التي تتجاوز الحدّ | تكلفة عالية أقل من الحدّ الأدنى | |||
|---|---|---|---|---|
| الحل 1 | الحل 2 | الحل 1 | الحل 2 | |
| عدد الكيلومترات أقل من الحدّ الأدنى | 0.45 | 0.38 | 0.45 | 0.38 |
| التكلفة لكل كيلومتر أقل من الحدّ الأدنى | 1.00 | 1.00 | 50.00 | 50.00 |
| عدد الكيلومترات التي تتجاوز الحدّ الأدنى | 3.71 | 3.78 | 3.71 | 3.78 |
| التكلفة لكل كيلومتر فوق الحدّ | 50.00 | 50.00 | 1.00 | 1.00 |
| إجمالي التكلفة | 185.95 | 189.38 | 26.21 | 22.78 |
بالنسبة إلى كل إصدار، يتم تمييز أقل التكاليف الإجمالية للحلّين بخط غليظ. يمكنك ملاحظة أنّه عند استخدام تكلفة عالية تتجاوز الحدّ، يصبح إجمالي تكلفة المسار أعلى بالنسبة إلى المسار الذي يتم فيه تجميع الزيارات، وهو عكس ما أردت تحقيقه.