برنامه نویسی

مدل انتشار راه حل در جامعه Rust – DEV

تصمیم گرفتم به یک ماجراجویی بروم. من یک شبیه ساز سلولی ساده بیولوژیکی در Rust خواهم نوشت. این اولین بار است که شبیه ساز می نویسم و ​​همچنین اولین بار است که از Rust استفاده می کنم.

در مراحل اولیه فقط برای درک بهتر مفاهیم زیست شناختی از قبل شناخته شده مفید خواهد بود. با این حال، امیدواریم بعداً به آزمایش سؤالات تکاملی و دارویی کمک کند. هدف بلند مدت من شبیه سازی چندین باکتری اشریشیا کلی در یک محیط پیچیده است. این باکتری ها به دلیل اهمیت آنها در سلامت انسان و حیوانات به خوبی مورد مطالعه قرار گرفته اند. آنها می توانند هم به عنوان پروبیوتیک مفید باشند و هم به عنوان پاتوژن مضر.

بامزه ترین اشریشیا کلی که تا کنون با لوگوی Rust در مرکز آن کشیده شده است

من Rust را انتخاب کردم، زیرا زبانی سریع و سطح پایین است. عملکردی قابل مقایسه با C و C++ دارد، اما بر خلاف آنها دارای یک راه حل داخلی و ساده برای مدیریت بسته و تولید اسناد است. من توانستم در 5 دقیقه به عنوان اولین تایمر از آنها استفاده کنم.

با این حال گویاترین شاخص این است که من توانستم ساده ترین اثبات مفهوم را در حدود یک ساعت بنویسم. انتزاعات زبان به نوعی شبیه به این است که من دوست دارم مشکلات را در ذهنم مدل کنم، که عمیقا ذهنی است، اما با این حال تصمیم من را تقویت کرد.

من قصد دارم در مراحل کودکی کار کنم، بنابراین ابتدا یک مدل انتشار بسیار ساده را برنامه ریزی کردم.

اگر در مورد انتشار چیزی نشنیده اید، توضیح اولیه آن آسان است. با توجه به اینکه شما یک مخزن آب دارید و آن را با اکسیژن یا مواد محلول دیگر تزریق می کنید، ذرات آن ماده می توانند آزادانه در هر جهتی حرکت کنند.

بنابراین با توجه به زمان، آنها کم و بیش به طور یکنواخت در مخزن آب پراکنده خواهند شد. با این حال، اگر مخزن آب را با یک غشاء تقسیم کنید، همان نتیجه را خواهید داشت، اما پس از مدت زمان طولانی تر. تأخیر زمانی به نفوذپذیری غشا برای آن ماده داده شده بستگی دارد. هرچه نفوذپذیری کمتر باشد، زمان بیشتری باید منتظر بمانید.

نقاشی من که انتشار مولکول را به صورت نقاط قرمز در یک مخزن آب دو بعدی بدون غشاء و در دیگری با غشاء نشان می دهد.

من اسکریپت پایتون شبه کد نوشتم تا ساده ترین مدل را برای این مشکل ارائه کنم.

def membrane_permeate(a_solvent_o2_count, b_solvent_o2_count, o2_permeability):
    o2_forward = int(round(a_solvent_o2_count * o2_permeability))
    o2_reverse = int(round(b_solvent_o2_count * o2_permeability))

    a_solvent_o2_count = a_solvent_o2_count - o2_forward
    b_solvent_o2_count = b_solvent_o2_count - o2_reverse

    a_solvent_o2_count = a_solvent_o2_count + o2_reverse
    b_solvent_o2_count = b_solvent_o2_count + o2_forward

    return a_solvent_o2_count, b_solvent_o2_count


a_solvent_o2_count = 10000
b_solvent_o2_count = 10
o2_permeability = 0.3
for cycle in range(10):
    a_solvent_o2_count, b_solvent_o2_count = membrane_permeate(
        a_solvent_o2_count,
        b_solvent_o2_count,
        o2_permeability,
    )
    print(f"{cycle},{a_solvent_o2_count},{b_solvent_o2_count}")
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اجرای Rust از نظر منطقی تقریباً یکسان است، اما برای 3 فضای حلال با حجم مساوی در 2 غشا بین آنها.

من یک مدل بسیار ساده شده از فضاهای حلال یک باکتری گرم منفی ترسیم کردم، یک مستطیل بزرگ که به سه مستطیل کوچکتر برای اگزوسول (محیط خارج سلولی، پری پلاسم و سیتوزول) تقسیم شده است.

خب تقریباً یک باکتری گرم منفی است، فقط چند قسمت از آن وجود ندارد. XD

این تصویر نشان دهنده یک باکتری گرم منفی است که هنوز ساده شده است، اما نشان می دهد که فضاهای حلال ذکر شده از نظر اندازه برابر نیستند و همچنین اجسام بسیار بیشتری در داخل و خارج از سطح سلول وجود دارد، مانند دیواره سلولی و پروتئین های غشایی.
(منبع تصویر ویکی پدیا)

