import%20marimo%0A%0A__generated_with%20%3D%20%220.15.2%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22!%5BMOSEK%20ApS%5D(https%3A%2F%2Fwww.mosek.com%2Fstatic%2Fimages%2Fbranding%2Fwebgraphmoseklogocolor.png%20)%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(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%23%20Equilibrium%20of%20a%20system%20of%20weights%20connected%20by%20strings%2Fsprings%0A%0A%20%20%20%20In%20this%20notebook%20we%20show%20how%20to%20solve%20the%20following%20problem%3A%20Find%20the%20equlibrium%20of%20a%20system%20of%20masses%20connected%20by%20a%20system%20of%20strings%2C%20with%20some%20masses%20being%20assigned%20fixed%20coordinates%20(attached%20to%20the%20wall%2C%20say).%20See%20the%20next%20picture.%0A%0A%20%20%20%20!%5B%5D(basic.png)%0A%0A%20%20%20%20Suppose%20we%20have%20%24n%24%20masses%20with%20weights%20%24w_1%2C%5Cldots%2Cw_n%24%2C%20and%20the%20length%20of%20the%20string%20between%20%24i%24%20and%20%24j%24%20is%20%24%5Cell_%7Bij%7D%24%20for%20some%20set%20%24L%24%20of%20pairs%20of%20indices%20%24(i%2Cj)%24%20(we%20assume%20%24%5Cell_%7Bij%7D%24%20is%20not%20defined%20if%20there%20is%20no%20connection).%20The%20strings%20themselves%20have%20no%20mass.%20We%20also%20have%20a%20set%20%24F%24%20of%20indices%20such%20that%20the%20%24i%24-th%20point%20is%20fixed%20to%20have%20coordinates%20%24f_i%24%20if%20%24i%5Cin%20F%24.%20The%20equilibrium%20of%20the%20system%20is%20a%20configuration%20which%20minimizes%20potential%20energy.%20With%20this%20setup%20we%20can%20write%20our%20problem%20as%3A%0A%0A%20%20%20%20%5Cbegin%7Bequation%7D%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20minimize%20%26%20g%5Ccdot%20%5Csum_i%20w_ix_i%5E%7B(2)%7D%20%5C%5C%0A%20%20%20%20s.t.%20%20%20%20%20%26%20%5C%7Cx_i-x_j%5C%7C%5Cleq%20%5Cell_%7Bij%7D%2C%5C%20ij%5Cin%20L%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%26%20x_i%20%3D%20f_i%2C%5C%20i%5Cin%20F%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%5Cend%7Bequation%7D%0A%0A%20%20%20%20where%20%24x%5Cin%20(%5Cmathbf%7BR%7D%5En)%5E2%24%2C%20%24x_i%5E%7B(2)%7D%24%20denotes%20the%20second%20(vertical)%20coordinate%20of%20%24x_i%24%20and%20%24g%24%20is%20the%20gravitational%20constant.%0A%0A%20%20%20%20Here%20is%20a%20sample%20problem%20description.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20w%20%3D%20%5B0.0%2C%201.1%2C%202.2%2C%200.0%2C%202.1%2C%202.2%2C%200.2%5D%0A%20%20%20%20l%20%3D%20%7B(0%2C1)%3A%201.0%2C%20(1%2C2)%3A%201.0%2C%20(2%2C3)%3A%201.0%2C%20(1%2C4)%3A%201.0%2C%20(4%2C5)%3A%200.3%2C%20(5%2C2)%3A%201.0%2C%20(5%2C6)%3A%200.5%2C%20(1%2C3)%3A%208.0%7D%0A%20%20%20%20f%20%3D%20%7B0%3A%20(0.0%2C1.0)%2C%203%3A%20(2.0%2C1.0)%7D%0A%20%20%20%20g%20%3D%209.81%0A%20%20%20%20return%20f%2C%20g%2C%20l%2C%20w%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Now%20we%20can%20formulate%20the%20problem%20using%20Mosek%20Fusion%3A%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20mosek.fusion%20import%20Model%2C%20Domain%2C%20Expr%2C%20ObjectiveSense%2C%20Matrix%2C%20Var%2C%20SolutionStatus%2C%20SolutionType%2C%20ProblemStatus%0A%20%20%20%20import%20mosek.fusion.pythonic%0A%0A%20%20%20%20def%20stringModel(w%2C%20l%2C%20f%2C%20g)%3A%0A%20%20%20%20%20%20%20%20_n%2C%20m%20%3D%20(len(w)%2C%20len(l))%0A%20%20%20%20%20%20%20%20starts%20%3D%20%5BlKey%5B0%5D%20for%20lKey%20in%20l.keys()%5D%0A%20%20%20%20%20%20%20%20ends%20%3D%20%5BlKey%5B1%5D%20for%20lKey%20in%20l.keys()%5D%0A%20%20%20%20%20%20%20%20M%20%3D%20Model('strings')%0A%20%20%20%20%20%20%20%20x%20%3D%20M.variable('x'%2C%20%5B_n%2C%202%5D)%0A%20%20%20%20%20%20%20%20A%20%3D%20Matrix.sparse(m%2C%20_n%2C%20list(range(m))%20%2B%20list(range(m))%2C%20starts%20%2B%20ends%2C%20%5B1.0%5D%20*%20m%20%2B%20%5B-1.0%5D%20*%20m)%0A%20%20%20%20%20%20%20%20c%20%3D%20M.constraint('c'%2C%20Expr.hstack(Expr.constTerm(list(l.values()))%2C%20A%20%40%20x)%2C%20Domain.inQCone())%0A%20%20%20%20%20%20%20%20for%20i%20in%20f%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20M.constraint(Var.flatten(x%5Bi%2C%20%3A%5D)%20%3D%3D%20list(f%5Bi%5D))%0A%20%20%20%20%20%20%20%20M.objective(ObjectiveSense.Minimize%2C%20g%20*%20(x%5B%3A%2C%201%5D.T%20%40%20w))%0A%20%20%20%20%20%20%20%20M.solve()%0A%20%20%20%20%20%20%20%20if%20M.getProblemStatus(SolutionType.Interior)%20%3D%3D%20ProblemStatus.PrimalAndDualFeasible%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(x.level().reshape(%5B_n%2C%202%5D)%2C%20c.dual().reshape(%5Bm%2C%203%5D))%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(None%2C%20None)%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%20Matrix%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%20ProblemStatus%2C%0A%20%20%20%20%20%20%20%20SolutionType%2C%0A%20%20%20%20%20%20%20%20Var%2C%0A%20%20%20%20%20%20%20%20stringModel%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%20r%22%22%22%0A%20%20%20%20Here%20is%20a%20quick%20description%20of%20how%20we%20use%20vectorization%20to%20deal%20with%20all%20the%20conic%20constraints%20in%20one%20go.%20The%20matrix%20%24A%24%20is%20the%20incidence%20matrix%20between%20the%20masses%20and%20the%20strings%2C%20with%20coefficients%20%24%2B1%2C%20-1%24%20for%20the%20two%20endpoints%20of%20each%20string.%20It%20is%20chosen%20so%20that%20the%20product%20%24Ax%24%20has%20rows%20of%20the%20form%0A%0A%20%20%20%20%24%24%0A%20%20%20%20(x_i%5E%7B(1)%7D%20-%20x_j%5E%7B(1)%7D%2C%20x_i%5E%7B(2)%7D%20-%20x_j%5E%7B(2)%7D)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20for%20all%20pairs%20%24i%2Cj%24%20for%20which%20%24%5Cell_%7Bij%7D%24%20is%20bounded.%20Stacking%20the%20values%20of%20%24%5Cell%24%20in%20the%20left%20column%20produces%20a%20matrix%20with%20each%20row%20of%20the%20form%0A%0A%20%20%20%20%24%24%0A%20%20%20%20(%5Cell_%7Bij%7D%2C%20x_i%5E%7B(1)%7D%20-%20x_j%5E%7B(1)%7D%2C%20x_i%5E%7B(2)%7D%20-%20x_j%5E%7B(2)%7D)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20a%20conic%20constraint%20is%20imposed%20on%20all%20the%20rows%2C%20as%20required.%0A%0A%20%20%20%20The%20objective%20and%20linear%20constraints%20show%20examples%20of%20slicing%20the%20variable%20%24x%24.%0A%0A%20%20%20%20The%20function%20returns%20the%20coordinates%20of%20the%20masses%20and%20the%20values%20of%20the%20dual%20conic%20variables.%20A%20zero%20dual%20value%20indicates%20that%20a%20particular%20string%20is%20hanging%20loose%2C%20and%20a%20nonzero%20value%20means%20it%20is%20fully%20stretched.%20%0A%0A%20%20%20%20All%20we%20need%20now%20is%20to%20define%20a%20display%20function%20and%20we%20can%20look%20at%20some%20plots.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20display(x%2C%20c%2C%20d)%3A%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20fig%2C%20ax%20%3D%20plt.subplots()%0A%20%20%20%20ax.scatter(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%201%5D%2C%20color%3D'r')%0A%20%20%20%20for%20i%20in%20range(len(c))%3A%0A%20%20%20%20%20%20%20%20col%20%3D%20'b'%20if%20c%5Bi%5D%5B0%5D%20%3E%200.0001%20else%20'b--'%0A%20%20%20%20%20%20%20%20ax.plot(%5Bx%5Bd%5Bi%5D%5B0%5D%5D%5B0%5D%2C%20x%5Bd%5Bi%5D%5B1%5D%5D%5B0%5D%5D%2C%20%5Bx%5Bd%5Bi%5D%5B0%5D%5D%5B1%5D%2C%20x%5Bd%5Bi%5D%5B1%5D%5D%5B1%5D%5D%2C%20col)%0A%20%20%20%20ax.axis('equal')%0A%20%20%20%20plt.show()%0A%0A%0A%40app.cell%0Adef%20_(f%2C%20g%2C%20l%2C%20stringModel%2C%20w)%3A%0A%20%20%20%20def%20_()%3A%0A%20%20%20%20%20%20%20%20x%2C%20c%20%3D%20stringModel(w%2C%20l%2C%20f%2C%20g)%0A%20%20%20%20%20%20%20%20if%20x%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20display(x%2C%20c%2C%20list(l.keys()))%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(r%22%22%22How%20about%20we%20find%20a%20discrete%20approximation%20to%20the%20%5Bcatenary%5D(%23https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FCatenary)%3A%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(stringModel)%3A%0A%20%20%20%20def%20_()%3A%0A%20%20%20%20%20%20%20%20_n%20%3D%201000%0A%20%20%20%20%20%20%20%20w_1%20%3D%20%5B1.0%5D%20*%20_n%0A%20%20%20%20%20%20%20%20l_1%20%3D%20%7B(i%2C%20i%20%2B%201)%3A%201.0%20%2F%20_n%20for%20i%20in%20range(_n%20-%201)%7D%0A%20%20%20%20%20%20%20%20f_1%20%3D%20%7B0%3A%20(0.0%2C%201.0)%2C%20_n%20-%201%3A%20(0.7%2C%201.0)%7D%0A%20%20%20%20%20%20%20%20g_1%20%3D%209.81%0A%20%20%20%20%20%20%20%20x%2C%20c%20%3D%20stringModel(w_1%2C%20l_1%2C%20f_1%2C%20g_1)%0A%20%20%20%20%20%20%20%20if%20x%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20display(x%2C%20c%2C%20list(l_1.keys()))%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(r%22%22%22We%20can%20also%20have%20more%20suspension%20points%20and%20more%20complicated%20shapes%3A%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(stringModel)%3A%0A%20%20%20%20def%20_()%3A%0A%20%20%20%20%20%20%20%20_n%20%3D%2020%0A%20%20%20%20%20%20%20%20w_2%20%3D%20%5B1.0%5D%20*%20_n%0A%20%20%20%20%20%20%20%20l_2%20%3D%20%7B(i%2C%20i%20%2B%201)%3A%200.09%20for%20i%20in%20range(_n%20-%201)%7D%0A%20%20%20%20%20%20%20%20l_2.update(%7B(5%2C%2014)%3A%200.3%7D)%0A%20%20%20%20%20%20%20%20f_2%20%3D%20%7B0%3A%20(0.0%2C%201.0)%2C%2013%3A%20(0.5%2C%200.9)%2C%2017%3A%20(0.7%2C%201.1)%7D%0A%20%20%20%20%20%20%20%20g_2%20%3D%209.81%0A%20%20%20%20%20%20%20%20x%2C%20c%20%3D%20stringModel(w_2%2C%20l_2%2C%20f_2%2C%20g_2)%0A%20%20%20%20%20%20%20%20if%20x%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20display(x%2C%20c%2C%20list(l_2.keys()))%0A%0A%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(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%23%20Duality%20and%20feasibility%0A%0A%20%20%20%20The%20dual%20problem%20is%20as%20follows%3A%0A%0A%20%20%20%20%5Cbegin%7Bequation%7D%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20maximize%20%26%20-%5Csum_%7Bij%5Cin%20L%7D%5Cell_%7Bij%7Dy_%7Bij%7D%20-%20%5Csum_%7Bi%5Cin%20F%7Df_i%5Ccirc%20z_i%5C%5C%0A%20%20%20%20s.t.%20%20%20%20%20%26%20y_%7Bij%7D%5Cgeq%20%5C%7Cv_%7Bij%7D%5C%7C%2C%5C%20ij%5Cin%20L%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%26%20%5Csum_%7Bj~%3A~ij%5Cin%20L%7D%20v_%7Bij%7D%5Cmathrm%7Bsgn%7D_%7Bij%7D%20%2B%20%5Cleft(%5Cbegin%7Barray%7D%7Bc%7D0%5C%5C%20gw_i%5Cend%7Barray%7D%5Cright)%20%2Bz_i%20%3D%200%2C%20%5C%20i%3D1%2C%5Cldots%2Cn%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%5Cend%7Bequation%7D%0A%0A%20%20%20%20where%20%24%5Cmathrm%7Bsgn%7D_%7Bij%7D%3D%2B1%24%20if%20%24i%3Ej%24%20and%20%24-1%24%20otherwise%20and%20%24%5Ccirc%24%20is%20the%20dot%20product.%20The%20variables%20are%20%24(y_%7Bij%7D%2Cv_%7Bij%7D)%5Cin%20%5Cmathbf%7BR%7D%5Ctimes%5Cmathbf%7BR%7D%5E2%24%20for%20%24ij%5Cin%20L%24%20and%20%24z_i%5Cin%5Cmathbf%7BR%7D%5E2%24%20for%20%24i%5Cin%20F%24%20(we%20assume%20%24z_i%3D0%24%20for%20%24i%5Cnot%5Cin%20F%24).%0A%0A%20%20%20%20Obviously%20(!)%20the%20linear%20constraints%20describe%20the%20equilibrium%20of%20forces%20at%20every%20mass.%20The%20ingredients%20are%3A%20the%20vectors%20of%20forces%20applied%20through%20adjacent%20strings%20(%24v_%7Bij%7D%24)%2C%20gravity%2C%20and%20the%20attaching%20force%20holding%20a%20fixed%20point%20in%20its%20position.%20By%20proper%20use%20of%20vectorization%20this%20is%20much%20easier%20to%20express%20in%20Fusion%20than%20it%20looks%3A%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Domain%2C%20Expr%2C%20Matrix%2C%20Model%2C%20ObjectiveSense)%3A%0A%20%20%20%20def%20dualStringModel(w%2C%20l%2C%20f%2C%20g)%3A%0A%20%20%20%20%20%20%20%20_n%2C%20m%20%3D%20(len(w)%2C%20len(l))%0A%20%20%20%20%20%20%20%20starts%20%3D%20%5BlKey%5B0%5D%20for%20lKey%20in%20l.keys()%5D%0A%20%20%20%20%20%20%20%20ends%20%3D%20%5BlKey%5B1%5D%20for%20lKey%20in%20l.keys()%5D%0A%20%20%20%20%20%20%20%20M%20%3D%20Model('dual%20strings')%0A%20%20%20%20%20%20%20%20x%20%3D%20M.variable(Domain.inQCone(m%2C%203))%0A%20%20%20%20%20%20%20%20y%20%3D%20x%5B0%3Am%2C%200%5D%0A%20%20%20%20%20%20%20%20v%20%3D%20x%5B0%3Am%2C%201%3A3%5D%0A%20%20%20%20%20%20%20%20z%20%3D%20M.variable(%5B_n%2C%202%5D)%0A%20%20%20%20%20%20%20%20for%20i%20in%20range(_n)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20i%20not%20in%20f%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20M.constraint(z%5Bi%2C%20%3A%5D%20%3D%3D%200)%0A%20%20%20%20%20%20%20%20B%20%3D%20Matrix.sparse(m%2C%20_n%2C%20list(range(m))%20%2B%20list(range(m))%2C%20starts%20%2B%20ends%2C%20%5B1.0%5D%20*%20m%20%2B%20%5B-1.0%5D%20*%20m).transpose()%0A%20%20%20%20%20%20%20%20w2%20%3D%20Matrix.sparse(_n%2C%202%2C%20range(_n)%2C%20%5B1%5D%20*%20_n%2C%20%5B-wT%20*%20g%20for%20wT%20in%20w%5D)%0A%20%20%20%20%20%20%20%20M.constraint(B%20%40%20v%20%2B%20z%20%3D%3D%20w2)%0A%20%20%20%20%20%20%20%20fM%20%3D%20Matrix.sparse(_n%2C%202%2C%20list(f.keys())%20%2B%20list(f.keys())%2C%20%5B0%5D%20*%20len(f)%20%2B%20%5B1%5D%20*%20len(f)%2C%20%5Bpt%5B0%5D%20for%20pt%20in%20f.values()%5D%20%2B%20%5Bpt%5B1%5D%20for%20pt%20in%20f.values()%5D)%0A%20%20%20%20%20%20%20%20M.objective(ObjectiveSense.Maximize%2C%20-Expr.dot(list(l.values())%2C%20y)%20-%20Expr.dot(fM%2C%20z))%0A%20%20%20%20%20%20%20%20M.solve()%0A%20%20%20%20return%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%20r%22%22%22%0A%20%20%20%20Let%20us%20quickly%20discuss%20the%20possible%20situations%20regarding%20feasibility%3A%0A%0A%20%20%20%20*%20The%20system%20has%20an%20equilibrium%20---%20the%20problem%20is%20**primal%20feasible**%20and%20**dual%20feasible**.%0A%20%20%20%20*%20The%20strings%20are%20too%20short%20and%20it%20is%20impossible%20to%20stretch%20the%20required%20distance%20between%20fixed%20points%20---%20the%20problem%20is%20**primal%20infeasible**.%0A%20%20%20%20*%20The%20system%20has%20a%20component%20that%20is%20not%20connected%20to%20any%20fixed%20point%2C%20hence%20some%20masses%20can%20keep%20falling%20down%20indefinitely%2C%20causing%20the%20problem%20**primal%20unbounded**.%20Clearly%20the%20forces%20within%20such%20component%20cannot%20be%20balanced%2C%20so%20the%20problem%20is%20**dual%20infeasible**.%0A%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(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%23%20Springs%0A%0A%20%20%20%20We%20can%20extend%20this%20to%20consider%20infinitely%20strechable%20springs%20instead%20of%20fixed-length%20strings%20connecting%20the%20masses.%20The%20next%20model%20appears%20in%20%5BApplications%20of%20SOCP%5D(%23http%3A%2F%2Fstanford.edu%2F~boyd%2Fpapers%2Fpdf%2Fsocp.pdf)%20by%20Lobo%2C%20Boyd%2C%20Vandenberghe%2C%20Lebret.%20We%20will%20now%20interpret%20%24%5Cell_%7Bij%7D%24%20as%20the%20base%20length%20of%20the%20spring%20and%20assume%20that%20the%20elastic%20potential%20energy%20stored%20in%20the%20spring%20at%20length%20%24x%24%20is%20%0A%0A%20%20%20%20%24%24%0A%20%20%20%20E_%7Bij%7D%3D%5Cleft%5C%7B%5Cbegin%7Barray%7D%7Bll%7D0%20%26%20x%5Cleq%20%5Cell_%7Bij%7D%5C%5C%20%5Cfrac%7Bk%7D%7B2%7D(x-%5Cell_%7Bij%7D)%5E2%20%26%20x%3E%5Cell_%7Bij%7D%5Cend%7Barray%7D%5Cright.%0A%20%20%20%20%24%24%0A%0A%20%20%20%20That%20leads%20us%20to%20consider%20the%20following%20second%20order%20cone%20program%20minimizing%20the%20total%20potential%20energy%3A%0A%0A%20%20%20%20%5Cbegin%7Bequation%7D%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20minimize%20%26%20g%5Ccdot%20%5Csum_i%20w_ix_i%5E%7B(2)%7D%20%2B%20%5Cfrac%7Bk%7D%7B2%7D%5Csum_%7Bij%5Cin%20L%7D%20t_%7Bij%7D%5E2%20%5C%5C%0A%20%20%20%20s.t.%20%20%20%20%20%26%20%5C%7Cx_i-x_j%5C%7C%5Cleq%20%5Cell_%7Bij%7D%2Bt_%7Bij%7D%2C%5C%20ij%5Cin%20L%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%26%200%5Cleq%20t_%7Bij%7D%2C%5C%20ij%5Cin%20L%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%26%20x_i%20%3D%20f_i%2C%5C%20i%5Cin%20F%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%5Cend%7Bequation%7D%0A%0A%20%20%20%20If%20%24t%24%20denotes%20the%20vector%20of%20%24t_%7Bij%7D%24%20then%20using%20a%20rotated%20quadratic%20cone%20for%20%24(1%2CT%2Ct)%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%202%5Ccdot%201%5Ccdot%20T%5Cgeq%20%5C%7Ct%5C%7C%5E2%0A%20%20%20%20%24%24%0A%0A%20%20%20%20will%20place%20a%20bound%20on%20%24%5Cfrac12%5Csum%20t_%7Bij%7D%5E2%24.%20We%20now%20have%20a%20simple%20extension%20of%20the%20first%20model.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20Domain%2C%0A%20%20%20%20Expr%2C%0A%20%20%20%20Matrix%2C%0A%20%20%20%20Model%2C%0A%20%20%20%20ObjectiveSense%2C%0A%20%20%20%20ProblemStatus%2C%0A%20%20%20%20SolutionType%2C%0A%20%20%20%20Var%2C%0A)%3A%0A%20%20%20%20def%20elasticModel(w%2C%20l%2C%20f%2C%20g%2C%20k)%3A%0A%20%20%20%20%20%20%20%20_n%2C%20m%20%3D%20(len(w)%2C%20len(l))%0A%20%20%20%20%20%20%20%20starts%20%3D%20%5BlKey%5B0%5D%20for%20lKey%20in%20l.keys()%5D%0A%20%20%20%20%20%20%20%20ends%20%3D%20%5BlKey%5B1%5D%20for%20lKey%20in%20l.keys()%5D%0A%20%20%20%20%20%20%20%20M%20%3D%20Model('strings')%0A%20%20%20%20%20%20%20%20x%20%3D%20M.variable('x'%2C%20%5B_n%2C%202%5D)%0A%20%20%20%20%20%20%20%20t%20%3D%20M.variable(m%2C%20Domain.greaterThan(0.0))%0A%20%20%20%20%20%20%20%20T%20%3D%20M.variable(1)%0A%20%20%20%20%20%20%20%20M.constraint(Expr.vstack(T%2C%20Expr.constTerm(1.0)%2C%20t)%2C%20Domain.inRotatedQCone())%0A%20%20%20%20%20%20%20%20A%20%3D%20Matrix.sparse(m%2C%20_n%2C%20list(range(m))%20%2B%20list(range(m))%2C%20starts%20%2B%20ends%2C%20%5B1.0%5D%20*%20m%20%2B%20%5B-1.0%5D%20*%20m)%0A%20%20%20%20%20%20%20%20c%20%3D%20M.constraint('c'%2C%20Expr.hstack(t%20%2B%20Expr.constTerm(list(l.values()))%2C%20A%20%40%20x)%2C%20Domain.inQCone())%0A%20%20%20%20%20%20%20%20for%20i%20in%20f%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20M.constraint(Var.flatten(x%5Bi%2C%20%3A%5D)%20%3D%3D%20list(f%5Bi%5D))%0A%20%20%20%20%20%20%20%20M.objective(ObjectiveSense.Minimize%2C%20k%20*%20T%20%2B%20g%20*%20(x%5B%3A%2C%201%5D.T%20%40%20w))%0A%20%20%20%20%20%20%20%20M.solve()%0A%20%20%20%20%20%20%20%20if%20M.getProblemStatus(SolutionType.Interior)%20%3D%3D%20ProblemStatus.PrimalAndDualFeasible%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(x.level().reshape(%5B_n%2C%202%5D)%2C%20c.dual().reshape(%5Bm%2C%203%5D))%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(None%2C%20None)%0A%20%20%20%20return%20(elasticModel%2C)%0A%0A%0A%40app.cell%0Adef%20_(elasticModel)%3A%0A%20%20%20%20def%20_()%3A%0A%20%20%20%20%20%20%20%20_n%20%3D%2020%0A%20%20%20%20%20%20%20%20w_3%20%3D%20%5B1.0%5D%20*%20_n%0A%20%20%20%20%20%20%20%20l_3%20%3D%20%7B(i%2C%20i%20%2B%201)%3A%200.09%20for%20i%20in%20range(_n%20-%201)%7D%0A%20%20%20%20%20%20%20%20l_3.update(%7B(5%2C%2014)%3A%200.3%7D)%0A%20%20%20%20%20%20%20%20f_3%20%3D%20%7B0%3A%20(0.0%2C%201.0)%2C%2013%3A%20(0.5%2C%200.9)%2C%2017%3A%20(0.7%2C%201.1)%7D%0A%20%20%20%20%20%20%20%20g_3%20%3D%209.81%0A%20%20%20%20%20%20%20%20k%20%3D%20800%0A%20%20%20%20%20%20%20%20x%2C%20c%20%3D%20elasticModel(w_3%2C%20l_3%2C%20f_3%2C%20g_3%2C%20k)%0A%20%20%20%20%20%20%20%20if%20x%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20display(x%2C%20c%2C%20list(l_3.keys()))%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(r%22%22%22%3Ca%20rel%3D%22license%22%20href%3D%22http%3A%2F%2Fcreativecommons.org%2Flicenses%2Fby%2F4.0%2F%22%3E%3Cimg%20alt%3D%22Creative%20Commons%20License%22%20style%3D%22border-width%3A0%22%20src%3D%22https%3A%2F%2Fi.creativecommons.org%2Fl%2Fby%2F4.0%2F80x15.png%22%20%2F%3E%3C%2Fa%3E%3Cbr%20%2F%3EThis%20work%20is%20licensed%20under%20a%20%3Ca%20rel%3D%22license%22%20href%3D%22http%3A%2F%2Fcreativecommons.org%2Flicenses%2Fby%2F4.0%2F%22%3ECreative%20Commons%20Attribution%204.0%20International%20License%3C%2Fa%3E.%20The%20**MOSEK**%20logo%20and%20name%20are%20trademarks%20of%20%3Ca%20href%3D%22http%3A%2F%2Fmosek.com%22%3EMosek%20ApS%3C%2Fa%3E.%20The%20code%20is%20provided%20as-is.%20Compatibility%20with%20future%20release%20of%20**MOSEK**%20or%20the%20%60Fusion%20API%60%20are%20not%20guaranteed.%20For%20more%20information%20contact%20our%20%5Bsupport%5D(mailto%3Asupport%40mosek.com).%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
947c5d73670527d9b5bff073ef02db86b1c776b68eff83af90ebfba694832e81