בדוגמה הזו אפשר לראות איך משתמשים במאפייני מעבר כדי לתת עדיפות למסלולים שבהם אותה מכונית מבצעת איסופים ומסירות בקרבת מקום בחלון זמן אחד. מידע נוסף על מאפייני מעבר זמין במאמר Model Business Logic with Transition Attributes.
בדוגמה הזו:
- משלוחים A, B ו-C קרובים זה לזה באותו רחוב.
- בהמשך נשיק משלוחים נוספים.
- לא צוינו זמני אספקה למשלוחים.
- לא משנה מה לוח הזמנים של הביקורים, הרכב צריך לנסוע בכביש הזה פעמיים: פעם אחת בבוקר בדרך מהדיפו, ופעם אחת בערב בדרך חזרה.
- המרחק הכולל של הנסיעה והמשך שלה במסלול תמיד זהים, לא משנה מתי מתבצעים שלבים 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 מעברים:
| מעבר | מרחק | מתחת לסף | מעל הסף | ||
|---|---|---|---|---|---|
| מרחק | עלות | מרחק | עלות | ||
| מחסן →א | 1,000 מ' | 100 מ' | 5 | 900 מ' | 0.9 |
| א→ב | 50 מ' | 50 מ' | 2.5 | פחות מדקה | 0 |
| B→other | 1,030 מ' | 100 מ' | 5 | 930 מ' | 0.93 |
| אחר→C | 1,000 מ' | 100 מ' | 5 | 900 מ' | 0.9 |
| C→depot | 1,080 מ' | 100 מ' | 5 | 980 מ' | 0.98 |
| סה"כ | 450 מ' | 22.5 | 3,710 מ' | 3.71 | |
העלות הכוללת מחושבת כסכום של שתי העלויות לקילומטר:
- העלות לקילומטר מתחת לסף (50) כפול המרחק הכולל מתחת לסף (450 מ' = 0.45 ק"מ),
- העלות לקילומטר מעל הסף (1) כפול מרחק הנסיעה הכולל מעל הסף (3,710 מ' = 3.71 ק"מ).
העלות הכוללת היא 0.45 * 50 + 3.71 * 1 = 22.5 + 3.71 = 26.21.
פתרון 2: מבצעים את הפעולות א', ב' ו-ג' בדרך לשם, ולא מבצעים שום פעולה בדרך חזרה
בפתרון הזה, בניגוד לפתרון 1, כל שלוש המשלוחים מועברים 'כקבוצה' במהלך מעבר אחד בכביש. במעבר השני, הרכב לא עוצר בכלל. שוב, יש 5 מעברים, אבל האורך וההרכב שלהם שונים:
| מעבר | מרחק | מתחת לסף | מעל הסף | ||
|---|---|---|---|---|---|
| מרחק | עלות | מרחק | עלות | ||
| מחסן →א | 1,000 מ' | 100 מ' | 5 | 900 מ' | 0.9 |
| א→ב | 50 מ' | 50 מ' | 2.5 | פחות מדקה | 0 |
| ב'→ג' | 30 מ' | 30 מ' | 1.5 | פחות מדקה | 0 |
| C→other | 1,000 מ' | 100 מ' | 5 | 900 מ' | 0.9 |
| other→depot | 2,080 מ' | 100 מ' | 5 | 1,980 מ' | 1.98 |
| סה"כ | 380 מ' | 19 | 3,780 מ' | 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 |
בכל גרסה, העלות הכוללת הנמוכה מבין שתי האפשרויות מודגשת. אפשר לראות שכאשר משתמשים בעלות גבוהה מעל הסף, העלות הכוללת של המסלול גבוהה יותר במסלול שבו הביקורים מקובצים, וזה הפוך ממה שרציתם להשיג.