همچنین باید توجه داشته باشید که من اصطلاح “exosol” را پیدا کردم. بنابراین در آزمون خود باید آنچه را که معلمتان گفته است بنویسید، که به احتمال زیاد “محیط خارج سلولی” است که طولانی و خسته کننده است اما پاسخ درستی خواهد بود.

بازگشت به موضوع: من عاشق زنگ زدم، زیرا با ویژگی زبان صفت می‌توانستم انتشار را به روشی بسیار نزدیک به نحوه استدلالم در مورد آن برنامه‌ریزی کنم:

“انتشار بر اساس ویژگی غشاها است که می توانند مولکول های بین حلال ها را که از هم جدا می کنند نفوذ کنند.”

و یکی از مهم‌ترین ویژگی‌های هر کد این است که چگونه می‌توان درباره آن استدلال کرد.

پس بیایید کد را ببینیم:

اول من تعریف کردم Solvent ساختار، که تنها یک میدان دارد، تعداد مولکول های اکسیژن. به نظر می رسد که ساختارهای زنگ بسیار شبیه سازه های C هستند، اما در برخی موارد مهم با هم تفاوت دارند. مهمترین تفاوت در مورد این کد، توانایی در Rust برای پیاده سازی توابع متصل به یک ساختار است.

struct Solvent {
    o2_count: i128,
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس من تعریف کردم Membrane همچنین به عنوان یک ساختار، دارای یک میدان تنها، نفوذپذیری آن برای اکسیژن مولکولی، به عنوان یک عامل ساده بیان می شود.

struct Membrane {
    o2_permeability: f32,
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس من تعریف کردم Permeate صفت که روشی با 2 حلال به عنوان پارامتر دارد.

trait Permeate {
    fn permeate(&self, solvent1: &mut Solvent, solvent2: &mut Solvent);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس من آن را اجرا کردم Permeate صفت برای Membrane ساخت. من فقط مقدار شار اکسیژن را در هر دو جهت با ضرب کردن تعداد اکسیژن در چرخه شبیه سازی داده شده با ضریب نفوذپذیری غشاء محاسبه کردم.

impl Permeate for Membrane {
    fn permeate(&self, solvent1: &mut Solvent, solvent2: &mut Solvent) {
        let o2_forward = (solvent1.o2_count as f32) * self.o2_permeability;
        let o2_reverse = (solvent2.o2_count as f32) * self.o2_permeability;

        solvent1.o2_count = solvent1.o2_count - (o2_forward.round() as i128);
        solvent2.o2_count = solvent2.o2_count - (o2_reverse.round() as i128);

        solvent1.o2_count = solvent1.o2_count + (o2_reverse.round() as i128);
        solvent2.o2_count = solvent2.o2_count + (o2_forward.round() as i128);
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت در main عملکرد من بازیکنان را اعلام می کنم: extrasol، periplasm، cytosol، outer_membrane و inner_membrane. بنابراین در یک حلقه شبیه سازی می توانم انتشار در دو غشا را محاسبه کنم.

مهمترین دو خط عبارتند از:

outer_membrane.permeate(&mut extrasol, &mut periplasm);
inner_membrane.permeate(&mut periplasm, &mut cytosol);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این تمام چیزی است که برای محاسبه انتشار در هر چرخه شبیه سازی لازم است. خیلی مرتبه

با این حال در اینجا تابع اصلی کامل است:

fn main() {
    let mut extrasol = Solvent { o2_count: 10000 };

    let mut periplasm = Solvent { o2_count: 10 };

    let mut cytosol = Solvent { o2_count: 5 };

    let outer_membrane = Membrane {
        o2_permeability: 0.3,
    };

    let inner_membrane = Membrane {
        o2_permeability: 0.3,
    };

    println!("cycle,extrasol_o2,periplasm_o2,cytosol_o2");
    for cycle in 1..=10 {
        println!(
            "{},{},{},{}",
            cycle, extrasol.o2_count, periplasm.o2_count, cytosol.o2_count
        );
        outer_membrane.permeate(&mut extrasol, &mut periplasm);
        inner_membrane.permeate(&mut periplasm, &mut cytosol);
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پس تجربه خوبی بود. در نسخه بعدی بازی خود را با توسعه یک مدل انتشار پیچیده تر افزایش خواهم داد، زیرا اکنون با یک مدل قوی بسیار فاصله دارم. یکی از بارزترین محدودیت ها این است که در واقعیت حجم آن حلال ها بسیار متفاوت است. همچنین نواحی سطح غشاء باید در نظر گرفته شود. بنابراین من مدل را با استفاده از قانون فیک بیشتر توسعه خواهم داد. که در پست بعدی توضیح خواهم داد.

اما با این وجود من یک مدل بسیار ساده به عنوان نقطه شروع در راهم به سمت یک مدل باکتریایی زیباتر دارم و همچنین کمی Rust را یاد گرفتم که خوشحال کننده بود.

این پروژه رایگان و منبع باز تحت مجوز GPL 3.0 است و در GitHub قابل مشاهده است.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا