בדוגמה הזו אפשר לראות איך משתמשים במאפייני מעבר כדי לתת עדיפות למסלולים שבהם אותו רכב מבצע איסופים ומסירות בסביבה הקרובה בפרק זמן אחד. מידע נוסף על מאפייני מעבר זמין במאמר 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
. מגדירים את התג הזה ל-SetTransitionAttributes.excluded_src_tag
andTransitionAttributes.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 |
א→ב | 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 מעברים, אבל האורך וההרכב שלהם שונים:
מעבר | מרחק | מתחת לסף | מעל הסף | ||
---|---|---|---|---|---|
מרחק | עלות | מרחק | עלות | ||
depot →A | 1,000 מ' | 100 מ' | 5 | 900 מ' | 0.9 |
א→ב | 50 מ' | 50 מ' | 2.5 | פחות מדקה | 0 |
B→C | 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 |
בכל גרסה, העלות הכוללת הנמוכה מבין שתי העלויות של הפתרונות מודגשת. אפשר לראות שכאשר משתמשים בעלות גבוהה מעל הסף, העלות הכוללת של המסלול גבוהה יותר במסלול שבו הביקורים מקובצים, וזה הפוך למה שרציתם להשיג.