import%20marimo%0A%0A__generated_with%20%3D%20%220.9.33%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20from%20mosek.fusion%20import%20Model%2C%20Domain%2C%20Expr%2C%20ObjectiveSense%0A%20%20%20%20import%20mosek.fusion.pythonic%0A%20%20%20%20import%20time%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20sys%0A%20%20%20%20np.random.seed(5)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20Domain%2C%0A%20%20%20%20%20%20%20%20Expr%2C%0A%20%20%20%20%20%20%20%20Model%2C%0A%20%20%20%20%20%20%20%20ObjectiveSense%2C%0A%20%20%20%20%20%20%20%20mo%2C%0A%20%20%20%20%20%20%20%20mosek%2C%0A%20%20%20%20%20%20%20%20np%2C%0A%20%20%20%20%20%20%20%20plt%2C%0A%20%20%20%20%20%20%20%20sys%2C%0A%20%20%20%20%20%20%20%20time%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20Hierarchical%20model%20structure%20allows%20users%20to%20consider%20multiple%20objectives%2C%20and%20the%20trade-offs%20in%20their%20models%20with%20a%20simple%20approach.%20%0A%0A%20%20%20%20%20%20%20%20In%20health-care%20scheduling%20it%20is%20not%20unsual%20to%20see%20objectives%20with%20more%20than%20one%20focus%20points.%20And%20in%20this%20example%2C%20we%20are%20showing%20a%20hierarchical%20model%20structure%20where%20the%20decisions%20are%20made%20minimizing%20the%20overall%20cost%20while%20increasing%20the%20overall%20affinity.%20%0A%0A%20%20%20%20%20%20%20%20Let's%20say%20we%20want%20to%20assign%20a%20set%20of%20healthcare%20workers%2C%20%24w%20%5Cin%20W%24%2C%20to%20a%20set%20of%20patients%2C%20%24p%20%5Cin%20P%24.%20For%20simplicity%2C%20the%20set%20sizes%20of%20both%20groups%20are%20the%20same%2C%20and%20the%20assignments%20of%20healthcare%20workers%20to%20patients%20are%20done%20one-to-one.%20For%20each%20worker%20assigned%20to%20a%20particular%20patient%2C%20there%20is%20a%20cost%20of%20assignment%2C%20%24c_%7Bwp%7D%24.%20And%20the%20proximity%20of%20workers%20to%20patients%20is%20measured%20with%20the%20affinity%20parameter%2C%20%24a_%7Bwp%7D%24.%20%0A%0A%20%20%20%20%20%20%20%20Firstly%2C%20we%20prioritize%20to%20minimize%20the%20costs%2C%20and%20do%20not%20consider%20the%20affinity%20measure.%20Then%2C%20we%20have%20a%20basic%20assignment%20problem%20on%20hand.%20Which%20can%20be%20modeled%20as%20follows%3A%20%0A%0A%20%20%20%20%20%20%20%20%24%24%0A%20%20%20%20%20%20%20%20min%20%5Cquad%20z%20%3D%20%5Csum_%7Bw%20%5Cin%20W%7D%20%5Csum_%7Bp%20%5Cin%20P%7D%20c_%7Bwp%7D%20x_%7Bwp%7D%20%20%0A%20%20%20%20%20%20%20%20%24%24%0A%0A%0A%20%20%20%20%20%20%20%20%24%24s.t.%20%5Csum_%7Bw%20%5Cin%20W%7D%20x_%7Bwp%7D%20%3D%201%20%5Cquad%20%5Cquad%20p%20%5Cin%20P%20%5Cquad%5Cquad%5Cquad%20(1)%24%24%0A%0A%0A%20%20%20%20%20%20%20%20%24%24%0A%20%20%20%20%20%20%20%20%5Csum_%7Bp%20%5Cin%20P%7D%20x_%7Bwp%7D%20%3D%201%20%5Cquad%5Cquad%20w%5Cin%20W%20%5Cquad%5Cquad%5Cquad%20(2)%0A%20%20%20%20%20%20%20%20%24%24%0A%0A%20%20%20%20%20%20%20%20%24%24%0A%20%20%20%20%20%20%20%20x_%7Bwp%7D%20%5Cin%20%5C%7B0%2C%201%5C%7D%20%5Cquad%20w%20%5Cin%20W%2C%20%5C%2C%20p%20%5Cin%20P%0A%20%20%20%20%20%20%20%20%24%24%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Let's%20define%20the%20model%20using%20MOSEK%20Fusion%20API.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(Domain%2C%20Expr%2C%20Model%2C%20ObjectiveSense%2C%20cost%2C%20ones)%3A%0A%20%20%20%20def%20minCostModel(N)%3A%0A%20%20%20%20%20%20%20%20%23Create%20the%20model%2C%20we%20call%20it%20M%20here%2C%20by%20calling%20the%20Model%20class%0A%20%20%20%20%20%20%20%20M%20%3D%20Model()%0A%0A%20%20%20%20%20%20%20%20%23The%20decision%20variable%2C%20x%2C%20is%20created%20using%20the%20Model.variable()%20function.%20%0A%20%20%20%20%20%20%20%20%23Model.variable(variable_name%2C%20dimensions%2C%20variable%20type)%0A%20%20%20%20%20%20%20%20%23As%20defined%20in%20the%20model%2C%20our%20W%20and%20P%20sets%20are%20equal%20sized%20and%202%20dimensional.%20%0A%20%20%20%20%20%20%20%20x%20%3D%20M.variable(%22x%22%2C%20%5BN%2CN%5D%2C%20Domain.binary())%0A%0A%20%20%20%20%20%20%20%20%23Model.constraint(constraint_name%2C%20expression)%0A%20%20%20%20%20%20%20%20%23The%20expression%20is%20constructed%20with%20the%20dot%20product%20operator%20%22%40%22%2C%20to%20ensure%20a%20more%20efficient%20implementation.%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(1)%2C%20the%20dot%20product%20will%20result%20in%20(sum%20of%20x%5Bw%2Cp%5D%20*%20ones%5Bw%2Cp%5D%20for%20each%20w)%2C%20for%20each%20p.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Contraint%20(1)%22%2C%20x.T%20%40%20ones%20%3D%3D%201)%20%23column%20sum%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(2)%2C%20the%20dot%20product%20will%20result%20in%20(sum%20of%20x%5Bw%2Cp%5D%20*%20ones%5Bw%2Cp%5D%20for%20each%20p)%2C%20for%20each%20w.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Contraint%20(2)%22%2C%20x%20%40%20ones.T%20%3D%3D%201)%20%23row%20sum%0A%0A%20%20%20%20%20%20%20%20%23Model.objective(objective_function_name%2C%20objective%2C_type%2C%20expression)%0A%20%20%20%20%20%20%20%20%23Expr.dot(a%2Cb)%20conducts%20a%20element-wise%20matrix%20multiplication.%20Then%20sums%20the%20cells%20values%20and%20outputs%20a%20scalar%20value.%0A%20%20%20%20%20%20%20%20%23Expr.dot(x%2Ccost)%20%3A%20sum%20of%20x%5Bw%2Cp%5D%20*%20cost%5Bw%2Cp%5D%20for%20each%20w%2Cp%0A%20%20%20%20%20%20%20%20M.objective(%22Minimum%20Cost%20Objective%20Function%22%2C%20ObjectiveSense.Minimize%2C%20Expr.dot(x%2C%20cost))%0A%0A%20%20%20%20%20%20%20%20%23solve%20the%20model%0A%20%20%20%20%20%20%20%20M.solve()%0A%0A%20%20%20%20%20%20%20%20%23retrieve%20the%20objective%20value%0A%20%20%20%20%20%20%20%20objective_value_init%20%3D%20M.primalObjValue()%0A%0A%20%20%20%20%20%20%20%20M.writeTask(%22minCostModel.ptf%22)%0A%20%20%20%20%20%20%20%20print(%22Objective%20Value%3A%22%2C%20round(objective_value_init%2C4))%0A%20%20%20%20%20%20%20%20return%20objective_value_init%0A%20%20%20%20return%20(minCostModel%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22The%20initial%20model%20can%20now%20be%20implemented.%20Firstly%2C%20select%20the%20number%20of%20desired%20workers%20and%20patients.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20NodeSize%20%3D%20mo.ui.number(10)%0A%20%20%20%20mo.md(f%22Choose%20the%20number%20of%20workers%2Fpatients%3A%20%7BNodeSize%7D)%22)%0A%20%20%20%20return%20(NodeSize%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(NodeSize)%3A%0A%20%20%20%20N%20%3D%20NodeSize.value%0A%20%20%20%20return%20(N%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Then%2C%20let's%20generate%20a%20data%20to%20use%20in%20our%20model.%20We%20randomly%20generate%20the%20cost%20matrix%20using%20a%20uniform%20distribution.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(N%2C%20np)%3A%0A%20%20%20%20cost%20%3D%20np.random.uniform(low%3D10%2C%20high%3D50%2C%20size%3D(N%2C%20N))%0A%20%20%20%20ones%20%3D%20np.ones(N)%0A%20%20%20%20return%20cost%2C%20ones%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Now%2C%20we%20can%20run%20the%20model.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(N%2C%20minCostModel)%3A%0A%20%20%20%20initialObjective%20%3D%20minCostModel(N)%0A%20%20%20%20return%20(initialObjective%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20With%20this%20solution%2C%20we%20have%20managed%20to%20obtain%20a%20minimum%20cost%20assignment.%20Now%2C%20we%20also%20want%20to%20consider%20the%20affinity%20of%20the%20assignments%20and%20maximize%20it.%20With%20hierarchical%20optimization%2C%20this%20approach%20can%20be%20implemented%20in%20a%20simple%20manner.%20%0A%0A%20%20%20%20%20%20%20%20Let's%20call%20the%20minimum%20cost%20assignment%20value%20%24z%5E*%24.%20We%20can%20change%20the%20objective%20function%20to%20maximize%20the%20affinity%20while%20constraining%20the%20model%20with%20a%20cost%20upper%20bound.%20This%20approach%20will%20allow%20us%20to%20maximizing%20the%20total%20affinity%20while%20still%20maintaining%20the%20minimal%20cost.%20%0A%0A%20%20%20%20%20%20%20%20The%20objective%20function%20maximizes%20the%20total%20affinity%2C%20while%20constraint%20(1)%20limits%20the%20total%20cost%20to%20be%20at%20most%20the%20retrieved%20minimal%20value.%20The%20rest%20of%20the%20constraints%20remain%20the%20same.%0A%0A%20%20%20%20%20%20%20%20%24%24%20max%20%5Cquad%20w%20%3D%20%5Csum_%7Bwp%7D%20a_%7Bwp%7D%20x_%7Bwp%7D%20%24%24%0A%0A%20%20%20%20%20%20%20%20%24%24%20%5Cquad%20%5Csum_%7Bwp%7D%20c_%7Bwp%7D%20x_%7Bwp%7D%20%5Cleq%20z%5E*%20%20%5Cquad%5Cquad%20(1)%24%24%0A%0A%20%20%20%20%20%20%20%20%24%24%20%5Csum_%7Bw%7D%20x_%7Bwp%7D%20%3D%201%2C%20%5Cquad%20%20p%20%5Cin%20P%20%5Cquad%5Cquad%20(2)%20%24%24%0A%0A%20%20%20%20%20%20%20%20%24%24%20%5Csum_%7Bp%7D%20x_%7Bwp%7D%20%3D%201%2C%20%5Cquad%20w%20%5Cin%20W%20%20%5Cquad%5Cquad%20(3)%20%24%24%0A%0A%20%20%20%20%20%20%20%20%24%24%20x_%7Bwp%7D%20%5Cin%20%5C%7B0%2C%201%5C%7D%2C%20%5Cquad%20w%20%5Cin%20W%2C%20p%20%5Cin%20P%20%24%24%0A%0A%20%20%20%20%20%20%20%20One%20can%20also%20decide%20to%20trade%20off%20from%20the%20cost%20and%20prioritize%20the%20affinity%20more.%20To%20achieve%20this%20we%20can%20increase%20the%20cost%20by%20a%20fraction%20and%20resulting%20in%20a%20more%20relaxed%20constraint.%20Let's%20call%20this%20fraction%2C%20%24a%24.%20Then%20constraint%20(1)%2C%20transforms%20into%20the%20following%3A%0A%0A%20%20%20%20%20%20%20%20%24%24%20%5Cquad%20%5Csum_%7Bwp%7D%20c_%7Bwp%7D%20x_%7Bwp%7D%20%5Cleq%20(1%2Ba)z%5E*%20%20%5Cquad%5Cquad%20(1)%24%24%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Let's%20implement%20the%20Maximum%20Affinity%20-%20Minimum%20Cost%20Model%20according%20to%20this%20definition.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(Domain%2C%20Expr%2C%20Model%2C%20ObjectiveSense%2C%20affinity%2C%20cost%2C%20ones)%3A%0A%20%20%20%20def%20maxAffinityMinCostModel(a%2C%20objective_value_init%2C%20N)%3A%0A%20%20%20%20%20%20%20%20%23Model%20definition%2C%20called%20m%0A%20%20%20%20%20%20%20%20M%20%3D%20Model()%0A%0A%20%20%20%20%20%20%20%20%23Binary%20variable%20x%5Bw%2Cp%5D%20is%20defined%20where%20w%2Cp%20in%20N%0A%20%20%20%20%20%20%20%20x%20%3D%20M.variable(%22x%22%2C%20%5BN%2CN%5D%2C%20Domain.binary())%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(1)%2C%20the%20dot%20function%20will%20execute%20(sum%20of%20(x%5Bw%2Cp%5D%20*%20cost%5Bw%2Cp%5D)%20for%20each%20w%2Cp).%20%0A%20%20%20%20%20%20%20%20%23RHS%20is%20relaxed%20by%20%22a%22%20percent.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Constraint%20(1)%22%2C%20%20Expr.dot(x%2C%20cost)%20%3C%3D%20%20(1%2Ba)*objective_value_init)%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(2)%2C%20the%20dot%20product%20will%20result%20in%20(sum%20of%20x%5Bw%2Cp%5D%20*%20ones%5Bw%2Cp%5D%20for%20each%20w)%2C%20for%20each%20p.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Constraint%20(2)%22%2C%20%20x.T%20%40%20ones%20%3D%3D%201)%20%23column%20sum%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(3)%2C%20the%20dot%20product%20will%20result%20in%20(sum%20of%20x%5Bw%2Cp%5D%20*%20ones%5Bw%2Cp%5D%20for%20each%20p)%2C%20for%20each%20w.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Constraint%20(3)%22%2C%20%20x%20%40%20ones.T%20%3D%3D%201)%20%23row%20sum%0A%0A%20%20%20%20%20%20%20%20%23Maximize%20the%20total%20affinifity%2C%20sum%20of%20x%5Bw%2Cp%5D%20*%20affinity%5Bw%2Cp%5D%20for%20each%20w%2Cp%0A%20%20%20%20%20%20%20%20M.objective(%22Maximum%20Affinity%20Objective%20Function%22%2C%20ObjectiveSense.Maximize%2C%20Expr.dot(x%2C%20affinity))%0A%20%20%20%20%20%20%20%20M.solve()%0A%0A%20%20%20%20%20%20%20%20%23retrieve%20the%20objective%20value%0A%20%20%20%20%20%20%20%20objective_value%20%3D%20M.primalObjValue()%0A%20%20%20%20%20%20%20%20%23%20print(%22Objective%20Value%3A%22%2C%20objective_value)%0A%20%20%20%20%20%20%20%20return%20M%2Cobjective_value%0A%20%20%20%20return%20(maxAffinityMinCostModel%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Let's%20generate%20a%20matrix%20for%20affinity%20data%20as%20well.%20We%20also%20create%20a%20list%20of%20%24a%24%20values%20and%20make%20multiple%20trials%20with%20the%20values%20to%20observe%20the%20trade%20off%20between%20affinty%20and%20cost.%20The%20%24a%24%20values%20range%20from%200%20to%20maximum%201%20incrementing%20by%200.05.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20slider%20%3D%20mo.ui.slider(0.05%2C%201%2Cstep%3D0.05%2Cvalue%3D0.5%2C%20show_value%3DTrue)%0A%20%20%20%20mo.md(f%22Choose%20the%20maximum%20alpha%20value%20for%20the%20trial%20range%3A%20%7Bslider%7D%22)%0A%20%20%20%20return%20(slider%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(slider)%3A%0A%20%20%20%20alpha_range_input%20%3D%20slider.value%0A%20%20%20%20alphaRange%20%3D%20(alpha_range_input%2F0.05)%20%2B%201%0A%20%20%20%20return%20alphaRange%2C%20alpha_range_input%0A%0A%0A%40app.cell%0Adef%20__(N%2C%20alphaRange%2C%20np)%3A%0A%20%20%20%20affinity%20%3D%20np.random.uniform(low%3D10%2C%20high%3D50%2C%20size%3D(N%2C%20N))%0A%20%20%20%20%23The%20alpha%20values%20range%20from%200%20to%201%20incrementing%20by%200.1%0A%20%20%20%20alphas%20%3D%20%5Bround(i%20*%200.05%2C%202)%20for%20i%20in%20range(0%2C%20int(alphaRange))%5D%0A%20%20%20%20return%20affinity%2C%20alphas%0A%0A%0A%40app.cell%0Adef%20__(alphas%2C%20maxAffinityMinCostModel%2C%20plt%2C%20time)%3A%0A%20%20%20%20def%20RunMaximumAffinityModel(N%2CinitialObjective)%3A%0A%20%20%20%20%20%20%20%20%23Record%20the%20retrieved%20affinities%20with%20the%20corresponding%20cost%20value%0A%20%20%20%20%20%20%20%20costs%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20affinities%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20start%20%3D%20time.time()%0A%20%20%20%20%20%20%20%20%23Solve%20the%20model%20for%20every%20%22a%22%20value.%0A%20%20%20%20%20%20%20%20for%20alpha%20in%20alphas%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23Get%20the%20maximum%20affinity%20objective%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20M%2C%20maxAff_objective_value%20%3D%20maxAffinityMinCostModel(alpha%2CinitialObjective%2CN)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(%22Objective%20value%3A%22%2C%20round(maxAff_objective_value%2C4)%2C%20%22%20%20%20Cost%3A%22%2C%20round((1%2Balpha)*initialObjective%2C4))%0A%20%20%20%20%20%20%20%20%20%20%20%20affinities.append(maxAff_objective_value)%0A%20%20%20%20%20%20%20%20%20%20%20%20costs.append((1%2Balpha)*initialObjective)%0A%0A%20%20%20%20%20%20%20%20end%20%3D%20time.time()%0A%20%20%20%20%20%20%20%20%23Plot%20the%20Cost%2FAffinity%20Scatter%20Plot%0A%20%20%20%20%20%20%20%20plt.scatter(costs%2C%20affinities)%0A%20%20%20%20%20%20%20%20plt.xlabel(%22Cost%22)%0A%20%20%20%20%20%20%20%20plt.ylabel(%22Affinity%22)%0A%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20%20%20%20%20return%20(end-start)%0A%20%20%20%20return%20(RunMaximumAffinityModel%2C)%0A%0A%0A%40app.cell%0Adef%20__(N%2C%20RunMaximumAffinityModel%2C%20initialObjective)%3A%0A%20%20%20%20runTime%20%3D%20RunMaximumAffinityModel(N%2CinitialObjective)%0A%20%20%20%20return%20(runTime%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20This%20model%20cu%C4%B1rrently%20is%20solved%20in%20seconds%2C%20but%20recalculating%20and%20resolving%20it%20from%20scratch%20every%20time%20the%20cost%20upper%20bound%20changes%20becomes%20slower%20and%20less%20efficient%20as%20the%20number%20of%20workers%20and%20patients%20increases.%20Instead%20of%20starting%20the%20solution%20process%20anew%20each%20time%2C%20we%20can%20parametrize%20the%20model%20and%20use%20a%20previously%20found%20initial%20solution%2C%20which%20will%20significantly%20reduce%20the%20solution%20time%20for%20larger%20instances.%0A%0A%20%20%20%20%20%20%20%20In%20parametrized%20models%2C%20the%20MOSEK%20Fusion%20Solver%20checks%20if%20the%20given%20solution%20is%20valid%20for%20the%20updated%20parameters.%20If%20so%2C%20it%20continues%20searching%20for%20the%20optimal%20value%20starting%20from%20the%20initial%20solution.%20Since%20we%20are%20only%20modifying%20the%20right-hand%20side%20of%20constraint%20(1)%2C%20it%20is%20more%20logical%20to%20increase%20the%20%24a%24%20values.%20By%20doing%20this%2C%20we%20relax%20the%20right-hand%20side%20and%20ensure%20the%20used%20initial%20solution%20value%20in%20other%20models%20(solution%20with%20the%20lowest%20%24a%24%20parameter)%20being%20feasible%20with%20other%20parameters%20as%20well.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22To%20make%20our%20model%20parametrized%2C%20we%20need%20to%20define%20a%20parameter%20variable.%20With%20this%20parameter%20update%2C%20if%20it%20is%20still%20applicable%2C%20the%20previous%20model%20solution%20is%20used.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(Domain%2C%20Expr%2C%20Model%2C%20ObjectiveSense%2C%20affinity%2C%20cost%2C%20np)%3A%0A%20%20%20%20def%20maxAffinityMinCostModelParametrized(a%2Cobjective_value_init%2CN)%3A%0A%20%20%20%20%20%20%20%20ones%20%3D%20np.ones(N)%0A%20%20%20%20%20%20%20%20%23Model%20definition%20called%20m%0A%20%20%20%20%20%20%20%20M%20%3D%20Model()%0A%0A%20%20%20%20%20%20%20%20%23Binary%20variable%20x%5Bw%2Cp%5D%20is%20defined%20where%20w%2Cp%20in%20N%0A%20%20%20%20%20%20%20%20x%20%3D%20M.variable(%22x%22%2C%20%5BN%2CN%5D%2C%20Domain.binary())%0A%0A%20%20%20%20%20%20%20%20%23Parameter%20to%20adjust%20the%20cost%0A%20%20%20%20%20%20%20%20%23Model.parameter(parameter_name%2C%20dimension)%0A%20%20%20%20%20%20%20%20a%20%3D%20M.parameter(%22a%22%2C%201)%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%201%2C%20the%20dot%20function%20will%20execute%20(sum%20of%20(x%5Bw%2Cp%5D%20*%20cost%5Bw%2Cp%5D)%20for%20each%20w%2Cp).%20%0A%20%20%20%20%20%20%20%20%23RHS%20is%20relaxed%20by%20%22a%22%20percent.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Constraint%20(1)%22%2C%20%20Expr.dot(x%2C%20cost)%20%3C%3D%20%20(1%2Ba)*objective_value_init)%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(2)%2C%20the%20dot%20product%20will%20result%20in%20each%20(sum%20of%20x%5Bw%2Cp%5D%20*%20ones%5Bw%2Cp%5D%20for%20each%20w)%2C%20for%20each%20p.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Constraint%20(2)%22%2C%20%20x.T%20%40%20ones%20%3D%3D%201)%20%23column%20sum%0A%0A%20%20%20%20%20%20%20%20%23In%20constraint%20(3)%2C%20the%20dot%20product%20will%20result%20in%20each%20(sum%20of%20x%5Bw%2Cp%5D%20*%20ones%5Bw%2Cp%5D%20for%20each%20p)%2C%20for%20each%20w.%20%0A%20%20%20%20%20%20%20%20M.constraint(%22Constraint%20(3)%22%2C%20%20x%20%40%20ones.T%20%3D%3D%201)%20%23row%20sum%0A%0A%20%20%20%20%20%20%20%20%23Maximize%20the%20total%20affinifity%2C%20sum%20of%20x%5Bw%2Cp%5D%20*%20affinity%5Bw%2Cp%5D%20for%20each%20w%2Cp%0A%20%20%20%20%20%20%20%20M.objective(%22Maximum%20Affinity%20Objective%20Function%22%2C%20ObjectiveSense.Maximize%2C%20Expr.dot(x%2C%20affinity))%0A%20%20%20%20%20%20%20%20M.solve()%0A%0A%20%20%20%20%20%20%20%20return%20M%0A%20%20%20%20return%20(maxAffinityMinCostModelParametrized%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%22%22Now%2C%20our%20model%20is%20parametrized.%20Let's%20run%20the%20model%20with%20the%20same%20%24a%24%20values%20again.%20The%20objective%20results%20should%20be%20the%20same.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(alphas%2C%20maxAffinityMinCostModelParametrized%2C%20plt%2C%20time)%3A%0A%20%20%20%20def%20RunMaximumAffinityParametrized(N%2CinitialObjective)%3A%0A%20%20%20%20%20%20%20%20affinities%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20costs%20%3D%20%5B%5D%0A%0A%20%20%20%20%20%20%20%20start%20%3D%20time.time()%0A%20%20%20%20%20%20%20%20%23Run%20the%20model%20once%2C%20get%20the%20model%20object%0A%20%20%20%20%20%20%20%20M%20%3D%20maxAffinityMinCostModelParametrized(0%2CinitialObjective%2CN)%0A%20%20%20%20%20%20%20%20%23Set%20the%20parameter%0A%20%20%20%20%20%20%20%20a_parameter%20%3D%20M.getParameter(%22a%22)%0A%0A%20%20%20%20%20%20%20%20%23Solve%20the%20model%20for%20every%20%22a%22%20value.%0A%20%20%20%20%20%20%20%20for%20alpha%20in%20alphas%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23Set%20parameter%20value%20according%20to%20chosen%20%22a%22%0A%20%20%20%20%20%20%20%20%20%20%20%20a_parameter.setValue(alpha)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23Reoptimize%20by%20calling%20the%20solve%20function%0A%20%20%20%20%20%20%20%20%20%20%20%20M.solve()%0A%20%20%20%20%20%20%20%20%20%20%20%20%23Get%20the%20objective%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20objective_value%20%3D%20M.primalObjValue()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(%22Objective%20value%3A%22%2C%20round(objective_value%2C4)%2C%20%22%20%20%20Cost%3A%22%2C%20round((1%2Balpha)*initialObjective%2C4))%0A%20%20%20%20%20%20%20%20%20%20%20%20affinities.append(objective_value)%0A%20%20%20%20%20%20%20%20%20%20%20%20costs.append((1%2Balpha)*initialObjective)%0A%20%20%20%20%20%20%20%20end%20%3D%20time.time()%0A%20%20%20%20%20%20%20%20%23Plot%20the%20Cost%2FAffinity%20Scatter%20Plot%0A%20%20%20%20%20%20%20%20plt.scatter(costs%2C%20affinities)%0A%20%20%20%20%20%20%20%20plt.xlabel(%22Cost%22)%0A%20%20%20%20%20%20%20%20plt.ylabel(%22Affinity%22)%0A%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20%20%20%20%20return%20(end-start)%0A%20%20%20%20return%20(RunMaximumAffinityParametrized%2C)%0A%0A%0A%40app.cell%0Adef%20__(N%2C%20RunMaximumAffinityParametrized%2C%20initialObjective)%3A%0A%20%20%20%20runtime_Parametrized%20%3D%20RunMaximumAffinityParametrized(N%2CinitialObjective)%0A%20%20%20%20return%20(runtime_Parametrized%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20Let's%20test%20the%20runtime%20difference.%20You%20can%20change%20all%20the%20model%20outputs%20by%20using%20the%20interactive%20elements.%20Go%20to%20the%20top%20of%20the%20page%20and%20increase%20the%20worker%2Fpatient%20size.%20%3Cbr%3E%0A%20%20%20%20%20%20%20%20_Hint%3A%20Try%20using%20200%20worker%2Fpatients!_%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(runTime%2C%20runtime_Parametrized)%3A%0A%20%20%20%20print(%22The%20runtime%20of%20non-parametrized%20Maximum%20Affinity%20Model%3A%20%22%2C%20runTime%2C%20%22s.%22)%0A%20%20%20%20print(%22The%20runtime%20of%20parametrized%20Maximum%20Affinity%20Model%3A%20%22%2C%20runtime_Parametrized%2C%22s.%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22You%20can%20also%20observe%20the%20trade-off%20relation%20between%20cost%20and%20affinity%20by%20changing%20the%20alpha%20range%20from%20the%20slider!%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22This%20work%20is%20inspired%20by%20Ryan%20O'Neill's%20blog%20post%20about%20the%20implementation%20of%20hierarchical%20optimization.%20Click%20%5Bhere%5D(https%3A%2F%2Fryanjoneil.github.io%2Fposts%2F2024-11-08-hierarchical-optimization-with-gurobi%2F)%20to%20check%20out%20the%20blog%20post.%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
a6e7b634c495ea35320620c3643a46f1c1a5398ac38157ac9e7dfd02f8894f14