بهینه سازی و مدیریت بانک خون با پایتون
آشنایی با مسئله مدیریت موجودی فرآوردههای خونی بهعنوان یک مسئله کنترل موجودی فسادپذیر در حوزه سلامت، و حل آن با ابزارهای متنباز پایتون.
هر روز صبح، مسئول بانک خون یک بیمارستان بزرگ با یک صفحهگسترده روبهرو میشود. این صفحه تعداد کیسههای خون موجود را به تفکیک گروه خونی و سن کیسه نشان میدهد. کیسهای که دیروز اهدا شده با کیسهای که سه هفته پیش وارد شده، از نظر پزشکی یکسان نیستند. گلبول قرمز معمولاً حدود ۴۲ روز عمر مفید دارد و بعد از آن باید دور ریخته شود.
مسئول بانک خون باید هر روز تصمیم بگیرد چقدر اهدای تازه جذب کند. باید مشخص کند کدام کیسهها را زودتر مصرف کند تا کمتر دور بریزد. در عین حال باید مطمئن شود که ذخیره کافی از هر گروه خونی در دسترس است؛ برای یک تصادف رانندگی نیمهشب، یا یک عمل جراحی اورژانسی.
این کشمکش همیشگی بین «کمبود» در یک سو و «دورریز بهخاطر انقضا» در سوی دیگر، دقیقاً همان چیزی است. در ادبیات تحقیق در عملیات به آن مدیریت موجودی فرآوردههای فسادپذیر (Perishable Inventory Management) میگویند. بانک خون یکی از پرمخاطرهترین کاربردهای آن در حوزه سلامت است، و در عین حال کمتر شناختهشده.
برخلاف کالای معمولی در یک انبار که فرض میشود تا ابد قابل نگهداری است، خون یک محصول با ساعت شمارششده است. اگر موجودی خیلی کم نگه دارید، هر بیمار اورژانسی که به گروه خونی نادری نیاز داشته باشد میتواند جانش را از دست بدهد. چون خون — برخلاف بسیاری کالاهای دیگر — را نمیشود یکشبه از تأمینکننده دیگری سفارش داد.
اگر هم خیلی زیاد ذخیره کنید، بخش بزرگی از کیسهها به تاریخ انقضا میرسند و باید امحا شوند. این اتفاق هم هزینه مالی دارد و هم از نظر اخلاقی؛ چون هر کیسه دورریختهشده بهمعنای یک اهدای داوطلبانه است که به هدر رفته.
مسئلهای که مسئول بانک خون هر روز حل میکند، در واقع یک مسئله بهینهسازی چندهدفه است. باید همزمان احتمال کمبود و میزان دورریز را کمینه کند. آنهم در شرایطی که تقاضای فردا از قبل دقیقاً معلوم نیست.
اهمیت این موضوع در دنیای واقعی
سازمان جهانی بهداشت تخمین میزند که میلیونها واحد خون در سراسر دنیا هر سال دور ریخته میشوند. دلیل اصلی، مدیریت ناکارآمد موجودی است، نه کمبود اهداکننده. در بسیاری از بیمارستانها، تصمیم روزانه «امروز چقدر اهدا جذب کنیم» هنوز بر پایه تجربه شخصی گرفته میشود. این تصمیم بر اساس قواعد سرانگشتی است، نه یک مدل بهینهسازی رسمی. این موضوع وقتی جدیتر میشود که به گروههای خونی کمیاب فکر کنیم. یا به بحرانهایی مثل پاندمی، که همزمان اهدای خون کاهش مییابد و تقاضای جراحی نوسان میکند.
یک مدل بهینه موجودی خون میتواند مستقیماً روی دو شاخص حیاتی اثر بگذارد: نرخ دورریز خون و نرخ کمبود در لحظات اورژانسی. نرخ دورریز در برخی مطالعات میدانی تا ۲۰-۳۰ درصد گزارش شده است. کاهش چند درصدی در هرکدام از این دو، بهمعنای صرفهجویی مالی برای نظام سلامت است. مهمتر از آن، بهمعنای نجات جانی است که در غیر اینصورت از دست میرفت. از این زاویه، این یکی از معدود مسائل بهینهسازی است که ارزش آن را نمیتوان فقط با عدد و ریال سنجید.
سازمانی مثل کانادین بلاد سرویسز (Canadian Blood Services) تأمین خون بیشتر بیمارستانهای کانادا را برعهده دارد. برای همین مصالحه، یک چارچوب عملیاتی ساده اما مؤثر تعریف کرده است. هر بیمارستان داده مصرف روزانه خود را گزارش میدهد. از آن، تقاضای متوسط روزانه گلبول قرمز یا ADRD محاسبه میشود؛ مجموع واحدهای تزریقشده، دورریختهشده و امحاشده، تقسیم بر تعداد روز.
سپس یک شاخص عملیاتی به نام شاخص موجودی یا Inventory Index (II) تعریف میشود. این شاخص از تقسیم موجودی فعلی بر همین ADRD به دست میآید. به مسئول بانک خون میگوید موجودی فعلی معادل چند روز مصرف است. توصیه رایج این است که موجودی گلبول قرمز معادل ۴ تا ۶ روز مصرف باشد. موجودی پلاکت هم معادل حدود ۲ روز مصرف متوسط نگه داشته شود. این یک قاعده سرانگشتی ساده است که همان مصالحه بین کمبود و دورریز را تقریب میزند، بدون نیاز به حل صریح یک مدل بهینهسازی.
مدل برنامهریزی خطی که در ادامه معرفی میشود، دقیقاً همین مصالحه را انجام میدهد. بهجای یک آستانه ثابت و یکسان برای همه روزها، یک تصمیم بهینه و پویا ارائه میدهد. این تصمیم همزمان چند رده سنی کیسه را میبیند و به شرایط واقعی هر روز حساس است. اگر تقاضای روزانه در این تصمیم قطعی فرض نشود، این مسئله به یک مدل تحت عدمقطعیت تبدیل میشود. برای مبانی این رویکرد میتوانید یادداشت مدلسازی عدمقطعیت در مطالعات سیستم های قدرت را ببینید.
فرمولبندی ریاضی مسئله
سادهترین و در عین حال کاربردیترین شکل این مسئله را میتوان بهصورت یک برنامهریزی خطی چندپریودی مدل کرد (یا خطی عدد صحیح مختلط). فرض کنید افق برنامهریزی شامل روز است. کیسههای خون بر اساس سنشان در رده سنی دستهبندی میشوند (سن یک روزه، دو روزه، تا حداکثر عمر مفید). خون به تفکیک گروه استاندارد ABO/Rh دیده میشود. در نسخه شبکهای مسئله، بیمارستان در یک منطقه با هم در ارتباطاند. پیش از نوشتن معادلات، بهتر است دقیقاً مشخص کنیم هرکدام از متغیرهای تصمیم چه چیزی را نشان میدهند:
مقدار خون تازه گروه است که در روز جذب میشود. هر واحد اهدایی یک کیسه فیزیکی و غیرقابلتقسیم است. پس این متغیر ذاتاً عدد صحیح غیرمنفی (Integer) است. در عمل، وقتی مقیاس مسئله بزرگ باشد (چند ده تا چند صد واحد در روز)، بسیاری از پیادهسازیها آن را پیوسته یا حقیقی در نظر میگیرند. این کار مسئله را به یک برنامهریزی خطی (LP) ساده تبدیل میکند، بهجای یک برنامهریزی عدد صحیح مختلط (MILP) کندتر. خطای گرد کردن حاصل از این تقریب معمولاً ناچیز است.
موجودی کیسههای گروه و سن در پایان روز را نشان میدهد. نشان میدهد چه مقدار از همین کیسهها در روز مصرف شدهاند. هر دو، مثل ، از جنس عدد صحیح غیرمنفی هستند. در عمل، پیوسته یا حقیقی غیرمنفی برای سادگی محاسباتی در نظر گرفته میشوند.
مقدار خون گروه است که در روز دور ریخته میشود، چون به حداکثر عمر مفید رسیده. مقدار تقاضای تأمیننشده (کمبود) همان گروه در همان روز است. این دو هم عدد صحیح غیرمنفی هستند، یا پیوسته/حقیقی در تقریب LP.
متغیر انتقال بینبیمارستانی است. این متغیر مقدار خون گروه را نشان میدهد که در روز از بیمارستان به بیمارستان فرستاده میشود. این متغیر هم عدد صحیح غیرمنفی است، یا پیوسته/حقیقی در تقریب LP؛ دقیقاً مثل بقیه متغیرهای جریان خون در مدل.
اما از جنس دیگری است: یک متغیر باینری (Binary) که فقط مقدار ۰ یا ۱ میگیرد. این متغیر نشان میدهد آیا یک محموله انتقالی بین بیمارستان و در روز فعال میشود یا نه. هر بار حمل خون بین دو بیمارستان یک هزینه ثابت لجستیکی دارد؛ رانندگی، بستهبندی زنجیره سرد، مستندسازی. این هزینه مستقل از حجم محموله است، پس فقط باید یکبار در نظر گرفته شود. این دقیقاً همان نقشی است که یک متغیر باینری در مدلهای MILP ایفا میکند.
با این تعاریف، تابع هدف مدل پایه (تکبیمارستانی، بدون بعد گروه خونی برای سادگی نماد) چنین است:
جمله اول، ، هزینه نگهداری کل موجودی است (جمع روی همه ردههای سنی) در روز . هرچه کیسه بیشتری نگه دارید، هزینه سردخانه و نظارت بیشتر میشود. جمله دوم، ، هزینه دورریز کیسههای منقضیشده در همان روز است؛ یا جریمه اخلاقی/مالی آن.
جمله سوم، ، هزینه یا جریمه کمبود تأمیننشده تقاضا در همان روز است. معمولاً بسیار بزرگتر از و انتخاب میشود. چون پیامد کمبود خون، بهخصوص در اورژانس، با هیچ هزینه مالی معمولی قابل مقایسه نیست. جمع این سه هزینه روی کل افق زمانی روز، همان مصالحهای است که مسئول بانک خون هر روز بهصورت شهودی انجام میدهد. اما اینجا بهصورت یک عدد واحد و قابل کمینهسازی درآمده است.
محدودیت اول مدل، موازنه موجودی بین روزهای متوالی برای هر رده سنی است. موجودی امروز با سن ، همان موجودی دیروز با سن یکروز کمتر است، منهای آنچه از آن مصرف شده:
این معادله عملاً «سنگذری» کیسهها را روز به روز شبیهسازی میکند. کیسهای که دیروز سن سه روزه داشت، اگر مصرف نشده باشد، امروز سن چهار روزه دارد. اما این معادله بهتنهایی نمیگوید موجودی تازه از کجا میآید. برای رده سنی اول () باید یک معادله جداگانه نوشت. این معادله موجودی را مستقیماً به همان متغیر ورودی وصل میکند:
یعنی موجودی یکروزه در پایان روز ، دقیقاً برابر است با خونی که همان روز جذب شده ()، منهای همان مقداری که از همین کیسههای تازه بلافاصله مصرف شده (). این دو معادله با هم کل زنجیره موجودی را مدل میکنند: یکی برای که ورودی را به موجودی متصل میکند، و دیگری برای که سنگذری روزانه را انجام میدهد. هیچ حلقه گمشدهای هم از لحظه ورود خون تا لحظه مصرف یا دورریز آن باقی نمیماند. محدودیت دوم، قاعده تخصیص تقاضا (FIFO) است:
این معادله میگوید مجموع آنچه از همه ردههای سنی مصرف شده باید دقیقاً برابر تقاضای روز منهای کمبود همان روز باشد. برای اینکه مصرف واقعاً از قدیمیترین کیسهها شروع شود، نه بهصورت دلخواه، در پیادهسازی معمولاً یک اولویت روی ردههای سنی بالاتر گذاشته میشود. یا یک هزینه نگهداری تصاعدی، تا سالور خودش کیسههای مسنتر را زودتر انتخاب کند. کیسههایی که به رده سنی حداکثر () برسند و مصرف نشوند، بهطور خودکار وارد متغیر دورریز میشوند.
نکتهای که تا اینجا سادهسازی شده، این است که متغیر ورودی نباید بدون هیچ سقفی هر مقداری بخواهد بپذیرد. آنچه در روز میتواند وارد سیستم شود، محدود به خونی است که واقعاً اهدا شده یا قرار است اهدا شود. این محدودیت با یک قید ساده وارد مدل میشود:
که در آن ظرفیت واقعی عرضه است؛ یعنی مقدار خون گروه که در روز در دسترس بانک خون قرار میگیرد. این خودش یک پارامتر ورودی مدل است که از قبل معلوم فرض میشود، درست مثل تقاضای . یعنی مدل بهینهسازی این عدد را پیشبینی نمیکند، بلکه آن را بهعنوان داده ورودی ثابت هر روز دریافت میکند. مدل صرفاً تصمیم میگیرد چه مقدار از همین عرضه معلوم را بپذیرد. همچنین تصمیم میگیرد کدام کیسهها مصرف شوند، و کجا کمبود یا دورریز رخ میدهد.
نکته مهمی که در فرمولبندی بالا سادهسازی شده، این است که در دنیای واقعی موجودی و تقاضا هر دو باید به تفکیک گروه خونی هم دیده شوند، نه فقط سن کیسه. یعنی همان متغیرهای بالا با اندیس اضافه نوشته شوند: ، ، ، و تقاضای . در آنها یکی از هشت گروه ABO/Rh استاندارد است، مثل O منفی، A مثبت، AB منفی و غیره.
این تفکیک اهمیت زیادی دارد چون گروههای خونی از نظر سازگاری با هم یکسان نیستند. مثلاً O منفی بهعنوان اهداکننده همگانی میتواند در شرایط اورژانسی به هر گروهی تزریق شود. اما عرضه آن معمولاً محدودتر از تقاضایش است. هر گروه، منحنی تقاضا و ریسک کمبود/دورریز مخصوص به خود را دارد.
وقتی موجودی و تقاضا به این شکل به تفکیک گروه خونی دیده شود، امکان یک توسعه طبیعی و بسیار کاربردی باز میشود: هماهنگی بین چند بیمارستان بهجای مدلسازی هر بیمارستان بهتنهایی. این توسعه در اصل مسئله را به یک مسئله انتقالمحور نزدیک میکند. شبیه مسئله مسیریابی وابسته به زمان تانکرهای حمل سوخت، با این تفاوت که کالای جابهجاشونده کیسه خون است، نه بار عمومی.
تصور کنید بیمارستان اول در یک روز از گروه O منفی کمبود دارد. در همان شهر یا منطقه، بیمارستان دوم همان روز موجودی مازاد از همان گروه دارد که در حال نزدیکشدن به تاریخ انقضاست. با متغیرهای و که بالاتر تعریف شدند، این وضعیت مستقیماً قابل مدلسازی است. مقدار انتقالی به موازنه موجودی هر دو بیمارستان اضافه میشود (خروج از ، ورود به ). قید پیوندی زیر تضمین میکند که انتقال فقط وقتی مجاز است که متغیر باینری فعالسازی هم روشن باشد:
که در آن یک عدد بزرگ ثابت است؛ کران بالای منطقی حجم هر محموله. در این نوع قید، یک متغیر پیوسته/صحیح فقط در صورت فعال بودن یک متغیر باینری مقدار غیرصفر میگیرد. این یکی از پرکاربردترین الگوهای مدلسازی در برنامهریزی عدد صحیح مختلط است. اینجا دقیقاً همان نقشی را ایفا میکند که در دنیای واقعی هم وجود دارد: هزینه ثابت راهاندازی هر سفر انتقال خون، مستقل از اینکه چند واحد در آن سفر جابهجا شود.
این دقیقاً همان منطقی است که پشت سامانههای ملی اشتراکگذاری موجودی خون قرار دارد. مثل چارچوب استفادهشده در کانادین بلاد سرویسز که در بالا اشاره شد. این سامانهها موجودی همه بیمارستانهای یک شبکه را همزمان و به تفکیک گروه خونی نشان میدهند. به این ترتیب، مازاد یک نقطه میتواند کمبود نقطه دیگر را قبل از رسیدن به بحران یا دورریز جبران کند.
از نظر ریاضی، این توسعه مسئله را از یک مدل موجودی تکمکانی به یک مدل ترکیبی موجودی-انتقال (Inventory-Transshipment) تبدیل میکند. این مدل روی یک شبکه از بیمارستانها کار میکند که هم بعد سنی، هم بعد گروه خونی، و هم بعد مکانی را همزمان در نظر میگیرد. برخلاف مدل پایه که یک برنامهریزی خطی خالص بود، حالا بهخاطر متغیر باینری ، یک مدل برنامهریزی خطی عدد صحیح مختلط (MILP) است.
پیادهسازی با پایتون
خبر خوب این است که برای حل این مدل، به هیچ نرمافزار تجاری گرانقیمتی نیاز نیست. این مسئله در مقیاس یک بیمارستان یا حتی یک شبکه منطقهای، ابعاد کاملاً قابل مدیریت دارد. حتی اگر بخواهیم دفعات سفارش را هم گسسته کنیم (خطی عدد صحیح مختلط)، کتابخانههای متنباز پایتون بهراحتی از پس آن برمیآیند. میتوان مدل را با Pyomo یا PuLP نوشت. برای حل آن میتوان از سالورهای رایگان مثل HiGHS یا CBC استفاده کرد؛ همان ابزارهایی که در بسیاری از مسائل این سایت استفاده شدهاند.
برای نسخههای تصادفی مسئله — یعنی وقتی تقاضای روزانه قطعی نیست — دو راه وجود دارد. میتوان با شبیهسازی مونتکارلو روی چند سناریوی تقاضا کار کرد، یا از برنامهریزی تصادفی دومرحلهای استفاده کرد. این کار مدل را به سمت واقعیت نزدیکتر میکند. نکته جالب اینجاست که تعداد متغیرها کوچک است (ردههای سنی محدود × افق زمانی نسبتاً کوتاه). حتی سالورهای رایگان روی یک لپتاپ معمولی میتوانند این مدل را در کسری از ثانیه حل کنند. یعنی هر بیمارستان کوچک یا متوسط، بدون بودجهای برای نرمافزارهای تجاری، میتواند از فردا این مدل را پیاده کند.
ظرفیت کار آکادمیک و پژوهشی
مدیریت موجودی خون یکی از حوزههایی است که هنوز بهاندازه کافی کاوش نشده. برای پایاننامه یا مقاله جای کار فراوان دارد. یک مسیر پژوهشی جذاب، تلفیق این مدل با عدمقطعیت تقاضا و عرضه است. میتوان از برنامهریزی تصادفی یا بهینهسازی مقاوم (Robust Optimization) استفاده کرد؛ برای مواقعی که هم اهدای خون (مثلاً در تعطیلات یا بحرانها) و هم تقاضای جراحی نوسان زیادی دارند.
مسیر دیگر، گسترش مدل از سطح یک بیمارستان به سطح یک شبکه منطقهای است. در این شبکه، چند بیمارستان و پایگاه انتقال خون با هم کار میکنند. باید تصمیم جابهجایی کیسههای در حال نزدیکشدن به انقضا بین بیمارستانها هم به مدل اضافه شود؛ ترکیبی از مسئله موجودی و مسئله مسیریابی. همچنین میتوان مدلهای یادگیری ماشین را با این مدل بهینهسازی ترکیب کرد. این مدلها میتوانند تقاضای روزانه را بر اساس تقویم پیشبینی کنند (تعطیلات، فصل تصادفات جادهای). نتیجه، یک سیستم تصمیمیار کامل برای بانکهای خون است.
با توجه به اینکه این حوزه هم بار پژوهشی نظری دارد و هم کاربرد عملی روشن، گزینه بسیار مناسبی است. بار نظری آن، مدلسازی ریاضی موجودی فسادپذیر است. کاربرد عملی آن، نجات جان و کاهش هدررفت است. برای پژوهشگرانی که به دنبال موضوعی با تأثیر اجتماعی مستقیم هستند، این حوزه انتخاب خوبی است.
بُعد دیگری که این مسئله را پیچیدهتر و در عین حال عملیتر میکند، نیاز به تفکیک موجودی بر اساس ویژگیهای آنتیژنی خون است، نه فقط سن کیسه. برای مثال، بیمارستانها معمولاً باید بخشی از موجودی گروه O منفی را جداگانه نگه دارند. همچنین خون آنتیژنمنفی نظیر K منفی را. این ذخیره برای بیمارانی با نیاز مکرر است؛ مثل زنان در سنین باروری یا بیماران با آنتیبادیهای خاص.
این یعنی مدل موجودی دیگر فقط یک بعد (سن کیسه) ندارد. باید همزمان رده سنی و دسته آنتیژنی را با هم مدل کند. این یک بعد تصمیم اضافه است که کمتر در ادبیات دانشگاهی موجودی فسادپذیر پوشش داده شده.
مسیر پژوهشی دیگر، جایگزینی فرض تقاضای کاملاً تصادفی است. بهجای آن میتوان از پیشبینی مبتنی بر برنامههای ازپیشتعیینشده جراحی استفاده کرد. این شبیه به چیزی است که در قالب حداکثر برنامه سفارش خون جراحی (Maximum Surgical Blood Order Schedule) استفاده میشود؛ بهعنوان ورودی مدل. این نوع پیشبینی مستقیماً به دادههای ورودی وابسته است. چون برنامه جراحیهای ازپیشتعیینشده همان منبعی است که تقاضای خون فردا را قابل پیشبینی میکند.
حتی جزئیاتی بهظاهر کوچک هم میتوانند وارد فرمولبندی شوند. مثلاً پرهیز از تحویل تعداد زیادی کیسه با تاریخ انقضای یکسان به یک بیمارستان؛ چون مدیریت همزمان آنها در عمل دشوار است. این میتواند بهصورت یک قید تنوع در تاریخ انقضا وارد مدل شود. این نمونه خوبی است از اینکه جزئیات عملیاتی واقعی زنجیره تأمین خون چطور میتوانند یک مدل ریاضی نسبتاً ساده را به سمت کاربرد صنعتی واقعیتر سوق دهند.
سوالات متداول
آیا این مدل فقط برای خون کاربرد دارد؟
خیر. همین چارچوب موجودی فسادپذیر با تغییرات جزئی جاهای دیگر هم کاربرد دارد. مثلاً واکسنها، بهخصوص در زنجیره سرد. یا پلاکت خون، که عمر مفید آن حتی کوتاهتر از گلبول قرمز است. همچنین داروهای با تاریخ انقضای نزدیک، و مواد غذایی فسادپذیر در زنجیره تأمین.
آیا بیمارستانها همین امروز هم بهنوعی این تعادل را مدیریت میکنند؟
بله، بسیاری از بیمارستانها همین حالا هم از شاخصی ساده به نام شاخص موجودی (Inventory Index) استفاده میکنند؛ یعنی موجودی فعلی تقسیم بر تقاضای متوسط روزانه. این شاخص یک قاعده سرانگشتی برای تصمیم «امروز چقدر سفارش بدهیم» است. مدل بهینهسازی معرفیشده در این مطلب، همان منطق را به یک تصمیم دقیق و بهروز تبدیل میکند؛ بهجای یک آستانه ثابت و یکسان برای هر روز. این تصمیم همزمان چند رده سنی کیسه و چند محدودیت واقعی را میبیند.
برای یادگیری مدلسازی این نوع مسائل از کجا شروع کنم؟
اگر میخواهید مبانی مدلسازی ریاضی و برنامهریزی خطی را از پایه یاد بگیرید، دوره مدلسازی بهینهسازی نقطه شروع مناسبی است.
چطور میتوان عدمقطعیت تقاضا را وارد این مدل کرد؟
بخش عدمقطعیت تقاضا و عرضه معمولاً با برنامهریزی تصادفی یا سناریوسازی مدل میشود. اگر به یادگیری این تکنیکها علاقه دارید، دوره بهینه سازی سیستم های سلامت با پایتون را ببینید. برای پیادهسازی اختصاصی این مدل برای سازمان خودتان هم میتوانید از طریق صفحه مشاوره با ما در ارتباط باشید.
مشاوره و ارتباط با ما
برای مشاوره و ثبتنام در دورهها و دریافت پروژهها با آیدی @pypyid در تلگرام در تماس باشید.