From 82a2ccb4c2d29c691ffdc710b8b2abbd7db1a74f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sun, 4 Feb 2024 22:14:50 +0000 Subject: [PATCH] build based on 79e2dba --- previews/PR2418/.documenter-siteinfo.json | 1 + previews/PR2418/MathOptInterface.pdf | Bin 0 -> 1281859 bytes previews/PR2418/assets/documenter.js | 898 ++++++++++++++++ previews/PR2418/assets/latency.png | Bin 0 -> 25175 bytes .../PR2418/assets/themes/documenter-dark.css | 7 + .../PR2418/assets/themes/documenter-light.css | 9 + previews/PR2418/assets/themeswap.js | 84 ++ previews/PR2418/assets/warner.js | 52 + previews/PR2418/background/duality/index.html | 80 ++ .../infeasibility_certificates/index.html | 28 + .../PR2418/background/motivation/index.html | 2 + .../background/naming_conventions/index.html | 2 + previews/PR2418/changelog/index.html | 30 + .../PR2418/developer/checklists/index.html | 112 ++ previews/PR2418/index.html | 9 + previews/PR2418/manual/constraints/index.html | 22 + previews/PR2418/manual/models/index.html | 2 + .../PR2418/manual/modification/index.html | 151 +++ previews/PR2418/manual/solutions/index.html | 35 + .../PR2418/manual/standard_form/index.html | 6 + previews/PR2418/manual/variables/index.html | 13 + .../PR2418/reference/callbacks/index.html | 32 + .../PR2418/reference/constraints/index.html | 12 + previews/PR2418/reference/errors/index.html | 48 + previews/PR2418/reference/models/index.html | 132 +++ .../PR2418/reference/modification/index.html | 31 + .../PR2418/reference/nonlinear/index.html | 78 ++ .../PR2418/reference/standard_form/index.html | 992 ++++++++++++++++++ .../PR2418/reference/variables/index.html | 24 + previews/PR2418/release_notes/index.html | 30 + previews/PR2418/search_index.js | 3 + previews/PR2418/siteinfo.js | 1 + .../submodules/Benchmarks/overview/index.html | 20 + .../Benchmarks/reference/index.html | 17 + .../Bridges/implementation/index.html | 32 + .../Bridges/list_of_bridges/index.html | 110 ++ .../submodules/Bridges/overview/index.html | 53 + .../submodules/Bridges/reference/index.html | 226 ++++ .../FileFormats/overview/index.html | 147 +++ .../FileFormats/reference/index.html | 18 + .../submodules/Nonlinear/overview/index.html | 183 ++++ .../submodules/Nonlinear/reference/index.html | 147 +++ .../submodules/Test/overview/index.html | 166 +++ .../submodules/Test/reference/index.html | 52 + .../submodules/Utilities/overview/index.html | 250 +++++ .../submodules/Utilities/reference/index.html | 296 ++++++ .../tutorials/bridging_constraint/index.html | 102 ++ previews/PR2418/tutorials/example/index.html | 45 + .../PR2418/tutorials/implementing/index.html | 114 ++ previews/PR2418/tutorials/latency/index.html | 129 +++ .../manipulating_expressions/index.html | 22 + .../PR2418/tutorials/mathprogbase/index.html | 54 + 52 files changed, 5109 insertions(+) create mode 100644 previews/PR2418/.documenter-siteinfo.json create mode 100644 previews/PR2418/MathOptInterface.pdf create mode 100644 previews/PR2418/assets/documenter.js create mode 100644 previews/PR2418/assets/latency.png create mode 100644 previews/PR2418/assets/themes/documenter-dark.css create mode 100644 previews/PR2418/assets/themes/documenter-light.css create mode 100644 previews/PR2418/assets/themeswap.js create mode 100644 previews/PR2418/assets/warner.js create mode 100644 previews/PR2418/background/duality/index.html create mode 100644 previews/PR2418/background/infeasibility_certificates/index.html create mode 100644 previews/PR2418/background/motivation/index.html create mode 100644 previews/PR2418/background/naming_conventions/index.html create mode 100644 previews/PR2418/changelog/index.html create mode 100644 previews/PR2418/developer/checklists/index.html create mode 100644 previews/PR2418/index.html create mode 100644 previews/PR2418/manual/constraints/index.html create mode 100644 previews/PR2418/manual/models/index.html create mode 100644 previews/PR2418/manual/modification/index.html create mode 100644 previews/PR2418/manual/solutions/index.html create mode 100644 previews/PR2418/manual/standard_form/index.html create mode 100644 previews/PR2418/manual/variables/index.html create mode 100644 previews/PR2418/reference/callbacks/index.html create mode 100644 previews/PR2418/reference/constraints/index.html create mode 100644 previews/PR2418/reference/errors/index.html create mode 100644 previews/PR2418/reference/models/index.html create mode 100644 previews/PR2418/reference/modification/index.html create mode 100644 previews/PR2418/reference/nonlinear/index.html create mode 100644 previews/PR2418/reference/standard_form/index.html create mode 100644 previews/PR2418/reference/variables/index.html create mode 100644 previews/PR2418/release_notes/index.html create mode 100644 previews/PR2418/search_index.js create mode 100644 previews/PR2418/siteinfo.js create mode 100644 previews/PR2418/submodules/Benchmarks/overview/index.html create mode 100644 previews/PR2418/submodules/Benchmarks/reference/index.html create mode 100644 previews/PR2418/submodules/Bridges/implementation/index.html create mode 100644 previews/PR2418/submodules/Bridges/list_of_bridges/index.html create mode 100644 previews/PR2418/submodules/Bridges/overview/index.html create mode 100644 previews/PR2418/submodules/Bridges/reference/index.html create mode 100644 previews/PR2418/submodules/FileFormats/overview/index.html create mode 100644 previews/PR2418/submodules/FileFormats/reference/index.html create mode 100644 previews/PR2418/submodules/Nonlinear/overview/index.html create mode 100644 previews/PR2418/submodules/Nonlinear/reference/index.html create mode 100644 previews/PR2418/submodules/Test/overview/index.html create mode 100644 previews/PR2418/submodules/Test/reference/index.html create mode 100644 previews/PR2418/submodules/Utilities/overview/index.html create mode 100644 previews/PR2418/submodules/Utilities/reference/index.html create mode 100644 previews/PR2418/tutorials/bridging_constraint/index.html create mode 100644 previews/PR2418/tutorials/example/index.html create mode 100644 previews/PR2418/tutorials/implementing/index.html create mode 100644 previews/PR2418/tutorials/latency/index.html create mode 100644 previews/PR2418/tutorials/manipulating_expressions/index.html create mode 100644 previews/PR2418/tutorials/mathprogbase/index.html diff --git a/previews/PR2418/.documenter-siteinfo.json b/previews/PR2418/.documenter-siteinfo.json new file mode 100644 index 0000000000..2b35c7c92a --- /dev/null +++ b/previews/PR2418/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2024-02-04T22:08:42","documenter_version":"1.2.1"}} \ No newline at end of file diff --git a/previews/PR2418/MathOptInterface.pdf b/previews/PR2418/MathOptInterface.pdf new file mode 100644 index 0000000000000000000000000000000000000000..580cb7632c7595a5788e53d40d3dca3351853952 GIT binary patch literal 1281859 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

pfvacC;9QGqcX7?>UWyrA_ZYe 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%0D!qSNDa2C)zCc(d2jiMq_#3vwB6)i(5)unQpZ z$wDpJ)Sw|M9m0!NiZBuAM4>CZZ((Mn_yN+<>_R?W14jKR5^1erF`V=AZ|w; z&ymJO?wF8s*)MtaIDD5Ko@1+6AuONyR{VIYsTzb3oUL($ZhfY>7>8(BuH^oLpw^$a znO}M*HU%5I@Nm>Q5JU&rYZa0I)bam~_DD|AEK`-yyUlP5@=o_a*}5uojc(h!cVfSr zNNuLn2j8s0ZvFkX-95bRp7InqDwscvti(lJ1Akh{nSxbKXnQjj_Ca4#>gh8IK`srY zrcFh~(H%BGfuuQ!whV@^xN2C;*FwzXx%uuh7Ej-HMi%N~yXXyf#iM~+X6}QUK|1-F zNzfkZX&2uO9@X4;BVUJJ-;K&qgM5PnCSVi(r>={aPRw?_{X09= z7r6nSqi@+V!Wy#y>!Eo@Ku=#Abgv)BeSQ&=D3Vkx@2KQC5&(Kkk`hrQ7Ku+9yFJ?& zDm@t-oZL$#D<&K5`Xeh#r$+{e$Novh4x`D$L6D|m=;@L9?Qy8B`O4EL=Tw9IiT!!C zXK{U#bPGTL^f~mEy+AmSyN5MfcMoa6!7DP<+e>ACODh*26G@aoKEjbK?4EfN^rp;i z$_v3ZFQ|<~aF2$;!99#|b5o>5a0j6r)bX=2SqmOhaeCAu%ao^n2qp$TFV&|1SD|#=a^t1IX=w5N;-fkVY`VSN?7G!Oz9U%6h@Ewmp!olLYr8Y zC~J%zazAP_GQ%>!J{a+zTeGM$`fO2b`e@tC$RWlfq#5GalT!S`{O4G&P!)uWC?#R+ zL)g)!I;+z3vHggK9idd5Z_Ns#J(i7;0g@`?HOZRrK3*Dqgepm|l^k{g=t+CLYdu;P zi_ju#;$=kw`5Hyy$l&I$_SnN@@sUjZ+VOFc>C(bZ)Jqd;S8q%g&O_m#vE|6bs@!cM zLoJ?w9_dmru`&3Hq!JNzS-MwEl|}0nwLJ+uCM840vE4F-X}!4i692tGj-0KG6bdT# z?J>9W?H*dICag zIsD&eHLWANEZAGx=<9-dKp+ge_{8@)|;Kkr$OZz{@-#@k$s0cLaXuCXI+ttU*9IlB6uO`xZ|1 zJE3yM-M{C^2N`aKxnjQ!+I!Ti>UWCGv#qKCJ!KQ{FCkxon@8Vo7N%!v@dcq)U6(^9 zrv#IB^q|I1k!!R3d5z<&4f4bwdhqZc!IEe#C-_OCOxFmGd}#0<88cgmcIXLFdT@WQ zpVxJz9$dZX7>m>ozt?qzZ3I28D4cz(*}m6zaaG@K~r4oF~|SO@puh?4iW`J!Y>*@1KoYtG=1es6xZ0&ubScUu)m&xn~E^Zj!%9>>bMOtg0rY;~lHIU~5(pJMh=O1A|j zOW#pxcDPEgFuJPy=sgxRp)uU7W|!SR#MvFi4NxO|f3A~vje*(MY%Jp?naWY2aazR~ zn-{#}n~i9Tvkf*YE87=O6%X!A97GD5^l`_2Pttc9z^#Ym96tbeV){4Vu)!a?q^f4P z96x{=40XQG`yD&IpSyP~;`D{q9}yT{f59k#*yj{I(9kZqK+B#5E_0}PYaS7`+A3M= zAOs#%!xaCOvpfSbNE2_Ccb*uqlI{>5UZT=SoKygd5Kox)Fycvanb&Sy;+A8M1m)n^ zSJZNRTW?VBfrwg(sq<`pz>A&#JFG{W858*vT<)R`heEjz)g`W1O|qE4u7Ji|Q~MhQ~>}PtT-9Vl6($<=i?3q)VaYlIj=Qvuqh4b72Bjh z2TIvW_3HEG0&Cv~xa#CQ{cIDmJdM@0V*zUBWI#;wY+~lsKm@!WGNbGAOgCA}H!w5W z_E;`W_Ap&+qlyTM+B=65wXw>ru`ZX5iX1hkZ6_~p+ip5SAybPHp{CvfpYDfO**Y2E?x5Pi1EyGqGN)C zb7QM8MII(75D&%4w=SW)6w9an3kJ!61%1UqT6VJfY-j^+rBL5U+|wWWI@Ztbi8C@Ivk2EQ|>gk_fwouLo#qeH~$_pIGPNrSA_||#mu?@ zPSZ@?yphXFv*|$ymMKBx#d2b9jefiH$EucprAxgj$BaPD7V`JHVYhX})BP$gn+pZR za^3KRHb%1ei&AB=`OS!MY;}fU+huG>{uY@{y&f)ACysqqo$=tTyA@vu&HGlhrA}xx2<;&J+@NLfp;d7peF&;AQEk| z8n&5C3X>Cw_-Zj{{*tPwd(+y_H(txye0*^;uC_-2R1Dk(sT;eSjTQlIA6Rfo2Ei-X zwwjxX_3`2vNeegPNS{`7c%#ABaP855o0}!H$i-d#IQq3YW~e<~_-2(6=tPFd^Ex@# zCI2p`v&)S_-a^u|ERiW{ic%x2tixjdL5ZPDW(%!u%%FV#TGPnhvU~=-P-)T|XuLG# zN16s*mtj-I4aWH!s1kanLP0DWF+)IEj}B+Zc=!c0rBS|gbi%>K#duXXRS;{MCeXm3 zM_VD!6RVC#ib8f9>BZo=_D%|?cp)P@Qy7Z?Q?B~3O;ot9bmkizd8kZ*Hdb{l;a?lo zX~oRaVuSI}-^AAJbB`w7F^?-smT|-NNXZP1X>L-@{0P+^>J?htnb)LhXQ>TL`1j?9 zk}Kq!5B(ydG(j<_{d+~pvW#2G5Fh7xs}U2Wd&y9<$jRjF)#K|9k%{Q9!c`Z~nmx*Q zPg(W{7t=Sx%H6~BU^{%&k|YvwQ-w{}Z0xBARiD2}@467VD<{ZQo-KC`bJU*dPNT#w z#`7bRg(gSV<(&QfqVr%5w!5jghZ%a5=+0yIHTg{v?^9}LpV+S69W<>3S6ON?^AI=} zLNa!yC3|<2VatV$3sud*g@j>}^ZWcO#!yS&x7|&RvMX>c#*m_o6?_JP>&2-qGiT!< zMQSKoB3oM?;Cuge<5aVaNGUZ>-p(Rm>T8;%v!O+JM?@}-qK z!Gv^oJqrQznF|}g3}vHBU;bs?4^VJpW<2hxwWv)(DKs})0>x!3*mk`eR3j#1OHA%2;PfIn@rfV4AjviReh zH!Bh(F7GRkB`W44ge4k!x6KNZ0Ov@GrF>-o-hSL!Y*lU-Uo$N43il5=puo97IKVm~ z<9@L}yMmf=YvCu*p_omCeK2cYEkh}2X^O+?LUufwTtP^8^(ni-817F$!TVc+9i7uq zPhiY@a!+7R>J@lgy#B7J&+SKzH*Y??_TP!vX9m}E>oXAbtHAN<0-VRAp`z1E)E;Da zN0Q-yT8D*@gb0kfV>nMTobuC=H&vYB3s{p&K{5C6)C2&H(!doN|J)UwyeN{NTfpe8 z0C3g%-s0MiXW0#eU1`egCD(aAg0(kj2;{hu|JXbKPt__5>;H@V#s5F$MXF5NZqOri zT~NIOo4Sr43Gw6i$sPc7H{VvDmWw-1pesFUIfO}2qaU*a@aRLJgTMfR0S2NC({bI($GE_i zYl6A|X}kTVxn=;tGKuL_`xFv7xGtSyNU-ueFLxaEXfCE*@!@o>Z18I158nb7sYDG{ z!US&ZcJI$TPG-JNul)c-fNC$y`EVZbRe5UPFPN19O|~i;k5NdhT39fAa>w+ApPUQ* zw~^KL_QZPX@7}`8MN~L_IsMV-fzd;wpoJ1oqFpb*_xkj0iORL3wQv-5s3e?1moOU? zfq>NAO8$}KjiKePfEkjA5>S(M`(?yjX!(FIHAc%Y`i2i#H~$BOF8ETLwFcU z*HBPe(0XUpb?3!e>T21QD0ByxW;g3i{M+8#s7$z}eCNdxDF5LMGP3^vJemJHP5}oy z!~cgVU}NI=uXHg>nl^U7n1b(XJ%K#EdHB7AEDX3(2%y7aS)`#bgHnDiA$r;QVbzLL z7>neRpPt#(YxnXqLKHRhtdc!NoXM=ko zX&>|U0+DUOkTh=4Xqar&yERSMA(~^NX;KuS2}N4ilFy}-GJUil^~SkW_>J#de!LQ`|D=n_zZf}l>4nc75?y!mF0-lS(IgYuIOv*zz8s#pDUvD3>k5dgbWVbIybQX57$GLq;q0R@8CRKol<&iDC3xOZH%) zsA)Z!2?H`e6cHGw9p#{n2~&OfBY-_v2P6l0m^YLL)W5SQg%}uZPSm|)k`oAt=X&3d z-+ukw`JErm%%~pR-rw6l+U?|IeR09$*3QJHp41{n@Z!My#p=QBaZg^+)1{6bQM0FH z?5Yel6rI5jHWV~brc@At519qB{c(J?eEPC{W%Lfhp@sw$7KOT})k@&|8}ZYUz1mCL z1@ED`LXNs~LCiq3PVSc$zbu|vR*lWQ<{7isc(H*OO;*Xo{`i8X_wj?*jWg)4{EWlQV=T7drS0S+KVjn;ayei%p<*q#WgAo_rsK zFD_}Q5?e$K9gQqBwrFGL!_4t{dAi7@l^ac5sT{=HyBnXC+B}upIgag}{vMNCp8Y(c z0w~#|(1ZDTJ?RCS7m6=4OD!!0_X0mGs$a@kQ}B~yBO1INK6iHczTet6#~33E+Ius^ zPCYTpuj>7NO1-O0JuuV`>H6L~JGUOfl#AD`8)>X2?l0T)dZ;AKWy!kjQ9ej9L z`Zsy>YU%!cw6OPaM0e0Xg37Dcr7@7+=-|Ps%f2buI~aL1e189F?omHt{d2Z<|7v{q zcAnZZi}D&|$l3SlG&NK>?`bF(9_fO2Hp%C)q!rF5Xh)(ZniKU+3=S_t5yVm87(aly zNEpwSi>^WK89?{Sz2luZlJ9||%2(F=HXCVP`JIHw&<+ctr7Z&&b4YjjZpQQOidJukGg5@l~p!NW|bP%F}i z)v2u`=wh{Oh^%O46y&x|fLrG7)`an#@vX76Tg%x@iI-Br zz>ZK)uM)5r7fj2euw8t7k-Eu|M2yr{PTRT;0wEWh`Avuf*6l-gik^_QQ&vdo>$eJ z*FGPJ@OdYzZ%36uQ5YU!mdEv*>@&Bl&Wp|n@F(KX>X!p8eZ6F(`-#fvj+*M4Yumzd z-hwo{A=IArmd9HbaGe5!vWQT? zDO9g02>b-BAoXt(lJZY5#BnD6q-!OJ{V(&a?>6uy{| zYT9E1_x%c-WXTUT?hawJcnn7Ou_6QwB^US4oL!wAXyK~Kj{KZ?rXO^OW2G^v3p7pJ z=09FGFzr^kIcvF_PO%2!uu;d@_%LZ<)gJ=<;_EE$gjFN_;(M?n>C4pGnS;;a(`1JH zXlZjIrbm6j_t(rq%};c!qfL2*OFC2MM0SZ#OPZFv2 zrO=Z7+H9fqEeJP8e-Swq2bkYZxtHY z$^v71JLdzaTK;77RPerys+g7tSRJ^)w~&nrl@p6h|%lL-DNG@(HR{hoxqaO-INJf+wmc{L&?z(JymUtg{L?L;S2So(ih!KW!a#(pd&vRt9=50Bl-4br!dvJ_2#){wI zEK59QH)Nxq0rlK$2NnbO%wM_$@$7Z$|Acx`=-T|$_TG7nT|EB)LU~5k{DW)7YD!BfEua2 z#GfoETTc~Jl+`2S@bOG|@^$}36oD8hiuyfl%iQRZ2HO#TQ=W;~({q#u$G@I$Jbpwb ztxH(IyK7MN?;hR#?c=)4iH2ntx^ny5^`i;Nl^@vb8%^(rwyZ@M)dZyw{9;5B6LeJ` z^TC<3eG{%>>QmO3&)eyEwASGb`1|aaL6-s^-K2@p3Lu3U(mj-3Q^+|obKxgFk|Bkx zl{?#u?G~cnf6sFh;i6)S|7z@4Xe}c>HQO$8e9an_I`%u1D7dhRys$=UQKk(U{iX}s zH8OW70F|f|>~3V%DSZcTc$7X(ifB2Vai64C&tE2c+ul;~TsT!Y8!dt79zpJm^ciPa zp!&GYMpTu}n!8op@0sj?y(t<~6B6uhwbtdD)OM8Et7(vqGM5_5A6iL+H+!{kdhp{_ z9=>tKP2oi}O|~fbYo&5)Rd2&0woFRF0?79Glr0-=wr= zT<(su^)(poSR8mtnkTCg7u0D^F6|o;K*VKqeyfG^&q{&y{c_1uQ(dwA8t!q-6`XZk;<}(N^P3kAkwb^Y1JQVJ- z&zVy#s`MoFEkZszh=Y)SmgPm)h~4}uVJfOkkk>u7-CDk~Y-S^ikFv)#P2d`Qk#MoG zNF}M!Cs!eKw6U!eF;vg7lR1MC)Y*9y-K_Ra`^mk z!V=|D#XtgX5oH6PZWhkbjIFidTZbLueoV}Xs3@oQ5s!%fQKitN$nuXT#ICTgPKfkv zXxoB_;8KbZTno0=baiZ63rodLb6~y5XM1>IFW3}UD0lhZKHg{3oL>$|q3y;IysukU zbETLeDbLGqbA5Ja8&IA@2o7b3B4N1y)0R_-MbNDx6ixF$7rA4K!-zkWYd0kv`cR)I>(U(A@E;AmRI?hp#Z z2wGhZG5Tt1%w>?c)vu@q%Ell;D7BNLRNVI*)!P5*Lprp&PRd+jMg%u3(fh1k71F(6 zv0}?XHeXQWslhh+=HL@HIj?wRtH2xrDera?(yYR!0SUfxue5M<9mRbxz23QnI4LA& zpxePNEMg$gpwKs;h1z=!k*027o-RuDpH3=F&s)8rFYT;3mfsrGl%2Rj8L#k-Lrj?1Z{7tdeF2KX^O&vM&s+AXJJB`(QS@N>6N%YAd$eqO&%dD$P z-u!@y>imh#KXjm{_c`T2WKEujDHN-iV=k$oYDtcaPrEkCCbu=0ChWIDMT6-MHR{&Y zHyB+vZa|jFO*VrnJl5Tn4BZ5UuSsBSEyv23@=qR4FWTr8t~L5=?E}dt z)XwZ_EqXAV1LlsypxFE&$Dv}_BuySGhapfac;xE7?8C2V97N`FZn_h$laKD(`g@vz zTj2-@W|-aVfBV2NlHSw+0un^kZ|nddR+z_V5E$%nmYHAt!u<=pyCFzJ*6;w3)b6YK z_po<100kF;luvK{HAcb9BToh`9*l1NlYE_bT#apmi$~c#@XfErwqn&e(xV}?j@-Wn zQd^8TV`7AQo|11cLaR{YszWLe{JQb@F%mO@N|kYDIBn>(z(5|est{L;4#sna;Sb7kP9bx3wp6x z(19x$bi?gQ?i!z0w>5I`h}h45VqLqB`Y5|duHim_H>u2EACajGfpH-6*;O2*{Hcp~ z@qTMYKt8gA&YrAyP~9Tf1h6p(2qhpwD`$4OKaRT=*;yV!d}pk@Jb!sVebLoyh|K~b z&n9DmyX6tnoDCIoIN}!Ye$skyd86egwKZj*cJOve@{d-8-9m>ArO{Pfj7X#jYH@`!}zfQ9pkwkSC|Q&0;4 zkK1tw92X*Tc~eU%i96~Tf2~udRst)2)6cls3`&?KRUbbg-mS3hMK*k0=4>1#-7Jpd z-WE4$p#L&z{bHrs*21*<0;^&OkxG2d4KN|+->UB&utFJ1{0R&*V_M86>j)u8`;n)R z`&ZP=Rx%q?byNModE;$V&RhPyGc?a{I9afS%R%=%?<0!w^)*kV!bv9G#yE5`;B|Ft}tiRDuxt9Sm&`K_2$fPeIxB$@Ed~3> zD8`=yiiy<${iZ!x;VSJMw)%^58@Pr$56L&yN5f|C zq)r4%rle)WYMiP)Nn9MY#3o)@2yIO3>poBe7rA6 z6v7%-(p}9!O2)hAWouEM z$%FGe(*D>OZFNv_htsqc^^%wVD547_GUU=qcSFn4ao`}l{=?9VTtxD{K0^0I?M!zI zwY3*9c;m6u!B!fF47R>Gr6?Z46!~FI6x@{U6-H51c?N!j0$h2M=8I0i+e7$;&SCr21EeXQZm_jrSk891A`Vg$liDpdz8`3CHWH9Cseb8Lt&Led$*V*ny5+7+mf%RttuNOd-91n{~ zSpGl3a!P@Q+807Pm!(@EK>C;*?J{{Sef4bDnMewj(Fx~Je^wAt>pLIAvJ-BQ(F#ud zWz(_h$$7nH-5oiEeJdhAjl(||mmn&oK1WJvkJd}YGI62D7hYY>0{)P24H>^hQys`e z(+!e1HkHJnQ2F%e@%G6>$<4m{Hg<0g?+}`ltxG6%8vw~dmIULPB}8s|Ei4wrAwRYK zL7E^-qhyjGb)g2Vd8G@hVO7?A;v>8Xqak3(m3SK;pn2{+TcWoDNOU4+0HqFLSa}x7` z8^yf$r>uEZ`c6hq%6iI{hCl&L$oGdl2qAC37fi_-3zsYGho}~b@nI2n8-F6JmkN2t zQHkb{VhF;ahup6;N+~g_NG}FN<<1-VtA6iS!G^?>_gB`Z6}f_&xnA=5Xih~eYFZIg zi_ksaTLOr?1PQPW_I5<6y}OJ`VXHIdP(#zqF29Y(@`a?bK;e^$hl~!HUgjUD%?9^rn1ko)hdq zUR4d>+PGG!c9OIkWq!jC{cQT_Nr605u*@N8oq)qat4eVBw8qHUmxvb=%YiIf@j$NQ z_CwO9Y+?q8%yXwjbs@!ye83>dO!(w)yiH<{yHS&pdp6zCiWLprb2T_#1ETCQRD+fR zoW&3@U124lTL;oac(kwp!g5me0BXI^= z=Z`FDIydhtW;c#@sG7s!9%X0R2+o1%cWUNpRXy2wpq!citC*$bMlu!7K-{R+=MZ2x zwTqrhfvzkgm|I(rxt2cJH-$4tjVL|P=<%nH&ZsV)7vXDqRA2pcsG*h(pEEsU)@2MV zh|of?&$o3!TN2FYnaP}b3U;RebI&U5{4{Fv)fnMZ*t0{h0`lJWCMw>Pc z=YP>lX_&w6W5BfTilh;v%F*>)OGi@1D>xC8O;Yt{XclSP1_MaOTwaSPD* zdu2-YrWs^N1l-po;mamQKk5BTg4boLJD%;nw~pb?Rrq*~gLzkiJxj$4_D7Tfj!FBU zFU`Isg$|Wz+k44v&kt3s_AB1W_FM93SNC%$)mNjZxb1oxr_{CV`Txb(J4a{MH2uP{ zZQHhO+nm_R#I`2R#5N|jZQHhOCtv1%-tVll)_bpYp1-bZ@9wUys;=(UySn;UWv!i_ z8|~TrbO3m!L)f)M%ymK&X;97CnSd7toiYqc#ja9xOXb&Cr z2KkAC4|)0Sb}1FGg$c&GN%P{ZeD`Lt_;c{t{O>Dy7QZgwAZ9O=-?xlIT$p z@u1E6P}!udv@bT|WlCJtjFY1Pr`_8SU5+0$cq;p^zU1BrIwwtPVR|EtIEq?$_sYF= z3v7%FGlR4fc!lHp;K)wBF-uFWFVON_P=|l}7Wo%gVn$|0#{cS=dq91}mY5ykJ8kDP zaGs_yDtb4A;YgDII?pxju)&Z1$sRbSk?(Jjp$hhf!P`h?#OV#g8jZJJrc+H!=cW~2 zYdW}S)oDcvjfd+32y8GrCIAmbe+f_V(;d|h2aCuDHy5{MjH7Fi_n7C=g+)aWFx|b} zGMgX0P!y=i*BedD-A$oo70#&y`k=lm5Et0H&SYqG*eAN&WHuLP%GEZ!J3Mk4R5XyD zD3w0m&+bNPS?J(lRF;xGZLFl;KVTtSU^dxl zy8G2XSEVA=Felvdkc&S9M24p2H3up59fQzkvcScSiCrqa%-7$zu1u&EK1?A~vGL4! zu|8!7bu}z`adMK25R#O-i5A(UQK<)js5`A(%(ILy0f|n6OwKAN7ID?eX5m@39)4wo+1&$izcFRE3y2A|e3a$W z-$)k@sq$-_Rva4?=E%u#VDYsNaJrzviwY5MbAs39o ztre(^B^j6eGXA)1$@FV>eo`4u5g>TxP{_5RB%@f+P5r{H7iXh==}M)#N~R8zJD*G_ zBaw%aK5tS+4iUaFQc#@Fk7q-lci)Y+*n@4@|I=I? zm#^4b0ci+_E7X_Oa`MFlrlO+->A=m}87{{>Jb%e+S|R!j3z|;A2~vfGm!@W;%L1iK z+*AslwT4wZ0M5zg!fHCO;B3p5sFY77i*L&p*|6S<%s0V{U=r1eiPhpY-l;lZdvyLC zMFPfes-GrQi=J&)`^TI~(*53@$^KWIZUfbBrRL;19NvWI`qMd0Upne6Pg(@4@x82i zXdA05bLm!v^d!3+vu>}t({KEuF)d7SZ4OH)6xNlL^j>t(es0xjL4W~;dHzyAf1+t5 z)?|ujnZ=!C+4`2}yO)#Vp{WA<^Q*}4$p9fiioz;qO0@_x(}&r`a^w{R)RQ0zQ&K$K z;W}J6I6v_Q18f$~bwjaZ=@7Ds-xZlSbRRUv{gXd{PMM6uf$Q%)Q-Ru4h$Hgm2*mVE zs4lGacD?u$lV4IRxvAtnD%s>M9kP7W`-n%C7DcQWqGci-=&EiFS{5?FB(F?b z(DtE;bl>X9ij=n6h#y=|u|a4dA0{xvFeL@v6$hf`6EY3Y{isKt6JA1BXD0gEJjtye z-Q0B{zuGgCMM!eWsZZF?fD8z1vu>xT8ntfJXEDmsm!VR-$jub8JBNsuD|}i#G3lW% z{^e1FNX1f#9p&9L+C3ICdw-^sn5FJ6U1xN_JA6!*%(zr=&7AsTbTo!XNSpOp{1TVZ z=%1uSQyFd*##7XzMHC~ciTo0C``I}DeFVmRGO0h-zBx8_;7g%Ckj=Ze@tl3ZIpdZ@ zOKHd|DPO zA^i2rB2#!8iT|fYHuAflrnlU6l%jX^yZ1;96K$7ot?^YulM!GXv+ea5z0i^V{jTWR zzb&@R|N9m#BgcP<)L8L-q(aON(=ny~3@$b!WaDSh?cxeP%y_IFYvqt8{rQDJiy|s{ zK=tGX$Gku%se?}$M=Jl7wSV$thm_qkW!L4s{8LFxQO0UOn$EbeCJ!CE(F-%yN$B91VdA~ToO9_h znx;@#!6}7k&mpBij3ldPk>4!y?P+%OHWD_|SFin}=}%)TD&RSGJ-r!J3IXsshrDWIkXH1sQa{DQECVU@rT=$iNKs1cm)pDs~EQuHI8au z3dgk$2=lMGjO@^;*s;qiz6(lwlgj<_ylYxul?qqC)b*s`v>rx2p%I(6*(`%c%Ih1S zQM&OP2~pf?j=r6cY+DgxEYH>B`5a4MVwUyjG`U>s1fwiyMA<WBOug!5=bOQ_MGm zUK!-xAvR(B7^HDLdYVo7`bgDuU=D4BsojKM=*2*)kR@nQA}zD#Ddf`UV4zrnjp#LL zn&~BXi)kyYLH7eJaYBY^LfH^>BTg_kyy4lPPup^>)(Ce8vYWzbKQ0?R8--T9mwm##}}mF9iupS*jB+~e11_G zg`pp+nlEwm3$8VL+3$FQaC1$1&u71d7YwLPkb+YM%f40#Iz|Ytzb^P1+yMW4E3`KZ zj%2ti_Gp_IN3Yc`>zaw<=Do%MOn9s6C>?WNQjkp9i7qH-@SsTic|=S9(j)D>v|o~6 ztGGsyQ7^q>?zz&;q5-m%&!mW*jRPy4j@+mQ19M;pZpL^#?_3^Y;<7#FKN1T)jOt*xn;dWpMfx;DR_zL%WFGEm0dQhN(Ux1e!_kbf)U8~mi6!?V%)u3YTH!PoF*`S z0fZ_vdn#&p0gzw}J#Z<}vthHbToz4hb{Msqa4yQtqF{cWp3qBrNT|~(J6S9&`>fWJ z{ZDOp(zkikX%Th&fk;X=dSnQ%1Sw)(Sf z74PXdHhd?oycQQ$-u=6tg~9jpR!FRo`Sx@YY|CMoQulyuvR#?af9hQ4h6&GIK0k6(hQ5TPP;EO|A03KXAWaFh#e>N<;CfY}CxFqREWBSKXvdmcRNthJx09FFe zcmlZVJOHb55Ay^Ix0St}Oa^b6W^I_}jLQL)&dv>i#{KdwD%I*8>^7O1j}pElV|K7$ zyJ&^?GCNsnw3xdQjL3>y+7C0RmJdRg;9gN!+>ot5F;r77DU^m{b z0>$hDfCLL;=jjdbg&gJ$!_O`Eh4ZV9r;Fwtr&@#Mw|&|2XTVCbIJ-=ap^EeU(7yXr z-&T1a*6a>U(kQm#DQGp~nUA>J#nB6yVg^wYf2h*d*nRU4zbvHxVtf4gsEzBGnLBI1 zp=L6coUM=ORRIK}pO!-c)Z2O=NyNG*yumf;w8`J~0e>+v_-|QQSeQBfS5N~p3+I1# z^wNPd7LC*L7wxXa#6MDPUb{Qz_etZBfGwLBv;#z>o1+H!-?JBdsXP)X)dgMNEH{4_ z`4ZCb-Ef*buV9+i?6HSk8F-0uzA5pp^45SPKZ@H$^yOm2G$o(` z*!|pI*N(b)BzhghM%;-Jpjw5Jf|VqVlel}<}| z?wAiYkh~u?icL`HT2tk2UtXz$&IJ&35Gq?6fT?EOc|95UtDUoPvvi#yD1mleU=ZlVONwEJ@wvATd?q zc}7S8YZk&?B$#{*ZbdZ6SH@6&n$Tnd6}kpCu1bwL$gz|0LZ)h2-Ewk8;RqB$H}GP$x2Tb)I* z$wO!9u?h(}yfR^CzwLy6h_x_E4-7-K(d#z^7Hp7a{5MH zYod@(a#LU0GHdm!<}2wM!1R&W23?6LJey6xgW7RUx^tZM()0mmCfVC6Qt@&n;0sEk zo@DVoL7hk8OLTd}h#A0aHPckoV(yAMu8Vye)ztBFaB`Wll&2A@6#p}-P0Blwc;%3a z9tY;tx_TfQVCbQDOV!+G8Z1VM&G6Gn_kLCu6?ke8`to4iup;x@X=`I4XK<)ToKf$T zeI*;dPL__oVl)4{rE5OrSv>>QPkxViEbJ|s+qWs|ZZe{lkK2Q_K09brMEs--DISSj zqv|o=WF8uUJ>LkFP0SdCphmjp1J{h_yDs0C*CTpgaR0H-_@dDPh;eyCjm|`ItC_1; zgk=2_PKau`6Ht+aRm^)}pbdJtKhSI4$p<|YF>PzzV!pEZiYY%53?o=`*4;9e*?tJ4 zhJw_5<2m{q1frI8it;H76Z4W%)U)yKzP3{F7Qy>gD%&scCx=#z^@-<|I#0T1AO*~# zb!Ea2S}URk0mg)p=3C>=>WSb-m8pdNxp6T|$ZmqA@-JtRph2D1@{{z+-B?XMgWz_> z71BTz!Y$ppdxpa;s@s)_SB&TZu5?Vv3ns}En5RX#^!0raJM-yL#b0*yzk`5k7-~J3 z!IF{E2}!(jhf!z*0!-60yW4LGMRZP1^Kd*!1K4)KM-P$XTr%Qc9_s7w9-q^4^uurz z^+OcoLQJ#}Sq=+1#U#kljc!8)ftD{TRuQZ&eXUQMQtpqtIFTN)9eqE1DShxDw5#+e z5{(5u_+iFYr?q{d13(;9ue26lqA4HdjxTm<_kk-N+5lx1<4 zL?AQG++|tIPE`sknr%KMWA{b6tkYW6k0BQ2n1M{i0U{AFavTWF@Y*S)23_jZ(o!my z`ec>nkmnAOlELy^wF0LOi3v#(&sspbh6cVH657G~&>doigRt?wM*1^}&t-$^^|{I< zLyYdO=4~8URB$h_o0#RJAKm@yS36BDcsYPsgd8ak$z^fZx(Y=Ix zG>)`X`c2m*%KRnR726(VBD+5Or@1_>G{v5Mct53NaoJQ}t18`#5vZz7 z-2(uyE+E5<8q>v7%T7x`+>CVfsafG-!<)Y7d!0TOlSZbK^=9?5+=3XQGb1v38~B5B ztUI0<$!@PSY&XuxjfS>h^$6}C<G>(LOI9_+v|7#e1&$avj(mV*T^RP5k=+UROJ_fYe~PD7hnO=^4HpOs z?hrDHv-)eFIiud)A4`cbKC2vx&YeGzDmyqpxq4UHpZsBDyApgUR1ZqA``t@Iwdl)a zABvdd?iU6$Z7UPIql+H#60+>EQ=X-6F7LTzdQMxJhXT0)ww-;_* z9hJp=ET}G`X9YmKfGt5JW&~y%MkHq4*xOJ)$8dWR-fT%atvzZ%#Z{3Q)n?L~Hyqc!C&Lv)HT9Ue9VphMMUS9* zeh=i?hoJf$Fa%yb0KQqfo>fC3DqJsY+PX<*SwK|mlZJ9C=j5laM~qY#WEb@&vEg#? zc#4H{{8H5&kz^ucY?e!U`>-xT6f$Ear{U&$b&2^j^AP@z&f-kA@h3r9udzALU`j$9 z7XPO4H4s^D7eq-jWpL~cDj&F@txgeo(Q)--t{pC+%`mrN82R|E-hBl(cEL?%PCj>^ zrrtd*1~;Ez`3`cXzyg4wY4ycCh0134VXVxOKMfZr3DKMr<*RL$cU}$jDFkJ_?79J| z7B1Y1bc0<&9J8oZ`a2A3b6!2rCrI_DUktYv!hU4GTG?u&wbCqx9%$;*M^Nn&QS~Y~ zZosINyt_f%)d#}`9|b>lF@P$6*we$4gJ*wZ?B45Y#$$pMv4VC@R$2O0N7gfZ~Xs$=8)ZCu|}T zU3=e93p~O!gpP^Z)qk&8mhRp-t9iSoMC}HUvVphiCeP)U$R4Uq2T34w0720OC)Q7g_ zQJ}5AvrMb!2|qM>RlP#_DRbvZ@75-c?a|%Dg-3XP)#`lZliK<^q<7_l%;UQ0n$GF6 z&=?UqZx@?eI_4E)o*f!5vZ#-#@tt7jY3a&x21`JN`G`%Z<-=1GfxsZ-dbJFh0jbRzyJ5vF%87P(_qAa|f{y6WZ(T6;!6Z5 z$JJ{*L+RJELB0(Jq^CGQQD$8aYGO{k?!2_8nIPtW@<&Yl;(Tom?KO(C$oNJz^yl^+SbqY6$>E$p7Y-(fC#U;{BG6NHhVDhVwneF8 zd{8egX&W`okDR|~Cmf8x$U9zhyKzeAEM~sQ*l{z9 zw}IOkr6N!ZJSxAIG_0TeL(eh*q$!1VSb{-1QEq};B=nlS@ZK)OYgol zsT8a3Y4P?8(1SU=O!ly2m60@#MSYQa8BKH!>6CSZcQNU zNNL+0==Xb*Lco@BlXjT$m-lVY=a+D}v3=QP(tO+|_q~K+{D9#Fv^bs*|8O7wrrg%1 zPYVWz8)EtG>-9xbU@tn-7gbo`Bwo8xFQ)VJ*^#JKpsi-c}S8 zhwzSeVe}QAN}4Zcr&WAs_e>joA5fwn?j4dNUuR$=6|F+E|0~Dm(Hj32i2Nhw88?DW8^9_nbBlug*2(93^6&ZZHHA<_}Jhc!I34 zV!`3pj9l95YC#O19|OQ8R>*Kk*TY>gS8`;l=`pupu`P=U;6M|fH0_QKo8rVHiViq# zfP+ik0E~5|JfK3HWqu+9ujI(CSc1Ecj^eoh9L5i}0-Evg$4%bv?_NCOawBW`G1+32L?4l$CWtG(@e%eyU>aH63ju1DEL=jhJcJZK>=A= z2+RXR*yXW2*BdlTC{!(Ptrsq%=;K$0zq(m{& zDFkgEYoo1SgK;{(MA^lv>3E++hrEIZII^L*uOLC1P11|VcCj$iPl9BgpO1} zClA?pbRy(L5Q+5}@FPphsD&i180J#m2qBmEEWN8ciMUYL%{*jJ86Zh&q8d3C&lWv& zNJ%Xucl=|>AY5nv>uu6z9>KKnj@8PQb>u!;a#XmU8ADYF!=ku8=>EZq`xj=6F1%8? z&WM1yp7MKrQIt;-`%6Wt1SSU{#!N(m>Ap;m1c;xsktI_=>qHlCjUGfOOMj2?s* z#=Pn3m|Q?U{Wm6q%Ki)stF z_O|!kkE*YJO6s?P-H*HW7Pgr~%Ny^o*9wvhLFQkD=|^J&U7CjLj;7Zo-V;#Ikzr96{M9k>5V>5TySpL z;6VG#1^FRY3ccRvVB<%TS2}T9ATSC=+Wj@ylV=~y-~_PY=I!BDA|ou?4CZtW8lce7 zcXU5Ay3HtMCQ%pvxg)7J@Cjp--R#G= z))2Z?l}WcN)_+jSB!}i1MqZf??|tTr+o$N0Rl3l=cQ%K9Xu4VHPj4qz{BuYe`T?3H z4|j20A6^GcVslw%O%gCZSO;X3C#*P`@>tPVT>5~N!Nz>6IJe-LTxVwv;-QPkI9tEn zYQu`<1tX5ixa_FdGWmnfsC-|~jZq=LYJ?UR0UULrc#(o*OKW(h-x6&WZ{3{6dFa?g=o6rsXE7vx-Do_igz(@$IOAP-ivjTc`hF= zy%lz5mnMIyR!L%4R1&EPp>9I9U+@T0TQr#Em?3r#ap@zFxnG>ClKdK7iMg5(YT4`s z=3WkV)Tf2cRwo?}tx;jgWSQZ*^=OT@pFUBNS3fKm8SLj^L9nR2(*3ilpXaW#duw~) zWMjOzuz6V3g}g=Js0wcbvue~N$HL>W&erQ7Y8J_ImT=QSndpAQsOXR2UB$1S$Z1cmOKcJIml5fsjP?5;J7Jsr?iq>RLpY;N zxI#vc8G8rRR>SB#E3p}ht}IkohWy_JxG;_joyrh0MJM7_f_`=iKl+h-1)ioU)l}0T z(}F@TA=VEQ0%n!@JKthgD_&KMs!g(aEC`zgZsq>?;6+tPJQ~%s7rIw^pmYf`EHs#1 zXq;&UwJ6_rSCQN6$J)83fRG zACRoEq$#bCewv2dr~*Bxc+stip#|vJbX=}wBikYO-{C~?IbS?%E=Bx#O<++FTkFw( zZoknVa#wEAFx&97+CE!Cg!SCuP98jzuiL?@Z`-fmA(^a1V|Cd^)|{=at~qe$Y?5F7 zQ7Tj?ZaG*c-cld9=^%B0J2Gx=hEL%+f66HAZ~%u_R9>^#H!YrQ`NZK+$e|VyX^oCN zMB=KRD^rZ^#OClT>9u%j`*ao*s*iAKdp7H;FGeaEW_0k2nF690Hkr-k*Dr6`mo$TG z%THy=^ozV9Pw%IVgoRO~QA5rG^=n;fK#o*FHdbARw#tB|^sFsF`P0$z9Zqm^cKh-; zKH<1z^kW3FB)WE>p&y`pI7*{^`z91pThj?GBXt#_Mep)c#2&}ljRRC#h&?}P^eQ6` zlFty8x!8-hfy@JctyLx_lE0C8!f5S|dZ<>QnW!~z248okCa$zP2@VbFUGeV4W zauyWC7pPY?W9HZQ)%8qh3&yZO$R!b!)zK-oKC2}?HIG>l{0<)N7z>j0Ja{z5{ zbw1*uF4Rm|EzUz(+wv$;iAR%|cNHbL7zN{xW+$_m*#^R1Q*@RR+f&T9>`WW~UYNcw zLk;nmSS)8_Ft0bQtgNCuY0}K{yI!Zr2|;1H*Sks>Ybq}*Zf%g?IYrwuFI#LVXd1&X zp;P|cA{+-#+kVY0>mOc9txXLHg_^QkBrQt2dC^jWbEFk+(D%2zEw1?^YJ{9+wBp~2 zSP{Zxwp}*fYd&P2ayfW%^AlK56Sz|E>h$Ek4wY+_d`T)+#xik4J!Tb3BDp1UqyB)W z)@8$qb`R>cKj`Dj;eM6>-!|o}tpBnp|1SZ>7j#CV@0t-ipOl|L)B3ytvA|Z-9sycR zrke|f)FWK$6JB1) zL0f;dcS#51-*2qMCKGj5EU0!Kn`QrwOB0c%~d|gC|)6MbLkbwGTjaf_u0dp^e$uRAreq7Y;$)@q zh@D%J@IbcEUK@Zlt5}=eVR+;f==vZL>3Ui2;e>?kaunG}6MRoGvcw4{<~OD?&v_h9 zD$#V~ZD`0vhXJ-dne5+p?zWP06fxhB)X%!cEjJdA%j{D;GqK>X zI43V9;y$0L+OKc@FT~MYCroFUMJ z=BP&^(jf5xQ*n%tu3V?q6b+bNOB~T(pzahM7~t;MH`@7T5@}UO3V8zsGr9>^O0FYP zp*&v3P zn~iGN?bre*H+2CVU3|Us_nR?$`H*e!mzSMZ;w<2xTEZm-kg}Ew zDFJJQ3Cf8XCO49}rXUlcr*Z~rl52mOwL1kRwO&0q0wpG=v-#BCIr_C@fTRVrMfmKQ zEFy(;kC`qV1?E7)M2*@hOdAgQp?OiAI^LI&*;v+dg_qDH6>K(wsYFb55@Q_AJCN^u z+?1k7@((ee1M(t9Ze}mwuq_;WaK-o!nIu*>=>V1 z$3*=J#!L#roc5<>;jnm&A^64&m>qd2V*X-}J}TR?O#Vv7#ME(^ELE}{Qf^lVMW^g~ ze#nxYl{wKuQKw$_WT{#Gkf_Fks8|L5qB2Iax!@89&+KMEu`XicDizFcpUYN+U5FS?zu2e6K&#KISXesSvz+h(82W+vq{HQt^+)ca96wAR$@q$LaPJk6*>rCuh3@lgY=@ooMQZ1}FE z5^6-~f6r9~(u`T`6NCg|f|A@-83eWfH~CA!o29T?0qDe84^m37wbVBV2`k~jnG~Tk zGhsTf)d-f6BsS{^m5>x$-BTL*3K<#VVCcIvyo9Okhmjz|nYS{Osi1o<$n3X-*VVGs zsHQgfqzI$92?7)@;gGPUF&m=X091~5Em?_D$V+G$>8`YDY$(;cH1e^>7QVL+!4(!g ziIGyJlhSWIi1ki-eTKOnHvHs(&#}gqsd9da3N)UGqfs@M$Y&1?21521$I?!>1KF`TN60|wxpe&xM+Y% z%1gjz+mAqib>&-+)h3!IpW;5#(1NT#6cYhc7Siyp*iWF42MwZ~B%iGhs1HNc5)_ps z{B%sSHxbGj)ZnLjTWj5SM27_WN>D{T?h2Hvy8wOpJaWqTJ{m#{yH_(XcuLH4vhr(X zl$R@bm|x%!{7KS7&!aQVJ;}e`gEaq;Q66C8HfBxnS~w`ddJllUjOL_3zaH}hn8o_P zgS=3gq$+(9=vyck`nRpVbU!8Z>O)l6e+5Olu-5O^AW9*}u;z!{)UUYlrXP~cH&-pp ztXqbA9*PZq`5(Ics*VlwhObfw&g7a;GAKdz>exJQTZ$)bFYIo%_eB_=d4AXB&_1 z40zrKP383&(~af?HQL}Lh)R(lbDp7;#C7JO3n7ih?#yiFjq|arLV-aPzWV~VPCZ!T0= zZ1{x*xXMD#GF1=*nfKxKMUROw6li78FWyPHj~!7CI$kPlXrp%Oy%IbeF4m>9={Ew1 z7PS0FPPrbugD6+>1HlPKn?D?=`w9P4MZT#Qmk@qxw#}QbF`M&5Q@ji1w>!Y2_-H_3 zZXo-x4)8uNRD4ZsyPB6``Z!y?&}`jsLAM~;J>7c@gAU6E6J@4Y0K=V;)umtn>Lk07 zzyeRwRpLSU)3>i$w)MtT^<=KQ5`(D2>&Z(;7CfLTN3=Nx?VjctjK2)uw;3zdvzZqu zwwW?}S?%d8nDQ4rD@A*m_MeW>rnW)uf%(wLb7kna-UZ z{LVCiBhw8nWKK&b_p4;hMMA(Tfcu3Ub7PWo>7AQ)PU!NP&6a|#=KVW& z+Kp}bb8}}fl71y8OG*8*lZ{g8PtTC-O&!jD`&I1{?BaP>A9h<-H=Pj&$j~((js?S@ zxkf_4K@)DS?YQ;EH(Kparz20liG2@hK-{104p&DJoeqF1A4G8(+nKcrLDCIptbwIE z5tg4EKrO!B-(gQ|sBjzqw%h)<^gYb%|D6kb0J|mnyqPh(>KGp*%@~z_JJ;W$gB{x1 z)QG9?_s)hn@YNSMT^5qGVUt$H1N3~T2--I?T0;A~&+laYO^w!13}%+&*t~L^n}$}=X~fwkesm@yKhLiSGdtR2vPaO)=q8}`}d;< zUEz0sb+ay7vOf^#X+_;m-r_bY89C;Fth!$h4`=B#8d8YX@0eZBUHJNTU*AcJfpY)~ z>ApVqX!!&bfZ96&uy#oFKHsMfnwq*Ct8Ex19fQK~@6V>T=+7tlp;p?-YbC9sPKJvh zLGub41O>bjMnVLo@=usHCLzLCf&wVKwgpHO(Yof?XXZyGXoN))f;G6W@rW)IG>X+E zQiDjN1Wr4Tzm{ z!3U$3Vnkvt;b!synFJ7cLJLfqp4e8Y5DWJ5B{4}5Dm^@WKBT_z@|4!jxakAf${r-` zr%hLP&2no-(y#{Tb(M>p3)coPrPmNoX<{l*`t52T#iRQA>i9&RDA6Z_Dlqr z@6T~q)e|ACJnhJ+$(Ae1rRm55>0&6BZmF{81%KS|c=SLAbO>F&k$Dg_06&M-&TYGhcI{Kq;b( z^{=g=kY-PP^5!;Gpeo$}is^41DvF6KnibH<%5|WW5*A z07O(VT5r#3%LmY$koQ&-+TEQpgxbFtQcD8_&p&q!eMpr;#96vIi=dQ((w6~eS3;$( zsJcgz$^bEM`1YeCD3&8`w1H|7mP;~ZBC_0OKC~2gfzWL0XE(a>-J}{0XfkQ6X}-Q9 z0c9{$v@i~3tcbtZ&CIjn@!qAvE6SCzVl2?bz@mrXQn*$|`T{zkJasL-wj<|NoUz$& zmslL`-sD(iS?)G&=^}MTW4GoN!K&1_a|Y3kIHOju2+NV` zBmnIKU90yJKnl>ImJOYH3FJkQ@{w})M~$ok^zBY&X>EABz>Z7se3vOrd2qn>;?_I2 z0**~&melR=YtD7Xu-O6O$JQ-*kY06d1 z)uslM@a%9)tprH-a*+E`bi0u)5w4bX$W;0G5%VM#84W+=%=gs4bh52vSomt;f)PSg z99FN56PZylqdFePsN0nFL-fVg_SNd)jMl!e<~508VAp@B?Qs>(EnOqnm(f*Cywa}==V%5 zTy2#szQxMrq*zRduvE0ALMSAP#p^=k9$$oTFX~(Ns^a9g`w)eAz^#xfWU{NN(5?BU z2pSL6@)*mbsOq-}^*m_tTa!W{W~0SPNs4J?6<#@>B>`GupM~I*f|hG&8+Cf#rqGfZphjxd}y?n}IWi7ma+`LR> zAw?e~NqoDIGk`|{^I%r1$D^*v~ z5V#k!<%QWJ!<5MLQew|iR{V~+%Fgvc%FKM&7DiHGLm%tqF-k?aK&QNld9q(EE$^kL z&fPitnI#1{Nm^o4y+T5KjSX-e5IOKd+)4)q)O_Z^H8Vwh27GJltqTJwRj}@qolk0_ zHv+G}>cSyQ>l{y>)CSsLb3r^IMAs5%nJ8}edT8irDi_%rUs|*oMe!#B7ou14bYh3z zlo)Kl`+aqKRNzms`Ylc@%9O;33ye2QDns%3O)=SRI++UNEu`8$Jn3VD)2MQ;{dD;a zWoKM7H}6KkQ5IeI=xM-(Bbt-AE9yWWa8pH7bsp#g_kH$|)ZEL8Hd9UebZR7sPfHzc zl)}rF8`Kq~&`A^XlNhBjTcQ#QK)e;Ar6NNG9brK2_hA{;XZjBRu5~ z$Btnk>DLCtZdQ~Ykh_A1>)>HnxxU+Hj+ZjeEB}2UMdQD2%l^d)%EJ1ez=Z!72D-Pxm}Nf$O#2)4J@Dh{!Eo>o^GC(i zH6h!=;@(G;(a*0!2Z`F;1iV3{G|Vx)AbJ5e$UY1>bj4~FCd@uJU zV{T}-Z$}%lhOXb7%M+@*k5DcNO&AX~tF1D%KAsd54h_^aNBYi0e!jvj$+~Pb_B+dZ zoxhMXHOAF5Fh~52DYf z=3ro^moTv~Gj}3jWnrclvT$-#FmVvJv-xRfYhvp}z(Fr;XKm-8{L{e5gkHqN#lpx$ zNnD6tS=PYOihz-Y?QdU7|9=b#BQq1jf9^^DKhWwgHl|{*SNxalaRWL%&a?0XhN2Hr zZ#b+ZZpJN5dGur#S0r=hF7cjnw1LRmG=3lx2z&w%h6bbckU<1Mw15ht^@4@pk)xz< z43H_D&l;F$vv1t9L&OG5r2C|)%ZsuNT>6lrvS!ocVOhKUrcwJn0UtiFYuNboM10n} zk?u<`8CRc4YZ~vm+48(`)%kYWwq*rJH62GHNd;cf;kxNgPC*?ROsn<%;=uA~?r*hA zb?>WVgnAOmxbOuWm7(cZJafr7lEjPS?;NxA9%l-1BqeSUFj}&_fV7fv1xg2R=Ke_} zl1e?%aCc2`g3{l`1ocIbS{GhWf2kH)o`yBSkxIse3~PseKLew71st8pcR;f3C?EbucntfUOt;TA1bbJ*n9i9 z{r-^!txhsv5rW?t;xAk2xeZT)*mmc5X8+-R_2qtT>(fPHG2O1y0{^d?16aXT{T9=Q z{zuiOo?9=IuA5ww|40oA-MqT7;r-TJeV?jIpxXJ!nVM8{llrM`6;ym&vs zzU6h)?7|27&%m)hkO+?br+tJSu9$h$bwyvOYnGPyH$&3U%~I2r{}DwBmEYO?AHHs8 zi{XY^V$i--RB%zjd*1lnMmh99qmkd&abMDxf8z}b|4*?E;~SLL{~n)tQ}K`{(Z5FW z;{{OK`}D6h{gBn=jQ&>2ECT0`lJ6gZ18^GH;(shjC1Rz3JNj>j-#&$kfoC`kkDW`| zGYP6&8OS*|A<0?k%91ih{LP-T01&P30cg1UxV(k~M>UuH=88(y2ZvU>p5)uwQOkMH z;jS2ZGj}@ZB)*H*v^$x-l+|-czx7#yQGXgntA+I4Nyzc0*VYd1-xjcnUS|w=n48}w z^tXMm+GmOI|IjMSlplIW<jNt9bvDiS&*NVk`JP69 zOTNWV$Hm-4qy10AB>d|6VmQ!$NNOmnN9X^;-Yi1YyI&#t%bg}(y$ zAGRv~Kla`-s>-bk14U8+>6Q`%m5`Q{lJ4%1l5UU&C6x{VX;4BWC8fK&1?hBybZ)8p z?#)Iy=lkxx-~DmNxIgY0!!gc&d1I|P=QHOspSAY8Q?^}#T(|(kLg%Zr(lJzWJ;U;# znFTVy&QJq20VyG=8Xk5N0CV3z!iF}Jw9Q-V2Yt?Syg8mw@xWu48G?oBFGn*NVN(X2 z>4g+=b>1ih<&gVAec4{icGkixUqGF*zZ*j?TGZ46YWLFy>9vkTxD-c_G-WI1XE3hQAwC zd1YOa&#&{WOixf@SF1vU?#h)Ko*O%p@lrp;uda3g>_EVn#)AjRzPT^NgMbl4c*16~ z60F~ZJI7NNab;-H436FL4A>m600_0KF90;M1z0izm2J*?Q2Vxg?^fCfA*dH_?*Y99lUq1!*c5w~z`!j1OY+Vn;`&^A z*iEirdljuib>R9IUa0-qMRp5XT#a3?P4lR1Po6B?CS?4|mkS2C6x_S5VJMZ0U{EV< zJlR?)WwLjzmByNVe znYvz29aq|&Hb!RCo{ z6{N9rHv*QS-udL0bk^n-29>I&T5Lk%zc|me{6C-gVvEGf#gL|y?&Wgc7eM6ef^fKE&XbqI!~HVJE}7h`5^2f z<_nGnt6JByjh-sY=uC927?uX0T0w>fB)z_HblZ@t=tAnj)Zl^EXlRssSgu?2b_`u% za`@=!9zvWi%pkytByv~Qk<8NSrJb>drM66i^zsj|tk7n$-n~Eu^*+hRSM_sbvkU1k zfJ?TwCQ1$DM8^Q+n+{w0HV6}yp51Mq%fuyTO zy0DAulf55L@uH5cg*%Jfxo4vGB3r)t#mV7r|DjVuGl+e-DB@LN0Jcw`?W38Lm8{(< z0pxLcEW+FecXgpv!P`HL2NB}3H*uNPfmfvgcr@T#mHb!yWc%tnuOU+wlpa1BhvgK& zYLIxDB-R5?15)$zvd;9e(NDard}aVVfb?K(yIK49Q|=4u%R=Ct6K0SEJoVDd8DJJ` z%COInx^NXT0OVk~19&#O!Y%d5{vCYS4Rck%IRF8 z^B;BR55jj&?ocO7n65^AW*6d1A$KtK9%a;bWR)r?^Y+ z3XFq#S{x1HDqzeN#9Fwvkl=+{3#)uGY5_K6z_gJ3bO_Db5G&9DmB)x5AOqJoqZRama% zWZ=)+BJekcT$laR?EOc;oe!mz+xJIWP3vdQGLrP&NX>oEde4$Q+xHTDfSeM#v+*g# z(!7;zBEqTM{7r59K(3w7{t5-bP$F;5f{0*MAt)%V)FgJH3(&jk=iHzskdZ=|J(Ooa;@SMI*v0rlKn*8QE*A_+Jx(Q05+dy6 zNX<)5EEBl|)~qU%3Ts_LKo(00<{0~6NgpY~fuiM$tULpM+>su2Iga76)zT;?|M&*I zz?zHVx5HX*(X9LW0vZBW_M0!+%t<79v~NZ?FuGhIuTMeCJ!CXUfMxhkl|Up{ft5~^ ztFZ}?U&|Xv-Q4_H%*%QlmTL?y1VWEQhhX+BX4CAdZ zyWfpMh`SEsYXS?q>?Z4hxCmgf0e?t;a)Dw}b&qvvzj!|s)s9+1A;KqE*KIynzgs%|DxXhdJ}VkiJ1)7UfssxS5y&>_K)drgjER`{Pn@^lnJ zFrX0#~$Sly^F6z?&9see?v$)$rj(yZHYms=~%N+bj+lC z*JuSloBN$|Aq5yIC%!1z$I2CDVB~i|%-lxlvp#*-^Ie;4n&d5Ko`-2%`Ps}uI+_cu zk`u(VJO0s5sW(VC1cLX#+J8V%hoob|+XD0vFjHmy6N~?-)sQG%vB0ch)Z+g$4J2Nk zU*YIJ?DaS7bCZ)p5Uzsv|0qRXk#oqyo-hANdF%?1{0REmH+#i`j#wO*nhJKj zvt&E{VNmh+mLd>sbCG$bNvi%+If~0fefio9JMY>HSK;XXX~US!~LN% z2de(|4hA%wfhTto6f9L@EJZB<{U$8%ZZrYV+W}?!5TEb*0+BwUzvC7WFMY<_0*!4* z3T0$9<2d{YIBj98&sx73AXKg&>XtiXNDaEyjKF8EJSlVc=qcXp`aXQd+LD$XU*!MQ zbED2pLtyXm5s(<#$ zd|(adviJT3l1E^CBsuqa%FV^t^(x396NEOBP+A2H>FM(;EcilEbcJwb`CowPuTeJn zai!on?CNNC30NY%LK#qHt~$u88A3|PpRoON2UMFO9-!R^1MFY6f5>z5A-%l##zIQYk9vPwzHf(9 z)A8yTFEmQgfsph7>ZvRNfroADzK4&L>63_Wi;L{w0Vl(i>hMx*;0^zR-k&TlNW{Jc zvNx;VWe;@yoa6kS!05NK?Q$N+dG$qCG*e^Q@W_F^WAVoiM3!!a)PkhKURdcGuNLb0oH2K8{`7_C&^utiobWD69|vH zG5KYJf)+rlcm+rUFl$|t*sGWaDjbX17_K(VI*`zV_OuAs9w0Fe8Q;|o+U?xo2YC6v z;`-_%v7VhbyRJ^Us&bx_I9(2pc}f<# zaRG<#NPqkF){-%d3t_jlyPUWmy%byQ!zS16-t7_phHwLaFhfmAGk!Kr41t!8AE-Wu zhIsA1T*8xB0nNAx=X#1`%eJ8i9@Yea3O<5d>o<{&$F^>d9n&X_qvX1 zLFp@ka&1k(A}v-!d*j#P2n4NVBz$2>$^t#ir$CnxCl%|nK1guwWgN5I7eF^@s!wN4 zapTxL;5um2b^UxnX_HDb=Q-z}^sav%mj!FSrU0&cbr4aD4z-|*)|PA*DDt6z)Rubm zd*D^>*N;t++PxB26z^%Cb1#^>z}K@?TLv>T zHiRmzk}H^r%Dgu#=e4L}1%Sn~#J}Bb2_cNaJU`#U6M{u?JaX68g@j4yATfuEO44*|;6LjZ5xRpg!9#@Mz~fO!r= z@KwH?acNcD@Fh*985y+SKs_1(?o z78k=Jl3gcfhvf!7IeB|e9&98=>9_0!Z}r*LlXHUgAJmawR>$kBs={jlJ=^gObkM2t zrrGQPlJ{R1Xgl7t6fno|mmW#K0Gf1l4vrb93|gZQ|74EzET!^&Ko_{_1*?|ro1S*R z?l7-28UTf{QCvXVzcMGJ5C`5YBS2d@P6=Z_*JT25|CLg4J=($RwsVUAPY?me7_|WH zssNByDQ4YB#CW^_Dsr%~+J+WrUoole)8vU^1O$CS6{vJ3z%hIo=4^DBlv+dSQElJ zHui4-H-vx7A4UX~?3(h+Y7y3jti`X();iSMDIOHEg{dDFJ$LWQTAMhk{~h`&MD18N zXut>1v2V=1U-=9*^<><@_D>#wY7!}!5N`G-4FER!3{^&M#9$tz%6a^S6{LqBce7Yu z&jf_f8|Q8C6>tOn>_46f0Md@+uN#rHu2qx2F`v!>6e0`_RG57M_tB{Xj3K z12<$8Sf&Gppq9J0WH$Nnuj>Zsszf)60nIdJLFnrC5Vh*6CedAv0Ii*it-u|D7LY4d zD!=NklIgb>)hCG!fmNu~0;cZZ?!=_DI(T&(p=kFD^A9U$we1&@U9ESW zE^=mrJDHS>Gc7lC9d#N&;L|CAkVDxg=OI4|)syY{S@t!xMq^?su8jtj1~&Kxfu>mi z1jvgwCdV^z%>n=I3UKSKc4s(e$a>jr^CeI8?IGF1yfM>p;wGXG~ zJv1H1JA679d%@VS)4Q0Z-DS#jIchNdC+;A8tAJ`S__}%jQ$CTjRw{s$uU)p7g8_?2 zsAi;U0mWy>zq|w70w#IiuvXrqGTMJy>sG-(DJbx8-@$H7jdfrd3zlJ_hX4%{&?f)F z;JIMWE$JJuKoFw8T0gvTmC_(g(!Alp{{$yW0YrSdS&>FL%S2<;Pa=ze~+3J|ZdC%78Zd2BoTsxGdkkjtd z3x`z;Fomc$X~8$q>-j>PG12rfh%oz>x5e+KCvKO)R%&i!pnuX^z>?1eH)cH>TwGCL zCqYwe?Bqx1vvC7H)>>d0`0AFBVszcW-Ee^6Ah3cx3uv$Zd~hPLu<#F8Za_7MzXKV^ z8q_i#w6K7z(p?<|fQ9b|6CZ9oz;|#D(8K=5Nz?xsWWE)6m4-FJFS?+=Y-O;haN~ssNa*z*&i`BPpR*Xvf)YnUWiTb;v!$un>{LsSJv#bp5t?x-mz|z zZ)bm4F;s*P7Nno2`$1fP%>^I{O6{>3be-|q*#L1@#R3+1|4okHsKLtnN$z#WdF95b zk7HgF3%mc}o<;SY)=G@cKiw*%f}s`wdj@X6?YUsyf0R|qGJt#j{?m{G$uWc~00G6h%<^id@f)KC+YY;ah1g{KOi+3R{FoFokta?0}-N++gDn0zPc* zSrypd0G)HBCd@e{)As4v@-H0#dQysBJx<47@7g}DPuNID+P&FN?0HE{N1k$fRnPYE z>%YWJc-Z!PU`EFtv!`+Clho;tyeso<<_0H*5lZ@?KGa)y%N8eaR$;O%|Iv=;Nv~&Y z0B`vo@%wRMzFmv>%R%aM{qD<%!?@wSPr4)q8~VT8nWC0_B(=Ql-^sV{IJ*6gH6lth0&?+9FChY3F&cPlTL4MpM(ipLLIswahWL+;6aoW(HHbd# z0ql^tx+%o(7+Qy|H+rNu0Dyp!`xmzmOWQ$(>eGMt2f7qD^(Xg3JdIoc6<%%(?0!11 z>jd^0D#DP!Ye5wlnA4z4^z}HEpPDjcx#Ul2%p-!<*%P<|0Cvx6_t`^Na6uDXPpjJ4 z?Y(L00OTEA;4vl5>6~%MfnC?!iNN|x3D9L8xsEhTvD!dpO+M`Qz~e{#f{B&vm!Pw= zCz+?Qm$@#vW$)WBKZmn5c>0Va)OE=4G*rs97!JhC*e+Z0$;7ECpKuh;u@7^b2ax2D zfk2U|B6a1-adz%UhvaMa2WowmPu(vqng@#0_j1JC-@21cbZTD;>UxJgaUE$(qpX{l zJ8;MD*gJTbqF*s9{k;@ez=y2-Tw@QIU#y?nac&D_+s5BW2H?oy45;%JH{DHCJc7onBc{2xUBKhz!wxPB27Y}H_xdfapk9a6#dE}SbrT%`|T z%f&x(6C@U}1}#ddTYmh*@wW>AwdJpH0f~j%kkWXgTLzjnV9ko6_yB0r0GaJTjEgPo z?2K@BQF0>YvYO9?&v8XIXusthXocP&bEC=!WWmFhiXq?;zZu45Lb`iE>+&$}C2gOQ zx3{g$h;bcny=T*|!1IwWT@&j3`#ljc-+0{fSQ&Pltm!G#LGt#SnfQ3}IoL%FF4^{h z*o3w^srK9*_=%}x;8I(#Jvq|}Nkq)Wo6H=sWUKwl`@?y3{Ax=+^BhGsb(fo2dO}ar zPBN3^E>jl0K(c8UCMz*3@w#poSkhc!u0{L*>XHWm!?jrrll_@2v~*tWhq&Qm7Qn}` z6o1G9^rWoxv1_UH8qW~hAr<_yVFr8+k?b(GUjXaVSFr?1;zDLCye*vN|46PY&=sc} z@dmJ1kA1Iy_UOm|a|KrZ%glg#0^scvihaHT@KSqV4VFDckGmO>iS(ha@k;p$C&^2O zlz!l~KbH_Zf=U*g`1S#odcqdUu}{hrEtbr$2c|tNq-#*F6yB(io!j{NhmiT$Zft^&30Ds0fU(^1>(G5wFpA0Ov~8`k&8<0@b^8pMu!rPE`+P~<7RVksaC4kH2OMqRAAW=!NUo`>{b z>aJxyboE3%zDR7~OL4lJlNdHD%aoR|df!JF_*h3TnKP1~J<$|fIp#5y+TeL>)g|*d zjjb1=b!8*pOsH32`zIm+u<`!0C-1IzCK7Ny88e503ThI3-*MPl2h2B+rUtsD;bwUy zg0K@Pw?(+x_5iS&f2+ih>WZobwlA}SNX@K3%7z?q2pI>K=un`sckPwi1;7GG5r*D% z;}315lm@>%gjNLDSpfQuS5Kj003?VY4dgfILP(O|I-s)KPrKS}jD^oywdzxB>&Pzw z*kf--1Ua3J{I(1q$;=BjwfSZR{PIcIia?vbe4;nlH%E5}Tqof|cSgGSnADVm(VviC zVvkr`&!mo9zn;)OCDln2@YsYy{m#-l7wDGf@E6apjy(h}1}dfl_wp;EEUUHW9!%n*9SfA=i zZ&8IIunS@u0pc{61tG~W2Yf{-<8DFsBSGK?Y;gT+Jq~D_4(^AlUoa~GJ^5dS83r{e zA=pN}zqh9W_M%<@+jedsnfr!LcI}=&T{>(Cj8H`g;sP8q>#-b+hrp%`$ddD)bine5 zN?#|4-Ro_8fX87t!-p(+K{xOH9nh7^%=M$j?s%1`eQWa}7<6FC#Zu>K;?}yqtzQj@ zX*ryG^u0{?p5P43*-ai5Zf1gg7TD=K%+;N0d(1O=Ia-yura#%?f}CoT>WDSC*}xxX zjq__eyAN&9*%!6KdwkBdDqii0=MuWtO$~=gT=+%{u#O;boD1k*3Rf(I9qBd4>G$jr z{+#WR^29lOf}?M!R*$|iF`2|QD|MFelKL`8?Wm2Ve(-p;;<$n3$r?1Fw6s}4#eA5l zyM-*HA$y4c3;i|zHNn63BeXA{8igS0+G`L50jw38|6mse*Eye@-Ga8}*S4GlB0L8J z*o5{s1^`UKHj)Af>>3-$T4+!$``V2dTEITkT3~tQdISIyy-{kf2Z2|1Eu38+xyhTa zZ-%7>M4apg6RxP#GTyh@qEnJ(y;icz5CFFlv zOP#~0=T?u^Y;|no{%u!^98-+QfU&_YG5&~|Xn<>90L%Pab1BDp2+#_Ozx>Uas%Iak zAGr5*A#9a8Eo^r4NdsRSIP~&)+<-nfy3&)U->o|Kz*vS!sfWp6gYboS$4D&Dx)iy& z5oZ&woL!m{0a*fk)izvP@v#}Ol@wSqO}gryVL=H{QRtS$8(|9c$!V*wGV<4(S5g`5 zW&i<%Zha#E1A%eDQ!|r}p+rcl{>R*~g+rLR{yX@z0kH%R(u!OU$X88S{!f*JB)IfS zjM6Km;QGdf5N&Axkbn_7%4@F?LG}eAJIypW9VYQTbyEO#Kb9;InIZ2<=?>6B7Qv`f z>w)TaHpU#vUOTukMsUH_L6~btl^T9o?ZHG0zT7|Kpx2|LFm;ucDYYM#R^2wCNuBig zo$RzxcN(oPS*;9G8%DF=reR>rie<{}sl@T=TjQIR^7dI8maYWIO~P40%T)<#fi4>Y zio@yImDtt84CQ*yt%d-*L6~)%0d%EYO2~3|+J(#=(v88+LCWChn&UY;^hkq?y}f4JaQ(j*6qVU{l!t^<5@!994cy@Bq zgCYQ4yzof7F}l*N-B;48dI1r11`ss4_+Ko%qze0y6P{g2($0tl6pBC3h0a<)_6~B z|JH5Ta5*pZxmP5>3@W-@XSzIyzuY_KzdVC{CE)a%NIqi0fWYOMxc+gI{dV24-u!r$ zbiDVDAH`YA+Udn{1BFj}{jujZdAwXcsAlfm=JzD;?&i|0>r&VWTZ%+O>Zl}cveUCV zkVk{w$)5a^vr=HCVBpoc0jQwiB4cgt&maW$4=)dL1jsheaxAqSsm`ZPH&(q&b7y8| zoT%_U56A7_Y1H*;+J}q>QFs%@#^&RDTyD(v{5DXV7de}xzs-1|qtC4E&2v%B8~)^M zx1oMV{BpgS;(X7F5HrL{9oU%qYeXLSn*X*|x*~Aa@71YUt+5{i$NgWZ$}R+)URS36 zw{HasHPdf4hF++5g>_{Zzy2P@5Id#g6$!^%~iIINwo{;n8!=$?7=oovZs* z7zV{KJ+M2uohoQYY}RE&(OyMUY`A|r=mM?~bL_oWy2ooIYD;0CrcJ?2o_Fer*yU=i zWy&Gdo#rOh#~W0y-m`}ke29#0YE|s=G1SV`S$3%ef703rFC{^IxfJR1$wBS1`&r3P zy5&b!)Lh34cR$@>Z}=}WIv=Y01yXfZ>izcu#FN+X~EZ_{Vq3#F9xD)6y18C7+(M#2Je;nq_k{lmIVwiz)T|&9w{Kyeq$r zIlwu`N5}idSnA%VoHb0`LC)k06q^rY7Q;HsU7);p&?)Ykuwyvpfp9;~D2H1UO23hFO{oD+4M-06U(vQzH!2@pgPV7{RpBLTOnLjRa{#+BF z&2}{uT@*>8V>ax(vnKOMm21J=6gPsd%~Qqx-E?0^I3F1NQ`G3)L*^VxtXnzk((R^E zY0mEQ^pABvw}LU`V$III`RW>SPpThq3ue6EPnG5#^+22wBs7kfBj(1W&P(JHcUM-U zo8t20Z}Xa$jpqK`#gY@yF1Ct6M8ug9CnFr?Hs9!&l3Sk4?kJ`;rl8&N{wpqBpVfo< z^F!5-gU?ZeLV0Ht-ijEEerRTSpfZZLy+_V<-;u!BkGd)9F@}gif+(@1cmD&!2gpJw zLX*J@N6%M#!cTCVaBz5|;7Z}C?hHJ5`7NZhS7T;t49{i4P)KHqDX7Jm&1X!H{AUe_nF3?tF?ag?D!pUGJOFMQBMJA==I2)i23Zy$YZ@ zW7+XnMnoMZgy&|wCwXBnb8`5kBS2r749~k#k)WQO^M>xk=R;2d21Xu+YE9V{i-o( z?n_un5-?PWG`>tDD_S|PdzH!o9~NCOp*7iNK1@+oQyWh5!#-+SJJ*Ku2Xe?f`=dj< zQUV4L$l3FUJz+Gms>`}{*&X&!zb)qv@U~K9QpFQ2^B#x+WlM`A$dQ;-VSV?fazwE+ z_`ANU$+Y6s1Z9-O*(ihnp)@GxH&$=9?D6dp;c$9w(a@`tER2xRc^BVs^Kc?5^t}H5 zG@uy0HqAysp)4-*wc9}qMb_E(k68F$5#cj-arcqO6jqyxxFWL8`N#YM@=8QsR2MI# zozcA;7r^n#-ix?U69ESDl){TSq~#XCr=qdZuD(2&5-Wx( zfxohV`07E#Tk?;QnfGY;fR{K%|K!IR`?3D4&~a^sXUuXWB~wRM6ExA?7pAz7mc2Gv zwKJe7nH~CME84oeqR{5n)Ry^|@9);ClQ55*G>GtC;G0|P6L}SX@rPS3BqO+=?Fh5-b_L?u9L9(^-~U#TXt%Pw_me; zpn~&BoicwcF|Dd-h{j@GU6ke}Z)+0|CP+xX%@Dv(BRWYG;&WGT^MOyeX%GqI{ly#AEcIGMh^V4q9n<7411z|nMLQB+llz#S%Q6_NX{&9}T>3N0xPb6bic?I%FOS>tm z6AiP*?ng>u^w~Hbd+M}-8HS_Y=6_^T9ssBPP$i{#Hcw#srFnN)|3IBk*SR!~Uqz4Q zP4$r=4NFy#r+IR`QP}60cfnLiQ_0KdR9YtaZ4|F`tk%DB9M+0Uy&!*jY8PyUe8((| zwsPzv*O;Qzp+y&QJK>{Hv=4V_Cwp`9TTk8)yVqPJ;ei|-s|_L z&kql)B4?NGs1`Jj`5`FzQr&jyy~%WfWhM=WQhRY^97*%huX%cI4N=t;4i7QvjDn9A zEsq1snbX;ly=(5OhW2rC7&%G%9EBSnJFqVk2$!qyzI;GdI!|z~sox|tGm*kW(I-_? z!3;+(BCD)9kj9TT+1V;Tv8}K@0-s$Ur9AUCW1F7dj>os(!7)Ehy-v)24E=I7pws0r zlrC8dpm8M6EC}TvK~tuEAmTDb#+3i4K&SXCYULL?M(2r^F})8|`H>S6((A^_D3hcp zA=USGMeVne?lf<@o62+%w!de7XhS@ax~jEZ>+txAL>_;?ImA7~K>Js-zb?lN}EFFgl=B_{du7Yr&Z}G_HUfB}bBLhKZ z#=dZ-!8pkuO1~b&2R4TN{!&UrauCNK{k>Z;fBRU^8K-+NbVK6RulH!}<(rI)rL~Fg zACM!Y%vMYa8k33+w124?%nj+tBiCJ7P_R91uxs2*d#H$G-u{6o4GuvgBJD*%phxX6 zC%v4iG}ABZ6naXvcs;u&iy4zA_QZIgis|;)MdCPhp|Oaw`p?^|^{-26>OzX(dV?pUh{XS6INW`8e{8LE$8-|$f`&llEjITFZHs6i1(e9^9N>1~h1^Fpjg_xyY- zR#z}OCX zvju9r`i$_XPy1J|wyZlrhV@I88|o2#S&z$n99iNd86zH0{Mv3zI=b*$;dVVdzN?$& zaA4`@Ua+FC#4Z3Xab7F4N{3lM-xH$gYu`PT#37cR#Gp}{+W z?g#?w7n;SW-fZM^RhSnhZxnZYz75!}&gou|y+GiX+!0}t57QCvb)DV|Yd@wymGeYE z5y=+}+B=@BKi_-D5aV$%zesZ@ulzuqZNCXM-8yAbnDeYrW?q0451Z%2>J~A7$?Mi; zOSvZlJG^T>rH8s7-h06{GeoC0v~ePM_b-PLZKV(-ECw(b7kh<$%Kv4TCLFt{QV=?D zuyC5~xisN25w*{WxuPBXm?6#j1(pSFs!nkYYecVd=~?024ht!|m2yVK;9IJ%Y0B&S zW?Oon+*dgHO${#>H)AgOH50yM;Va%!mc`S`>Y4L#-8-z@+avP?uZRXmHm^MQJ`4(Z zD)ilKe*ZYWfgdbA@U%==!EtvAZJYB4vwwk9mQ1={&T9PQmB;l}CG&KdeD91F%L({T z*jlACbVEsIOLlO>*y1m5c^t_%(8*C&Z;3SBd4$jTaK|p?{l19!CYAi1G%`=7ITd7L zcp_u?3e8|76@{Ozk<(rXQb$fKgvIZuDeu~Ts9=Qw<+VYgd;?Bqkr@AX2JudvGzp!O zfwb=B>lzFL($lHzgY~1gAD1e9qICHAy=3%JXHCvP*?1DCS%5|HOLOk!#y1*F#tNj% zp$PVH>Me7PZ_-OSs~?}ec@8#ygL_a454`&u_?OhU@8kE={C*D#a>=a^SPk1FzhWE3 z(JwI3R)w^PJu&LhOEP1b2u2SC^y$Y~p64HUxHETb_BYeL9)9!uu&Xjsrm~YF^0xQz z2bG?D%^t2syn|d}ncI{*f2enU0MT#=EG>DCG=Hs|J1&MLRI&M>{2^PpBjmn^9V(<9hcN>yNF~*_$##Y*a z-s2~3NI565iL6QR;e8$vb7x8VsA_g%e~tKr0`4bfesYV?Ra(a5y&WS8!Olw0i93@6 zStGgcnov5DSVZGIp28*Rj_fu6`EIg^q+3w%`R4mT*3XbXa}FwWPKG^o#%SDYP$(f+ zkJFUm8&VBF`8p-_i0Hj?QiT%M)C1d}-w-zUN!N3tzh4fE-|ofi-^M!fpyc5;z**aD z6h>D=E)gEB#6s95@`s~jCdZ>-BlwtZ_4>D;0r7|1##~+5!EOkB0TvRIiRSaIX&|hv zi)U6sBC79PUqs72$5Gq0X~S8(zfG#9{^HOFCu19$*B5NOT&=r z_oA%#$_i%Jgn#1p#bR+;7UCJt>O3B`C=`f~YihJo#$yR2TNK(*;#pu`R`~p8lCBs- z`98^qg7Nu@`=0KDzU+kGop6A63%Y&Ph#}X&egC2y(fhZXnOyg1ZBm)uhxZfsz&FuD zoTCa4EMC;z5~gzJ?`{sjK2=va%A0PCFptpkSJ?gXd8ToJhMLr~+*Gsjc|etmwSw13 zab(f2R_=+6;rY5VP1L(8o=u#Otel$ToVk!45SZ@pNR`CZYJn4%N58CZ*H)>Wifi_0 z5=s;gR12cAZo@wwWfC21;P-l2F%Ggt5ctq2IE-=HiRo^~ImRyTJt$&7BqXKJ-Ee?~@cJgRSi#}N`5=;mD` z_!4)VE*-&(z}31hlcQmm=B$?oN^PF7Ta=^vOlPS(d{^^>WVnVAkL;=66 zB=(;<8&Mz!JTrb^AK|s!PI+fE?s?d>1|G>_if`!I2V8;}F-wu)m;Dju3oN?n8hYqb zbd>q24WwN7X!Qf_!KYqxYm|h_)oNp!b8DaM+EY|;oTMWs>^>hquUuBjQXdHFNS2&U7^Bf5vj9enG#O5gRkDuQFW>~B zua;jK95_CSZ`|t-j-l8)()O2v||}xeP&Bu>$R9 zWGuADFVh#Eas9&jkT~li?@=Sopds6<@qx{yXncmoNubTkC3s%b+ImIcD9XrVri#Q( z@5{cI@lRD}6Ti8`1O%<@gZ_QYBOdNS5@Pxo)d&jdSW|7Zap4tJ7fA^LzT}8l#1X6f zOv?SQ(ZXI*ep$`@lP@w99PbjKvP`~cl3i#@wkTF$h`CG9-sx>uA?2FIWiTgUf;=Yk z+KSIXqydA#jdG2Xbbyw~2mO|B6z{OHPi4q1R#&l-ne1n5Qz3g6VaGAe(_fb)@7V}m z)19ANW7)>oRY#A)Ne>H8XsOe@uh$&>Y=%iYF;@x_5uHz`2#=NDWO_=!C4N7~#USMY zRM8(38R2rTFe4!y5aDa&sU{H;7qi3B z5pqe-0q_6$WPFY;-DIDr5X*m8mfnvw72_jS;b65wh(RV-BxjA;04kGVYRoHARlh~_ zZmeJTeZNvsyre}kHsBGuALv-}Q@GfxDFZobwpk}xxqK-hqaY*v<^@WAu+^r)W5 zQ7&Flq7wwC)8yiN8ZLTHC5#(-1Bc6{d>d<=6ER{DCcFN@njtxq`vmeCa$24NcEgL0 zM>E@$BPByHDP^54*63SU&38lH90>*zDl|PUJGu;absl~#eJ6h0TzxXZ%9;={E!-Bb zoc@^FkB-2BLTsh+_cOI3{8Qv{%%U&7^={3Ax&=il3k2g4e2(TWmbpm&97g|*41xsdl+DPlxn%Ea(@sy{l3Ug<-(O$e@i3YUpR@Ig??LP z^Rhh#K8?)c2kB^sV(<$(#Tm*#`0f0;UqrUgjZJsR-sPnx>npCvY$0?d3mox>GdkgD z(GKvkMpo^Iql;k1A??0+#$%A+f>6|aq@44B_+yoF^wi_~@+r~A6035O znBk5o1FMGRm-?fWt@<}&%b8I)r*dd!IyQ2n$%ueJ*9B(iWcKLYavcD z+YEmzl|b|rgqp9xOlV?G`INv9npl60uA}PyonW0W)6es}nzB zEPM0qc@8L%fu3+oY+Q~ggJ%Kis6C1+E`)jk8v*LeI60fBpC&fWM=9JUW1CC$hMb?& z@U&LzIIY;)4dK@qr#p^w*|(}U*UiL$nd&uY)X~%HJXab1`2h7VsqDg+ zi?rOgyErPW-w$TtPgv%2i|4IPATq_XyO@_vt(1cC39`bS5ttN4&%S)$dVq)c7%hTp zKJ26*y??(;rSru3SlT8>+0Y_HUS~vfzVfKL>sxKo9DRHkuR{nKi4!p+1D*D)3q7s& zXNSC`?_^$@(*Y)+Sxw=X_(95I3{Ubnq~bC% zp2ZxJi?AAIp!x~EvG|<#iJr)&#iB4!vi+w*wue?#Z++bA-hryKPpp=>w(cIuY6-H9 z=bSOGD`7+5ShU_+WngUIt-6K#u}JknqNn!~qjoCZ79^}_Jix?-XHql@QMBij3crte z_@p75olz1C2?};UNV}qrpGuCw_xbd+wTDX~X5)a*&u?#RW(IYEd_NJ)>>Wrr^>E%r z)A~6n!sR-lKCYHNp#7t}Mk|BhEHsfiz~Vc-inm&x-`Q$Hc#R;w*Fe^aZKYsR#^mNg zYNJL8neknPp^?UW&+gWuG1fF{drCTQ;a%!Ps%D=_QVPp;nyp&Yg$(l)yl7*QWcwMN2 zqZ1`JC;Ro509FoG_WwyqYSXfIyjO{RQK%K3*6bI@LcKI(|B$?kNkJ2m+?YCdMkuz6fZaaS;VgblcL(it(04|x43f2!BO?V>Zp1pI9HUPNqTQr43Lo>Ie!4dU5z3_qav{ne08omA6 zNOkOelHqoKX!yOBG#Nc9=hOZx*IB(U+O#Jpd8=bP4o)2WP9CL=REBcdLo@!C8*IrCI`NOuSx`c&t_q40VO9_eihXuaIU(aw2veS|4z?UJo8 zX6WSHPDkB7sBfTee-*?#_pFwLymFf_##tjZ`8#@)zeau_-dd~DgBc+v)SF%jeBL;Ik`gdv*~Du zBERlzy&J_H#;tlNC2nSsh*kfv`TQB8W-HY(<Z|gt#w*MMYeHA7vS!_7@@Hh!YP*d znU1{qQ3G>p0gfQ@lp(%232`{@c?@wamFsQ941}M9*|pTLKuAFd@G#+%*eWsP|&Q8=^+zrg z(1iEoE0z@-!sZ^u2!E=U`p&YWA!Y-nqS*v_JKAEXWzJ1s&m&^Q0j+@Rz|qtce|94n%N1v4-Qwp zJ(w|!@2uRRG1Pzk0DGl^K!Lr_B5DW)PeirmK}UK$en+I1BvN_i&XF*QlyFFH4sjqp zbxz7VgO8yakxqx{_r>qsYWw~eT`zi#@?GS7znz!LGItN@mO{`T=trk#eG7U*$O;4I zy#2n0Th(#FhW#=j-;?*UeBq0|OU;OPH*(wjC7#`X78U<()&c1g`qTQNTGr=S-RCoOXVm)2)R4<9c1G@P$72{gN zh+_e7Ph8Vvi*HnwsO(ik8x>1|CUsbR3`2DLkJmHr1>LSZR8diD75Hi2GG)NVw@)J&ZX?1w2>a{0{8neYBiYN(m5sJb zY0*qc=UZh{^5pBcPQ+-j31z8ljB)sQdB&6vJP<}BJKgK#I@^A06q#8SGONbDui?jo zYlhQVMd+qSe9ORzrTAWzND`0(Ov^KX8*GL zAA;C|O?!o~-&N07ahWBKyPN~BbC%iLT_0)FpT!j5WJ2By(r21li)=h;Ptf`p0I#_NbIz} zM{tz~3!U11UY_y3?)PdtN`KAJC&W(k6l@{YSjZWShOtLL^w`yP4V_)k_0j- zeYJw*J&U3|zfSVQJ_0^h6JYuOu*s$QDj%B4|GhE4(ztIdsFiZO3j3-leRO6l>@Fu+ zZ!No_0Du;wIylmpI<`O#GbRJE(3qSi1-S9mXaNU^e#FD zG!aR`1+0tIDL{$LhG(H@jto)usnGknI#=QYBb;8GYPuqoJ}<87eH}kJic|*{O8Kdx z%eMkWP*bg}@Tf01o_pj4{r!Fr0cd%yOh6*+Y$&XZ%z>oAer8G?V0Fr+P=B#!WAjuZ z&8sdTd#>T4kuPDtx!A}vC5mwVaE4O^y)4Dni5+RMt)y_&3 zUdk+LE99EV3C~lLFeinKU{z4R)e7=-^sfUopGxC*lX7Q!t>S^!pg!=O^;hMPvh@&= zbRzQLn=M)uXPfbUCeF1zNP35B#gCtQJpj;%^9fA0R%d@x-$)!rqobr|f@-bELBfyc#SG zQE4x`H<8iLzf7}kVmR~;&i9T#H;bw8jC3_$-*4ypz3|r!Rcr&2&L2Ogp|(AVrTAx~ zbaIMqd$PY$tv_Bsg+cfJKfk$)y?8(E6x7B+;EoNl&=S6lbq5Fjq!CU0#{rP`;k17v zd*{K;1^9`CkZ&h{OM?p}BQPSkoQRQK&2^UZ>n z76lpPG~pvL(9gjlG0~W{Bhi%5VB>0g=T4p9baZFt?fh&KS0(f1YMWjN0+!L_$vh6S zViSwpsV54j-_`>mOl%5O^+6j>MJ0PIWNI?1LPtgi^sY5Q3iXtE8A|lpSS|yWLuhKv z#g#9$Bqy>LJsa}--~tuGp2~baO8T{+I*0aqqLh@ZGdU9U&#srrIG^tYlYRn|k<*%f zdTy{nnFk9hEq>KiQ=keN(e%MbKhlQ2nq9%^P<^0OSPPV+bkQ+{pfU^P4t9*sBfNKC zGT3!RE0XKPH@9vqtl(z5Es2k3iKun%Sk|p#TlTJjvdnkvGogo!382L zF4Xl6Zr1rv7olUbOYpJURRpfh(O(UL$u5V(W)&f0!$8O&a|FR=nZT^=gMa`}oQYV` z%bJyD3{#I<2>GuvTWo|c^GoDfIycc6CkbYxGh7W>Fz%%1eHuCsfg?`|05it~lsU63 zx9nry2F05!->FIyk>_VwN*j=AhY}>|wuBuY`!Nr!kEnJQu#^#Gg{ZzMHMzWol_Z%p znm3by6G5tyZ00kJ=$)#_JS@vX2{KT9_^TH2ZzrcplCb$@1bMzd5oaWFjEI|4 z{$h#dR_36r$@jrGmtTjd7?gZBgs3u7k_3*-VL4qFI*T6fdW)itwHO;ZyM_TGDPnzs zkN9Di8dw2#_smLgdgmrOef$$!d-8UWk)KOGK-pERN4lJ_8w+o?1Zg>ph@cibH}JCotv=8akWE*K}oARK39tXpzCcFLcQi~pAc9)MZTyKq)fP>EGnQ> z8M8gF-IRi&xNlG%XpM5MK%}f;fmK(yRwhm=)!3!qC>J#_7BKMxEDSWJ=*ros*AEb@?ro0K)H?c$+T4-Ud2bV5nRT^=RyL^HdC65_aJ z0c9k9Y%S7!7?UJ}u}<%?aZ(UHX9=agU(gL9Fr8A^c6hn$6%Tb3(NJ3%qPd1(BKaG6 z~;RWiAA#Iz<{h;wg zL{4@tCNKLe3Sy1nNhI z9tm5;8hTwaU%N70mtP1a2?q~|S@Z#n{}ARAu=>OuWlq)Y1^}z{0)$z10n$tgY7MZ- zgaaHPS_u!hN%Wkpq9_G0)Izv2)pQe-oqsZUZf%2g4}ha}Nj-53(5?^ST&yn~oCm3H zkDv^Mngd)MoFZaQkN*oTjA(CY_xSRCe!^*}4=)s-wN&?QpXB>)usp_^xEbcNC7!aP z$GRw@$QB#2KOwSBXj2?@nl5;#2A3hN{yoJ?AAeVS@az+}E@E!6%)C|#D~KVQ=gOKl z-;M@7fNF~)UN3lsCZ1sv%0UtYH9LlX2p#k~DKF{L!+WkTI(9yK{UU(qW!l4S2bGpR6E01cBFF(A`A+v@x#Z{JIOp) z6x4S6C4x*NLuCgL62>@jqngNn;y5_l!>M?w4IZlQ{iy)p-`@a~bw&Wi3dtt#E9X@3 zOLQvm%a3S&>ho0aTXg!LA1sFhX@g{w%bT~rgIYw(lJB+3_qq8K+KT@gY5~xa_80+k z;#G~wy!+mQIR43Eyj~Km($E(^h8=?9A6<0sFliz>=cimg$-_?P-wy}qF4%Cv7jN#= zaLr8~gtEV^)n5u_QQq)twhrS8VF}?zbei@Cwrx1d(Bi3Zz& zVA+Aj&k)%Gv_R4C&Ftt;T`PRT4wOq!YCt(CB_I=7jyJgRH6t)3E@eW_xrFs)lO|AcsV2cwJXN!yOmi3_!4 zvH6qI9viXr{=3Q@yLE=S%AS4p*E^)oQonDOeP5%J`kwt31J$X|)C7W7w_aL}0dj!4 zlM$N5uD7_BKM!ZM;=&x93w2L|)}~I{5MIlK>*LF<8n@@qd7BK)h1=H@-ISXW@qLv2 zPenOy?w#m-*2FyQMPKT20!82hhCNk$jWf~Qj zO02pdmA@xy+9Y5<+=nHGsV2A$_1cFztZd@VFV<(1Vk5~}0XAM$l#BFn11;!j(}r!E z$$jQ*e^6q-DY+8k-r1vgRANK2wEFKbYb<Cnhq3O<=Mi6%}|2OG|NdXVO|y3aNtR8FO%8 z7l(jm@g{Wq79Gf`+?mh&N79H?6;x7i2&Cg1qxLlN_*?E}h!swZLXdsTlcaJ0XXc68 z59oJ>I`0lKMfKY2X&z++_6AH@PK;OY@mP#4xRqoJWnI@j8hx$a+w6^UQsJ1Nt=wnm zzj<|KUcp$*UJw(EqPVEUC8%X{l8G3UK;+nxwOOIUfpDbjn`4e8^m@v=)oIb%9;kJ+ z??r%wk+dhtK4jjv=uOU=jtezys6n?uY>PH%N~pk3KG1TDmjLYTV=yHW2;Yvf(0M;e zTjhBIP3A z6^(*IS-I4_RBl*|p>}qiFto5{e#?C?TLJ(IPZ~<4Ips*jooA*#raIbzTt!-R3HRT0nJVZC9%A%%3Kxj-(R24q{)E=hcN0JTvwG(&ZnfOo3gp4K1l@j!9y;3_8$oo_ zgaB5g*rfb}YK9djY+ec4eh6SiI4y%(8yeW!oH1Eq^3qIFrINA4H7#PVBp`GfIx2>Y#8qJl7b4f;wwt#c0`kDR8 zaXj&g$u{h9u8rZ?fANC6-%`dMG{3SqAInEOk$xMkMK4!u}Mj zHSTxSi5YD*Dgl1|G9at=F6m|v0{Fxmxg~Y4FIs8U*#+Lj#4V#me0NSaX(g7>!iU<|h-su}lF)GdW+~_yF=0bx} ziBFkpy~X+Th)v=Rb9US%Ss@;mp^A{9m|3%Yo+jdMx$3!!dF#(8%MS0=@>RDvTPzzf z7A2*@pRSj$65M+oi!m_$<(Azp>GxR-83$RTH$-4(X)Tu1!i|b@ef^y{e1xlIRi=Z^ zB{WWb>ub5<(%H<|=ll{O&2kQ$Wl0&>??Ul1 z!wfS~&a&_ftkXwzKDQ$C=4*i4McgPvIOjhF?*d6S{&Z0;{Cg}c9mzrrmV&N8_ALdO z65jQHj#WGP1J&4|BBtirTiUDP@b(j@Wal z_Jog+I?M(rpl)u3IW`Tw8-N2u{DOBy(8+OhTlz-cFlO=(4k(BRB+4{R8u@%ON_70< zoVXdvrO}(qxBdNOFbJlpe%igs>%9)JEB*z)5V?1CQiP;=P?Bb0{@(1 zJg;6v$LvHHzc_CP*tEP@Ts*M))dX#tDYW zkM5R)7q|jwmoKSqtg-9TgoX$EZ{uSUCY@({;{!1CoV^!gOZ4x-*PEMG~xlwIaqBi1qUem&t|qB^^FJ zb)Zggae{(h=)e5WLWOSm3zC5lm#aUmlmo&XoN$# z`h8xmvDWgn4`}{5Xy=RPRb7++cEP@ol}xny`wB6bwz!$mL4xX2*jwrB;fG^CxfDxH zqeWbqTh5_)*K$!Fvsp^WkXl6x$32-rR`2V^%5kPLrfXc7-`0Ui#gj(PsXOBeSPGs| zHK+`m2dlONF2O~mUVph};b#b`z)Ah+g7ZbVMpd;{!%X`TDS(_MF}1yfL)|F-HFiDJ z9P^rI;_QIySS^@^P8*68(5*%#myzv!l$SwV(VN{=VE1fo0ywgh^Ap-q$3cpL-hoS~ z`a+>*Dytl8K~jB0)(1PWIJO~bh3MkMu|iWA{d21F6i2CDEpqo|X%){qN#Y?hN8$p? zW*P<;8lQ<71{R@rTywvfUh&$=o+T3<51vVW{wuv%Sc{B$pwj#W&>n?Hww+4rZQ(iN zF+e5sJ;j6Cs%4@*bcLGSz*=GCd0`VJ3`0}&fW2HlM86xRbIh`m{FGy=M`MR<%2@e@ zB49mV;rlSH@Eulj>LA7@L2~!V>MrsoSQ20;U2~J5P2>ypXn5X1%uFez)|=-sDnfbk zrNKDtHP^*NiZ&vtb$0jGXEW{|Uh4!exr8`mskdc|8bDt`n1=&kOIYg3+>A{ zZ|~RFdo6+88lRF{JE30#!r)6cH&NaKr5=J$<*Y3GEj_h7W|>0cIza-X3icWnudS=7 zJ0O_5u`fueH?jiblzZsE4HT#oANYp}De$ zH2#mYj{Q>Y=634!jp1^I^MvVbVz8alTk8TP1h6jfDmBYF0SOU|kY+fZ_hDZ0>@~PYn$d8|Ns+4hKfn7G1q`0E0{Lbw<}F{} zAKg*!VFmm(*L+8Ks8qnq7EfY8rUtpDGUg`A_NAL8PjvwbN=r0qCWWC#h|I9PBz(3J z#rW$U=-2xuK>&(^V;d?XSz#T-jr=WLHW8eq91GX$LI}#K=2HD}sN#_z^DH)F7}Vva zou!nN!H<~6o^sHrW$|fyoTYG?ap#9)$`Li$aExi{8K7b9!6!-(#N_PqIoa|DZd5-> z%aiqZ6in!pm(rfqQ!cB+nu$W4z9<~mllOie=ngeWT;%1b>%v`P|3O^Tn*4?H?3P*m zN}-!Bx$X?fe8kQ2py4TAm>tx)sCD;4p9@jD@LLH#YiCewHj^8LbNDHT4cf&hNq zF0)N7S!T`frtHWdF}r4zGrxqS3i)y*;O3<%`|!ahaQz0BGL1F|`!&zEIZ z$cGXa-pKReJN{FSj${iBj_xQ1;wntJkdg=6eBf>ZHglUDgIO}me^l9uQGEp}Nt%ca zBaQS2Q?1LZu*-`X-CH%D3eV?n&q|KgZLb>BBv)nkC@WulorjsHXMK+W`VZ^T@`p49 znU{|zpmNARgt&*ITg*Q{t=E&=qv@2{RM6=I11D>7#WD0vUy8F?LKC119MTa&DD3($ zCldHUiY@?j4yU7r;S|8pJR)0Hl*c9!8K|6z6YNd$l?&2FB5KS*iG2Wxi55?B!5g+o z0~t5bNZ(c7WkGy-BU&7@JLclx)-{B=0^6PnpR9B^MW}dy zPnoC8?aFGSC2G5uy#NVrNzPwTx%g<5Lr*t@dmnwu6J?iV$qEe{wj+Ce<_VX}`)8JH zZgJK&eCr&`&J3Cz+e)#Hx&sKLaVi+YQj-%VKRFQ!;vkB{C%v#s$DlEw-$Y!w9~So4 zOQstdtl7OE!R&lN;&C%ym%qTAnXS0|EG42fT}6DiAMLd;z&WpV!LQ&9H}6+!-1uHt z2K##q#cG33X7#ykltdzJ1kKq93}KU+Pa5?9NMh*Jkq34IB`H-IQ)t1qrcNv_Q;|QH4J+KHs81?MUQFPk zm+lfs4 zXIj7Tv$*9oka5qM<$s7IeG}n_OzmNlK#+OWJth330VyGHYc5V{?>=DiNIG8>#7O)g zpQaxj-|^!lp>70y!%iIAXK1vDs&2H1t@^B;6tDl`b`tjSUgrPVrHMsctbiuBAM*Aq z&R%J3x}3pc+bFBge=K0;9^<-Gtxcj)WBFSf#{Ant)^um$PUY{=^hUlheQ{Ai>0=h> z5VkMpS=b^fj8B?lG@4UorAIXS;nOD=q-00{UXsRFnUh{_$K1 zwBLJcHWQ(zhx9l)`L=Z*QAp!#H*+tDu+tVUwqEPRy7iuG$32j+za;?Q+r#{cfrQA4 zYbuOVm1{zRfqCLR-V1o`QkC%^(pWZn=Kmv&{b%y~f5-9K*5HagWQVyqReOVvQY8}M z@e}ZqFlp>d33Up!ysfaj`9+uFp;?zbVAnubbK~|iVhcj@Z#<|@Ri zvMZv7N$mw622S{;9M28`t4yLV3z_U4%*9s>*gqYMO+kvspZw+WS=`4>KE#X=Ly0AK zc5BtNhi4-Jnw@mqpR#szTg@}VP}{2g+OM6QWlKk;x~+iClRpACY}QNH$Sf?nspP~K zP-iX8#dRiI2}I%B_f3%^DK?3Irg+tA861mU!ZuCP;1+t!)V^5Uw;s6C1HMdHadKCE zqpS+Qo~pB%<2SVgjdP?I&wsZUXa5>anezO7>-TYJIwGUjHOttnXv9PB5SFE4md_Rj|f(Ey~qX0lQi3v?=@!8sLUf||noC_6;Ds&-Vdu7|V# z!>V~&JASHS1>|58ers0)Bkv}_c zdK>nEm{F)9kNe^8;FTBhmE=X0znV-V)I zfZUt3J~|%?6)SJ_2=FO8+L+4QIHc4#z4$tJp;Tnc-#IuIjX~p{nN8re4Yeu*Q66Z$ zuf+7GC+`(=?!yIeb9N)&-6pmxxC3;_=5Avq$RB2fqOs@fmIf5e= zUV`ST#Yga@QM8ViswSd#6wNI_Jt1ABjrx;>JhHJ)*%6epdLBX2mE+#_U{KrxGSIhW zk?UPh!?4eJ7#76p#!9sARMODc(&1O6HMs~^;g}IvkK-l3F54Q}7^8iCLkgKjDx>O76{&P)%8opFDYIBs{R7E+R4&zA_tc_8-)=)`4R81P6F` zP6;_7WCjY4c|%EuPO&t$b!2SlWLZE(n}7|v3o2u1aqd0!D;Z|so}Lo(J7%$2 z+hjE>+aTwjWjj!kc#vbh$H+A_5sx&aThtk?8kMNIy`Dw$-9_kYn`1O0ep+H@2@CtN=xakgL9fs-$0csrg&Y}Hxy5Zuw|`n4@mM7ESwZ{zL3#VQ2YYvG@NEG5HTW`Ts&Dnf|eF|F0mE-I-edO;{#)_nGR0!F@kY zg`^S!1I#Nt8vv3(*hie`OduXT98t(}%(CzO^}WKAyqdlmBj&uyPh$oylv`%yIEzRn zW0l6X__#sh-fXO-T3D#{0xP=Xd7)sQwUP(R+i|zoSZmz)cF0xg*m|)Z_5Q1zRDpV3AG^(`K#M92y)9cyL)W6uA z*v_mQR!{47>vxvG_LJO#x^JIX$NW_o3Za2Kn2kmSPC=LuvRqm z`bBI6Qw-AzO`JVTkgVJ226hsN0!7hD@ZyR`zft`TL_|~05aJ6TG$A`#b*Z?IldMf^ zf)LY*@z6!fMQ(2V392@*K()lNh$3g@L3{_pf+)>omWQ}d^5bnf;gV7IqqEH|f>~q% z)FAmRA|RgV zgm*&Z!`=r}=H`(g5s~7?Bml*$w>OL!y!^FcJf{W$m(T_8AQr6+AcQMgEB*ek<0KvB z8Vaaa1tV0Egh95mp>`1=gtsOF5K2a%R|nB!Qcj~A5Qu|g#;qXnyGSeA(%;SdWkR@1 zQ3kQECa=g_{|z-L|5t5Hmm7%*pvNZ>Lutz2;p=4k~c(p=HaK<`5X!KJPP&p z2h5tZQC&Ao(8)C_4EoK)kMj|RyO9HG!g~(`6RmlPONs+%s83`p2e2Z?$gYi)d~aMp z1oa#6-yDK_u=MFb>3+7i<%71-0XTruriCPFH8C6Lv>*df5SRv_v%={7YU*KHr}Pb= z4sdA1z^nZ2)I)ROD`%__9uMM2dJ8@#NHdLzn|T*8M*JDnAOcSGOGG`nV~73{pVm!5 zJ$VQUiS$+qBu-jsEky}E_u=Q*{bm*00T^}|Tlwnq3t$DE$-x95(ER8<%@E1Vvit~& z)dgC>Qq^O)zUYm7Vq)vGYP7!Zm%D<$*PK~mso5zixwzs?7pEt*qo!1DGsik!IcsDy;J8*!`@7uBPe|bIK-tAg(7cL%# zzc0a0-he3ZlY`TaB3slTV_5B%C!4JamukHQ$MB)zTCDPmVtEw=?;XDR&z-Dqo8uN@ z*a-KZIW1yslRUhURs8L(N7=qOcXiF~zw>#2-X5N&zbj2$;b-aO_>V znEKmh_(zv-tJ~*|w*sZ}Xb7vP_jiA~vhy}}K;-LO&h@YF$d{vMkzeUc4^GD(&$UM;pb94t81)%e0UN9&~Z zxb?a9vc`Fn!|PRRRxj3?zJeo1>#2C>n5vISXJ-n5)xxu&Nl-33Mq);6_w3m<|6`({ zeFiWchrqVlyHCh~v&>g%{-@!L4$X^W64X9eJ#(GRR@S7eCM4l`6j8F61gE8L5K}6$ zB2=HDkZT}HT~RFvA|{R;@N0cO2=O>jE(HY)U?N2v6`D1#5YbxTd7Kdp?(!vN#t)x5 z8nPolGIXL7zed=|AtPu8C;u8z%Cd4cgBl9KgA`8Bn>ynLq>}nei+`(ONl96u)U_!E znfq#mWMr-k(36m#VrBkO5P@B6Q|GAz+mDhgeEp6{cxlWIWmK(`c1XV94plq(RpAss zi9>&8yW1!Y@*anWDKE7LP8gR%XYyG%ToNmV#8i7)6O=>)A8@`Qwq9_T3M{-k5NJ@i zzmJOm@OqFuuPO|KJpx&NKgD=F1Vg!gL_yLjOn}}a0DUl9YXHKQm^3l*!cj!$q@bdi z7DT@+v@BWcVk(Jdnjr+l!g_>YYAjA5>DF?gV$o|`425Pe zt)=8iej2H|Kp*USDdK=vdk1BCDcljcRUUpL zjWg_Ef^gkGgvH-uEhk1~hy#^E)Zy#xh1JF5#1^4DF@?Y7t%$a*K)?2(6k`hL2x%Ww z5D%k7U-frBa&f-mLA_*M_*DOGAinE|j_6BAfA7@dPUyC$v>#sK%aP^nAE6Z%4;=<> zexnrXMhR5TeW#TBRw?IIDCc(}(GWhSLnTRQz0xY7YDfe=T=8kW9APBlz=W;rx<46A_V2i;M!&=r95Y7bF9&>U6=^&Kftay9mfj4oOWs!uP>Z7f}8+ zdhv{05XwT#fVn*)xztiGx}Tp_kw6@VkwLk=H$`+9;Mt~ELIgxinQW6$wI`>r6m=i} z%stlXkYbQvnMJgE;={UmeL@I`j8=6Bhp40%-4~v7LoRtk&+es=$V#KG0(6D5%K4Lh z`;(BuW_I)2--=Wh?HP9*j_bDmN96d$7%pyG;!-J3qV_OdKkhC!Y`?)LnBUY`!lYatCIYMq^&F8?0Z;L19r)RQra>>KZ1=s2jpelnqLzj4dpczC&vz)2_ty2HhrR0?~^2prk_(5TNuPG(VWU! z6*m(;)`k#X{SKb0Tw925I#(Ji$;4%nWH2Kj8r$3%RSn2_((}5A+xg$coySGFI>C;B z1CYU?arlY^mkbn)t8mInbxDwGz+4HD-1XZ=cFCM5r zSAoqFj}$nB2n!gEhmU~Fix(6AuuM2$PccR(ii2)jR3DM{chbzXS`&gfv+lF2_$ydp zr7k{2c@NGo*H905tfxfzX@(WBQ=_aR$k-R_f_`tx9sH5|=TE!xr=bJk7!4~pt~Eqw zRs|xHKHF=6&leYtn_&nv^a30|*6-Lwb37KCJ=ojt(-@~YjvXyzQoMw5mGFk^s_ATm zZ4H*pW5}9h%V->Rr4^!Xl6^LN2C-T3>h}n*T0bg1Rb0nvJtGod4Ph9bfq4$>ewPfv z==usudXS0GocIQ$-@-vBjb8{=<7*db*ETl^>+3`~{i7`GKv6zw&a~-4(9@5n=)2=< ztVoWZe1Up*LWum1KqHREVY-4oJh(=|!R)~Shhqe^8tLhz$bskJ%)PHfZ(QTh${07S zOin~U#!DXpZN;#u5t^Qa&2V^ZPd--LO8@0bvgc}%>u}^i;vhokEzb!P5pk4L;$feL;-dpMa;?CAI{Gh#$l2W zlMsg%8IUAnxBOfgYiFG!w?Y@=aRf2N&PN~5H$UD1y!AJqJFre^99RhxP^Wt`pzC}l zIAzB%>qt_#Js+h+Z#;XuAYBhaw|3Uabu=MyfaBsA*b3zg%A2#BICgF>yVg$X?3f~g zL%rm7e?}&a5Wit`ij)2&eWGC8H~=KDWNc zd`7{(KN>1Yv%5D`&D%z8xRV1oE;J?J{kNjj@{*pY&Lo;c%y;TS-NYaGhcH6{tCcY; zv{HJ0?hp7I<_&Wc_L>)x^Mmvt$EhZdd-2S~S-qj$!DS=%$Gp(`xeN0wi@9PRB#NK}zdT#U&<>*n zYm#?d2|5pP4UJl2Oi-Mwiwv2zO-Fr)PuD%z3@^=#T_Dc2lOdf@$$6c%xLl=L<-%1F zKiQXsCby|Bf{VXUyLa$B9awj3YA^TyS>ouS|EJZ;{Qu!{{!bJ>!+$GR{P*X-K;aK- zOxql>!t~54oq>u{Nf!C|>CG86K+b8QwWIP-2axiRh`4&5U8W}d(MaJ*PaiS|VsBwV z`W5ymGW(Mggw%?ie5>}FNyl~siXpMWL3M)h3N#U+ddSa=FY(^0y4{?>neX*QkG5e4}GIxXCoMS|$T!svo z%>Y}BvSUeU5&I)4E03<~&hhHqM-H%2A}BU!bnE8L_2u`;s7VWO2#Ej!JYD7+Fjibh zbmjXh|G_E#fxY9Z5)B~{DjnueJXVVd;{#1-?5h>MG0pstUSFped0dl|GA>T7hD0vv zWQ4_83&Hhs77?X6>@&(aWhPjm_VHgNSH^*Zn4|!Ztnrd%;TX|7M)uKd7X{)lkNsh((5K z8JNa>SdPNvIz$D2XUha;Lls0S&!fh4I)K8Gb>s%%fw97flRnovv*AjiE9mP$HV_DS zQfWxlgJFLWO<2yBpp5s{u8lZ+M`ahZwdexVE%BPS;lr6Z&SmD4XdN@68HbNACl7kqMTyl%yUNc7Y`{& zDhN*|$k-RgU!r8gj+Ux1W$$W2VjOXO$W?(v9cxZ!qEh+C9C$J^Vw$gw;SLL7a;SlH zi`LqF*#p%iRbR=8myBMx$27L>4NksO4JXB_<=}!CQ@(!k_p;TH(G)2U(`P;fieZwh!Hs z<5Jvru2Utw;SLl3@v$9mA{$Lh|JuEu<2+7*L0UWyr3-yR54okNQ_y($ePSDCWoPJlcvsc>Vr%lHM3w;jBHg_*0p4Bl~`5Br4u&-H##2X1mV*E&By0y`!Sn|y8@)*$%{Z-7M_FpK^? z;Vf-P`V)wve%r3~zCi}1qMGZ1MqiejgUSY4jEA`Dp*T@zz5`-xWMJc4T0$iH%CUmgb?l0_Is-*gmuSx)(!M*=g` zn8q71lG@{KXaH>!|SZxWlNN z#Q)Z2cD!!ka5rx!vBTEdC^fFM(>5wB&!4t{>{5`}w05P_#!orj$$HEch&h*V-QNty zDl#bDgkvuJ8*DcdoxKV)-{Akv_S3C4ZbQt5(0xhu23(*) z5(!NJ5zkEw+`fKCGp4UMG}8~qm?-4K7i&ppq46MG2N1EntTJ3Nsww_QHwekK^84`O zM6c?Ok=~sKFBfz_aDa~j0T)`1B%AR5jnrq8ycl-`Z;;X$CS=sHZ)&qS9{{ewdCujU z#^2yzC0!<2f2#FZqx4iL*>$s7#b0LuAls?)`}=-1xgx~JTYDPTabrxc%gsZ}8(psp zIo-3kDBORzmnfbP#N?FQ#4xP%JM zr!Z1>Eqg4=Un@9pt@|6T_uMU*)CHMO*&b&3&LOcrvf&Xm8l6(dST40fa9{$%#&)@u zW}Hf&hlAiJG?TpjHJDJ%mpqhyG-4;$1AvvT$U%S=Ya25aKQZVQ<15~4JfZ#ab6;s zeh3AHA$76m^VLb(`b!GP7z1}ezE%L9kwW4*jC^B>0>sFP9&j$X_W5cp2TJIx*4^h) zIfLSNlPQXj@D8&}N|pUO4YS+e+q{RVb~y54@T=rQrH*`H`o^PiPWIhXR@Qpeyd#17 zi70-niJfkQd2FJ_)GlGJUkEd{ zjPDzEy8NweDTkCSS8*Pz(r+l}UdDD2H*-0`(KKh@ghXJdy^O)L_WD)#S8{4?Fb+S% zWX{MhmPIpb0d|(9q_BMcJV%GHVZ7%hbvj2LPZSp*!_GU$G7Fa+%!UrvKyQS{iXLX2 z4&P!~ztbh+C$~AHYiS5wvy#QejTSHeIX_2(mw-l=uu~sSi^uYOK{-*KpnaI+! zYi6!Pwu|+W1JvYmaz&2Zuu6;D?5bb^KWY{Ek27nb(J%P>J`vM@ikGba0mQ+^$nk#_ zFR%Y$k+)b8dOp?4TEWUNXYAg9V1Qpn;O4Y|cO!BlN=k7uetpmG{=_FWEz}qT13Jvz zWE7kX@84z0r4054;_&W{{o}1VJl<<`0w&FkXfkzq;riW*|A3eWGkMS>1t)l2Zr+_{ zCz%x$iS>v}R=+iTZQi%`^r{@Wf!*QGz4~^4h?A{1ydXLC!j$rq6gz6IQU{-pF8$zuh9(^=j7nSC`+=2=A*_&;0JwV6dN z50n{1I!F+-zty3XWe*BK9ZXVGhun4vKhD$TYQ!%_M#w{#bMi2Aj-u-x$x9@tjCLWZ zzQl<5kKF@rmcbJnS{>G&`KU_3d-06gCAo7c0TO`EW$M|!eQbR{KRG<^PFr!XYnDyl zy|!lB1)@L<=c~rx7Vm%Z4X$SLd6XN!LX5{2!P6`XvJn4$m~n_XB#oZ$2*(~P3v5Cv z8V&v!`f0-nR(e3r*9vR9bMz;12XvyFJL;3KtMC#w%tT~$K{^7Jx5bX|FUFBWWuJDrsSfSo{bxnoE!*`^KFN! z3=N_o6n-5!6McLYPuq&v9D!WNwotbzzUc%RxO1H0pIk8D&Z$KjZvp7Ec=np{ATrd0 zylwLQ>}V6%vG6b@$KrX0Do0I)gyB9$Cfrn7)2TyOSP>B;$>1UfQ^8nw%GKno(Q!M9 zcZ`0{ze3ZB*HzF%6)GNPN0P^QUiLcr6|^TgKsYTvFE27o*6s=;iFpLityc&^GjQ+E z3n3sFZF6L7p5F5{aj%!zKVMpHP5|MfLj`wYl#5qC#Fe{zro}NgBq`jO1>_OwF+z*( zUJ*m20(K}tLSX%)?2YvX^pu&_wHk;#!yqd?H2=KgBqT0zXjE)#ew7bG!#gF}^HGGz zuvXbWj102GW6}`R(-aUiv*icUJ_8RFE!$gN+dz_&9~WI_O;=NK)Ev=KXa?1lYfAF^ zNq1Q_1RVHmjW8{=2Z=ql<17(5qD7bmXJkVjI0UBb!BJ7@)b5j3f+!@WS0%Z3r^4a_G4>hT6A8657NDZT%sn9!3nlCOJqAq}(_%)9gML$wWzMtp;LC0*;24yDZels8Uh zSH)CmZQdc~8B@E@WnK4lwYb=IwO>CM0L_9<_Fv0z&$9Hq!B=8*51x+%$;<70<*-hy{-D_d9AI%l|>RQ>7?Sv70iBIU4zyP)E>T6bWO~g71x|3Bj+&quwmmn?6g&UPEA)f zpdP}h*%O52d`h!5Di||r(}<k_-6 z)KMVu>Imzp_}-NG%M$DKv<&Lr4JFMF9p}T}6334#S0S73hEbj&ya6q-+=$7k*-j?$ z-t_-4_D;c_MP0jZY}>YNcWm3X?WAMdwr$%<$96h4{xME}Rr~C-tM+@U-kVkHV$8d> z<`{F#XZ#*AIYFT$=fbe=YR}cp@!m*n!3Xz9m^s*o6N@5yN^2k~?F~XICBSH;_D2V+ zQnti%57IgbRUj6rY=sHjP~~~~bTkt8!aS*(_6ePFSRJWg%+sB;C&WiCz(KAWhZaq! zo}JvUa9)DK=;&CiXiB5UxAm)xG*K4Zm{5id`%twc&ys`@547lIKU0WCc$Hv+ z)eQx4zk)Xs7tf9JV*np{(J&O`VS6LEI~drRsO1?l$)t7w-o9qZUx+hx$Jiv!^wZi2 zmtjSP(FnuUs4Ips8_KPz4qJ-c%SnM)LwLHoli3J8_-a!%$bY^G-HJlrwv^4b&(Z`9 zWltS;;Cv-MJCRto=^GN&G2-?=rNjS|ME3u7uQ=HMJ5A&0|7aRHkZ!(cRlSijrpMt3 zCyar&JOqgJFt(1B$%Jnb4x@Ba^Yaf>$VyvH>yOZy=%aAvd>;uO4=xA76|#pfPwq<$ znP!TZoISr-pu7jpRUEaKxv+>c)QvsAI6fanI+tDX&p_rButWcFTrRE8E2gcZOR z$@4rQM7<@Xy1?{!`hI<+`b4?@W#)gp%sS($j43zeZ#^|I2-v(EVX~0_$p5bH|9I_s z^I2-HS7IR!7woh9 zI{74l|8{$d@8?txcNAZIiPq1&oh&jyi&5}NLQX=BcFw;{+AU;ykg+Of=rh?f58PY@ zRcBk05o(S?e;&`3QD1!`i;SuMCd$BU6@QmoMb2z(E5{N_*oB=55g`6l z9mMt!dd_fjgouwS&^-gKK-*}z&IQ727RmJhnd9n35loP{%T7(dqH{xw+%w$qmrRSt zh50Z&+*%dw3HaYufavzuTcZO)q6wBCw+?_+w-$PU(zg`XGYy*NEX$#>Tpi4TWjdDD zbNa}E=WN>yol+2}0y5^(N!S_ug$1tRlzRTY^Gf#{$L`l~taG>u@#5rt`!VeO;`(KN zB;sQj4La%>1kmunaf0LiI`$B}a%R%Zyt2=tG;ajE`aqPztSj}Y8Fr>Dn42@eJOHoxCUc6$8p@ z3WS`l@S0gEjf+_JEuA4KfzDY;_vp{6$c2M~+m8RX_#|=2V?cr1tYPaf7I#A!l%}D5% zSb@}axt_U*S;(3B70xtXeg!0>N|WpI=2qnLnmkMh>9p!YKn|LuSw_Qq*q4pOJ;c9< zQ(?fhdpwN(Qgz>N9cs8_5DjPAQo{nh{*SIz66vw{gAXYokWDzfvyqe%cc}M;v@4>P8(0k~ zw~Gmf_9P-2V*(AlC;8dcWgRYj*XnYs6$!x}xMn zCE5fnA@B-r*E;rrYYT?uVR^d%-*sraPx>5m+`s~Ka}thaf^OxrfBL9R>t^W%Dryy+ zt*9rR1Tlwz08R9?(6aBbe}kR-BP%4;{+K=Ih`B@#ElbNER8_dV_GCG7^rHE|E6%-e z+(BS? zwgH-s!UY->hv89ma}+#dFRE_6qyOj`ojDd-ms)AW>K^dZ`H?}7x+>r@Wt*&ibWog| z!|y*89m?4PsXrN)dC zW|$?0mM?J=P^>Zb9sTnz9$^y)3fLTkBtzumrHZXU*MxtA4||kLM(XmC7)HN0=45Jm zzwY1T?C#6(Zbkz({hT|9oG#zjNANRPsh{AI@Ks&Bzy_RuwYr|aXM(cUyYBgKWotP? ziGH7VD}q~gPjApOT&Aa>ai8!6tCk|f`Ed#yZ-ek~wm9#(z0uROF=**-uB3QU{_od= zE#6FQ2EqPs$Cvo-sj7Iou4sU^CUknfz|PlQanGl$fxl1U5V*(N+S5gObdg36!qdkd z!`|MP5hl=W2)Ik5Jal9ikdRH9q%5v61~e2I1$=;bv~c$KSUOZxHj!sfydqZc;Jk9I zoC9w1p6}cr{2+>j<46+gi%z2Iq2fWV2nELC+;Uk^!QEnsR%yJTd`~yjf=eK6M$4xq zAZ<5j5>2y2(24}05{=qMkluVC-67Y$Tw{FBxQ$Gw; zFwd2_hg%V2btyV#aTGhrZ^^0-!Nf-p*|W+5#RX~g7D;g06jpe(MDdlR8h(mQ(6G-* z9^}%pp}zG=QwkgJNs+em;^?Hqr_GxONo^&~h#@L28ai!^L?ot70@O52;Y;_l#s=4c zw2%-ph#_YZAqBAaj2f&J+zIKRMJ08GjZc0T0s($r>h{U07L>6w74@=Opi2cU?EF%w zxlTRWBQgVgR%UtU?U8?LBH&~5g0+0Xm#WRqs2GZ$M@uA$6PYxWu^cdQItxEHp%>Hg ztp8R;+F2_`|?TEICRgfhW2T>7ciBtg7mUF>6So#kI2PdKx9xH*Y zB~UjU_8?WtgTISN<(p)3AEJV%ZYchgiKQ~4SRaAK%)_gUTqT&pEbJy2;o~hwzqc|!6+%ZoEH$y)UYnbx7R>d)uNW3o+a0GD0lW-F!uy)7pi;Ur&h^XiWa4;@R64h6%jtcTr-LM@(@Ak+kDs;gHV-8u=5dnZ2=yJ8P!xSeNbtgGT5r0H{Icg$L~ z*Wi**xT&U!emXH?0h5F0`O@Y$m(g4zBT9zyTY3CyBGe$Bz#_wqVx&5x1|U4MQlEoA zUo}=)kPe9;DR%+HYPTp;7eM$K8YD2NIVhIcax^TER3)LbbtN1@p{8V8SS*4H{*IVH z5?+BCU8m%_3IWwrTe~*YZS3=5`QA!N$~^X@9);_6x_|nKgZqqh(mLM+DQDZa;qBVD zmT9hd-@(p|)Ateom@cR@&L=UpAMNlqO_1N7@>mwTS>j*s_8suBt;BEAuQl$K;yheW zylM6iz4T^rylXXdOwvr?X9q^B#bmP;rxv7vv|LEo4;wXp(d;CMSolY+a1PX zxNFLv&biB%t+r3Y(zz~N&fdE<-`pt6FXyh__=veaUM&G%Z0j|0$sRR>>T#UlEV>uhax*tSsq< zSmgjwufiT3}~w+0djH2RtO30l5fFf;r@dF+)`gMl_YgR+&t;P zFHphtLrnXj`mQ2JA~3Vfx@Wy?(we!0>;k>Kl=);(fHW6X?z75TP?dA^x}CvN)#^N6UZ7MQIFO6oY+>05Sp_q zaT%W1B8x_%(uWzZ_Euo2LJ@RDsV?7bnqP|%gk#bsB?g!w^Su6Al(N{;OkN`UZt1P{ zNnI}T#A{W#i0#(=LHS&(C?VgLLXsCcJ`wS8yJ2W5?`S(Yc=_4@!Ni~e&6`DqLJk~nwvV8Lifnp~pt(eYk+e|w8NYb^L zVBL0_{vB1u?q&kz$8+bW+Sjo&TFtGki3e&vQZ^0$MLQLauo4Q!dt&_gatw$}C*qL> z;>PT?b4pRCWymt;)xHp4tEC<%)9_z&+Kf1oGk@^*>m$W6BE@H>+^JeP#?(}+=X9pa z*abfhQ|Uq)(-n%H|zSixbB%LjvP#FaBZMv=fB@`8i4!@Y(!`S}Hcs&2ea&7Kja#bR=;`lPDdtMy|?`ZauXq> z;~2Bb;T-L|MQ*v!i52eJDWn8JV#}hu1&Um!+TGawD&8p9JzoFVE=m>O-*5kA28}vhWSYif+aI?XHq?i zd_g@+hPT$sF5#Q&WxNS^(MqMijew4*#E&clW_CFEh3^$!MQ>#oF|!Dk9rjJP)M~P+ zSxhdYe8xjaV4OY(>~MFHU)@Px4H&eZ=q_mD_f7%C6#67iOWdA9K9EyK*u< z5U0{ZPOG4MaYL?M91}}uL7{1XI6l`ea{*jU~GPlR05 zN;Kqtfi$tX5Ql70`SPf`nn<{5(v#AASBgk7MjJUvLBCE;R-}I7d}#W~`CN&DL#LWB z>jDc^w~kRZ(jbsje0&$JqCG?u1!eB~@)2+lye>Mmlt8&>ac#q8v~I|DL+b^GW|5Tj zISb!B6aQ+ew+tK^;*;G)lU;fIb7k8fYNE4-V&tIJ7QI``14mGa(ZH9hu)E(N(5|5kjy*AXXpYYI0;Jb&S%Qqu0Vh`5tP>Vy2ATe$T6)&)8 z=V%c@_L|&uV)5sJ_jpY0-G5D#R*rqSr&=SHeXqa$Jd+5h(rNOhixA0--_FdrmL z-w~_I9PXF%PXK?!HBfLrb}Pj>t~$EI)hjqDx^)HRMxm~R*t?UMIo>&&labzZxY2=LGCfX$HTQ5@#Ggj=(! z#0sL}Wq;Twqf*t2^?x{^a{iOA{%=X^|KIo`Hy8K+Hhkb_{_hMQdbQ>LXL_;sQsXW| zm&?>IK`oGYppAr52m~t$Q3?zn%?k+&**zA3UKJxxBnxbTG-aTSxA7WVx&weTmv~2a`DN z&@s5B*F(Qsj6Uobt3LcA-j2>WbJS#fCBiHM5N#cGQAO#BKCPfYVTln=k!4J8PLOOmW){ z*Tcu!t=pzDaSRhg!36g!bveb@o$0vN3TPmqRwqDYV3%$cYCp?rhGM3|3wq$BGW{O6 z51LkBwzNis{oa6eZyR#^$-kRqt5omWCDwO`U>xuG|gmL zJ?WNFqx2v!v%}SC=Rw}-;Bl{AiDqNe!N3;7Vcyyxk$$hbaPR*rVKodnJUP{|b`a`V z(_j-#T|0~dm#5ii$e!g{%K|@xA=gT2;Opf13}cVO@O^mq67b2|H612atlcy?Rp;;j zasyZ@_hiBE>+|>Udwdw@bcna=NkG`^>+I#<)g|9#_<5SX=45o(+a^%i@%QxibBkuq z8Vcm*S~FlM9}wf8!r*_bV~}P zyF*ZK9{{swR~(Kxo?jQx=jHQh<#PIZ?l68E;Q6=$V62B>z}1A{0N~v2?avmJT#qu= z*VVPh+2VdrRu7s2`!H=(Dp{E9Rz0fcw$sc){0W=+=jV_eD}c*^+ia1=zjT#p{^$2^ zgC2oDV?qI*Z;$=ERA_{oMk5G65B}4Gob)z8yoggYE&o?@x14z9V>2(p@K1caFEF?TFOU)SoAfV{OXoC#f;7Z^Jl?)^E z_naNKU?T7o${uj23&2Mj92w-s5U(9{qQJu~`}#{UufY{iX#Q5HiVT|tVo2n~1co>* zt_*i;+(jI4DWv*qHKx4sG!zlMcQBzs!gy6JNZ_(6T5~r+^Lg1V_-L{a&14B=f6>a! zk98wl;=rxIx`MNU?1G6Hg(Enz>43X1L!8xgpg?l4tNw~+Wjw|(`9cp>zaT}lqL3kz z%}B#dbs{d+U?+(gX1>nIP^yJ^K+U7bgW!hl(2W57ZkboCGo*&n!lK9lB(dNRqFKX} z0Xqb@*!3WRT`iLO+=1+k$Re4|AAmzy{yC)MAHq@&5pQF1C!#V7hvEB81ysmO0c@WT zOi4sN3G+nEsEZh;hrsXqZ;t0KNv8O$4qgg|l|a-O6tIC2Jnsl2hzmZfW);q|k;9A+ zwwAzzAUiICM3+g_K2L3&PAUfqm5iSUWQHNi38kwh%5(fuhOM3P6o+BY{V=HdT<9A zuXr6$^9%YmNg6X#hiJhp@`DJj@-i!n@3RvVlKI{&B?N<_iR9ePu;OrZst@TpqGJjP z?ehI3gRr)wJdy)k^+FIx|1aCCGolb()1wI$B3RgEBO6*n??1DVAnc5;@Q|V2dD2 z(~@1D^$^6{SXvgNu0b)_vTK+{K*!0w8jdhsp@`QrVvvH~sDFvQHFZ5EuT>wo3sr{LSQr8wt zaXjoNK48e_S-@NDt`M%l^zop!hNoxmEGQL6EG%8!T}qNiS(Fmtk&>h|Ij7UTpwn%m z#@ErShA6hw&kf5C!%^*z`NB(`l)OcHY9-y%RR-a%9GrM48P5wM(GO*Ub+C&E4YvNP z6QX>3#v4@2=0Fb(o9niYZHqWQu_e~1<= z63&`WZ!SfGgQ3PTtS!||!y6SEH4fie;m($-;}@B@^1-u#VyLdszhN}1NO|oqN)Izr z*%hs^R{rpU4JCP4GEIz2dB-MWfDPNxMh`+IH3~9;w+QiH-yjD14~`-1#4u^mV(M!} zv|@aK8nz|=i9s2h`v!XbgS{auA!Nw}r=KzB2pY0Jn6I|Z(7gp}X!!fbgCi)IUI|_w z3d9{7#8z8W)hzaJS|wd=4s?du72=HFPQ{e>#@4K>xThk8-y^dF|pQ^qEuNVG{?x#tfDwe&`PXwh6S^4oj z!h|msZNkMy<;f3T)_B=a#G|sJXE|&}zP*Ivohn|y1EeG(EvAHB4d362SUU*|j&maw z%XKsyj?gfL9}se;@O`DYliY#W3~7ff(YZF zLCe}IQ7J|s6s#-nZzLG0<=gy7j6%o*1#$#rl1RNkVOpv_M0(9~`jA*fJpJ`XXiJX2 z%}AtB+zBgAHD^mo19Rig3!;TEq0-KRFky;HqeW~S)nQ(Z>|Q(+SV?Gb2gneK+#}v- zB~zc0yjBSsI+H_WDmggjo6;Brl-y5=Rp5BOp#_5`?Zk18stM$ZEnH#;@y1!FSp>f9 z4~~}4>odOx-{rOL9~0C@U#5sE2Y}vk!4tm);POMOM9_Wko>8ai5u}BR#+^>9@_47~ z!bwbA7_|>ev_zY_tLUnn`n5YdKL&gPY>gnWF!@Y+6(jU>3NCl4t)G4*kt}}5@s+4WofH^ zsoQ3*bnp~`@KBf9m+sr$^CFv;9M2remy}K5@MJ1!f=T+2^o|)C;xV;f{&M2uQxA(% zb6m!3SXxsfBOB2npkqIC|KaodU+IOJstT^0njfPw3x3#n*SZf7?8o$yet0` ztI{t&1tV^lpJ{;^9pt0!=cH z6aKv+x!7#aGNW_s%E&(+qM@0}YUY-*Tk7c)(L1vg=OyViP}h^)2pY`=-L4J?lj1lX z@p1e+G1+2Q@)tf-84W1Zu;et@y-tu~v}8+o2NlaitQ?WUS|ZkL%0*%iwPuYTm{Tyc zF#n9lrDl)eHbT#5%UpDLRWe^F<|H}m5TlH3CMGr4(qhg~bV^PlZo{Xp&=X69nf4^X zU;cFOTn_MK%C%qja3DtXuaK3IUcM{AXe!mu`ClM(dP*$2|M<-Tm#ig>5dNs2|J(;) z3*GJ@+r6OI=#E&b4zs9+O#9a4z!fxK+A@czy}6<(*;RsvVBDfIQJ9D9bB)V{#)geQ zW?RIX)?{@ua?Lk`uh^EpdQ@5UlGejAZ%#|ItYDj#WOa}-sIOU2ORDQ`M{RN{K}uNT$ysF~0LOqRD;j9#%Vb$pIA@nAvo@}0ZFAV>B^I58 z+_cW@RO<|xhfSuLuNu{1TVa3wab>t>@VBLCTB~b)85^Shpi*i(kwx4nq#cI0gc`YN zTeI;d-_e|gc~{A)H5v&E9D^A@ZAIi&YG->sq8kkMO^<*!+WNcR!y{77oI z5MS*eYwCIxC(Q5}S$kjetJaczFF;OUf`ev%K5B9s2+XZW${%Sdk_ase1!^fzosFU_ zCs`lZV!aC6R#rH25%kNl*M{c5QOg|Bop*Xh*FfwXs#BVk-z-5VYbs=)BwaS}Cx=X^ zia>~Au}F6kcsKYzWdSCK(*b_pPp9#MgGzGwKd5C7kr~S%bKf@Jp}Z8QP{vaAI4JDu za=~6#_;Q;pGV`S{8ju3=m|&DZ!_Kp3=}Z@m6jB>Nw1bLnVUgg%tSM4Zu&aZ?H!{4M z5n0TlaWv=$^fgIF!?gRbs-E!q&%LtX%X{U~3QMEebSicw@G5u;us**7WLQG=p{qq{ z*I2*+WR+~_g`Ux0f-IX4I*9`MHFCye&d zNnKRKMuFloq+n>8T$4ji`vv`H9rJ+!U0!8w2_Qxvt(kQ##9{pKHt5y5&LdvlnR+$K zraIB~WSc63%TK{^^dKn?Wnm>FTPri$**hS@cYw_+BuQc$VWfEvBRlkw#0XVSAybqp z7?F2ebeR6X*9TEG6U0>U6KC^!Z)LAXR9soZnH=aGyuN0?`}04v%u3wMDqDJx3+XZW zJ$&31`%F;^AXCwB4`#_;CcO=y- zg4BONZ5CsAi`+O#&VM~!R+wJ+tb#t}eL#4iLDISEI&)YpTwI<+s4u}w5i`A<_|;am z6`J?RZ8ha=(>rgA-xR-c;uv${uV8`iLy(#pBlaoS-)L`Qf{%R(=sV$oez4$Ni9Qou>k%oNi;fXj+qXq;jk1jrmwwiOu+zR zsUSxR_k*X_hkaOE$x7^qH*wW*e&6raRvy85+Z=A{}zY%TWTxB^dr zP6M5SLtF@;;~L=?At&=?AnRc$Y3vS(O3}n!GfAxM_-@foBW(?1#36dKzK^HE@@d7N zAY5zI)GTS_kI=N3l&V-3T0iy6-VNllUs|c|{J@7(UlDQfTOxPm%K%TZXME908Zn%A z;-iM#td-Mv+%)qJ+|o@ZhedVq(AoyEKm768pmNx$V_n_lAve{sj4R!d?QBC}4xds100ro0Faxh&v z)uk_Wm3;(3G%|7HOfj*od8bLAq-RZDYrGgq;H+0mcG%AbDxp?;c(mkAx#*LD1Auj{ zdN9*d3lZf~=Ku77Zr0RLwv0k+3ylbSKDfE%hnS2#p{ZvZnA41)cuc5DIh)uKNJTW&mDntBRp7iTe;IV| zOn+1dqaRiSA1#2$mwEfx{QR1gLxWa4u8W7}3|iH>b#yCKEA27ej!1rCL-Njkwz$nZ zc^2ATo8?bcCY{)d8;a#mg?bj>OspKgrhcsiSI~f7{T;ThBSo93PNv7~wnw0A$qB=z zlA>*^Wx%Byq0HQj>AO0wJHJ%@*{;QsFz7@e0D{&aJsk=%Mw&Pa=<|$L$X$v z{-g8qh8G9iwi@&ol>Pot+U9pV;8TgU8Y1VGxDU_~6eTSp!CL`Pku8N^VyBSiG0cF4@Zp?Z$LG8QeJ zPm{XkmaeaORLQN@+5WZr*T#9AOWWke^n43J;fT@%^}euiha1W?pXI3;#{lcDY=zc7 z9aOe6JaJg;61xjYX&*tICn1-s@m8J4@@)SU=%4cPQM#%5$Okk!1X`!+i-#^^?lvjCIl68XUO}ho$MMwdVqRE= zm1lyL;zvR<4uP`rx8EDB=*Uxgpe}j6!=P&L+09zAvgxCESEBl2Z2IImROdC<_%GOi zl&yv4&?P^0+nO~QiD^0`C5nVsL{TUKQe@v$c#*=BUhegQ>u5zCx$i1X$E>_F-O-DJ ze7(jJ&lqDsi-3CL`-(s1=tU%#L}M5{-!;jVJvphWq<((2DgM(VEp|Xm(*HzF{!bM7 z<-e%OFnHa5-8P*{MFr`mQyMkMFU?YA36VY4Q0aW0QBcHF8eEnwMKZW*{@f-z8yxrL zLIgZ2F0rMQ$o^^^55WGSSf6vcJio#shrJ^At4nL`Z+~~pwEgN|w4vShH_{hg5&%D+ zn=Gb>4>@|(B+ZUPraSjK3=*W!OZ{Q%J!M#>2Hxc;Q1Eig!uuI%r-m)c$$(UGe1xg9 z1n~v-Ea?NPLu6-{8W$6rC7Z^?rPRo##J_PMHuCV!fbV$>HK#E@d%amZ-ixT|kFw@3 zrd`Cc#o#G3OAYf{Oa+qd&(_m2LVnj4z1{@`-jQB}D>FQ6K za|=0QNTb6U(OxpxZ>%S1CgQr3ldxcfwD#+GiCYZcfx5z-!pX+2tlh%{UpoZuu5DFg`jV7Y?}$fTeXE+7Fu0!Z~!y zy11*SJl#2=ivjeb(zjSEq?tGN$2&8(j&RF_!YiEZo;&TceACD&I_uXE{@wJJ2Qe3a z?&RH!@b5ASt~8GyGd#7JMU>GKdWfhVc$XBA&dw;G6j{I5N0 zTs35qvBbExp1fBG{56g8HBA2wF~-iNW4+z!#3)JSQ6X5eX!^1x9DumG48QycXz%?e zqd+d!|NF$k!p#2P%{=vLPusJ$BkZ11e}bsF725yX2;7qixw=(MHC)wNELKL(KNzKV zs4iIAmR@g%oXo{Zl?f*m$jrR{DJb*$_$S}}zCGXXcfyichInpw&X3}ghbU2gXwJnP zpZ}I%h#wXUD)jToROY5Qjv-1~!Ta-l6W(q0eHs$&Lxn1&_`Cs*1l^n|U4ibpCu;#9 zd@Ymk^7icVuW@^Y^8VB>HA9Hm95D0R_G)2gq4q8qZg<6tKa7I=={aJfG!XfNHaZge zMqNi+_%@f?eqTSz_3gJ7$EeCiUVEv>W*d3*(*w{NhN){?W?r;0(O~M};JS&x%89Gj zG@uq(2~GY#%eCrz-KPATD?Vb7i|^CxA)u1E=6 zfZB!As+$?<+C0Pqi-a1RUnmGwqSvT@bZzs-Ie7cp8z(uQMKt1$xIJALC1LD-%~MhX z2@Yzyyu)gl_I^BaKK(WH$g4@TB4xStw{)Rm!ov3<>daF0Fc};yjNw*ek1U zk1zkJkHAGz&t7r}5GaK-OkwI!G;OxrKCjAqtt!(N&}?L%jONZK7h zpX|0IT2i;*SSszCR#7?O#6JJ%iyF>aNInJvX}XA#bu73S`B(iD$DkzC!A{f_l2zR58=v z3E^%?v$d2Q{LinGy6s1LlahA0B~uQmNt-3A>526RU4~N>_Q%>kFj;pq6JzbR)%vuH z9wZ|uqH;8M4Mo+V?m@>KQj4XgUTT+RW_VJy;LhK58(V{Lw=p$^$J$J%xlW=4`diw( zv(w)vA1!tbS1r=lUiYi0aI5f%G+g!`0qHyZ&4|Z+rXCMUBKZ!jUe5!3d23Q;raE2~ z?>U(P-E|JT>(LD8$TMxRekV$zjhGTTzv555bXwh1cb_Z?P7b_WO3q zqb`${n(=&2!SlQZmH24sQt=zp!i0xPjomZ-;*sn<4C>df?zdW^I^=j+ZGIT9mo|?C zYAp^tu9tRl@vsrYs@I{rL;XnVa^60l{#YZ}#oX=wVGq|B!UY^>{gOZe9#Z^8u>YR< z4oVAcamCl2_VEr{q}XuwkorDOjohf8Va`_-kb^pP?#0I3(BD2s{drm9ttg#bG6hSU zYpPu(7ho!8*r8&~pxf%fL=uvhr|(=7@8q)2+*+1n?wK;K`TJvmg%`y2jD6Pn2-n~~ zYX;6e?|#C@G3CK2F}^95`gtwAC|=z5iTB>3IU_ZecOy4{t&8utVnK10LhpfD&ukF) zrE4{r=8wml$tK`JCGBg4x9t7036kL}E&SCuN?Acp%W_Ad-SqaQ!2PNnU937p)m%&| z->Yp|T`s~pPIcpQ+9w6ju{)USdrVA4oGuNEN1nFkCiT%a1>guxGiec?%{`Ra`_P#s zt|as{*V@}k>79Jdbq))3%hG21Zg++#|5uZz={MPRjvhOGEmVZAMccYK+85|>U~BKa z*P-J8r8MnlZ?S7XXg8J$ZYA3#jw8j;DrisE3?cLA-1$bH)3361Zt8!a4G=dIzfq>0`_Ur4%){VksE=9`m+ z#loM77;|B(q00+dtz3gD&#<~jSoxOV$_JG^XEolsD`}4~DJFivq?VodVY*ak+*E$w zCLqRfDe)Ox|tYsG$`CRwBvQ#UneNzT9fSk{Z;h$AdK4zIVs6>em-)bW{HV?@u zvnlqj@`86`ziEf#er!i{F7c#qieN!|!Xc+Y2V=kGVIEi3>Q>o`+wUpGb9N;Nw$3T8 z(v?(OP(41@DdjF`%m{;K26gg*cV?-Zv*x6~{o5r!WycDxL28OpTg1bo%}arA`^qt1 zXL(Vl_BJMWxI<477q|`D}z*q zwpga?{8}ad2jyPCwO-$t#0iFslX6mzfb~V)X<2K`}f6 zf(Azn#bl&hcK`H#**089dO=+?d>b(+R#&@-ywI`H>&N#6pX}`|^`F|UY~25!bmD)t zTUof7{=0VTwa#SRKl7;G7mdG&Y@_5Iz_DS~(hR^ZOPcM2cn~aPgv(*$0yDR~9bl{z zx->c$c?($f1*)mC42{f(VhKr0r&98_H*=y!XnhH<^-1ezSASDc z<|@vIm!6h>r)(aa#tbJTi2wFz8?W|b*^Fr(G)^}p zxs%;hAsKiDY5lFd#`Od<6NNHQmH4CHgI39*QV}I_BwtN8v*=A+{6*8etQO!P6X0m- z8~qw*TtwT(Nx6slNkc9ra@}@w<`xXg}nu>1s-0LA*{$HQ=O-1w_3A9 z9fzz^;Ob&+r&#%KCh?`2=B43yiP%DRieJyEwhzpXTjM1!nIZlDn(OIqN>t@#@d_UO z@>HQ7Dj49_lcFhK4l35_Qsi^o@p}*{QBo!z4&Q*cB?E!)A~1wk1svjkU;#B|Sp~pC zM1`#CQu_N%?_d2%7I;tt75Dc+z3W#C9s@0Q+J^|`ZcwT}G(A{$}P7B<$_6`bbfA*?croM`ic zGV#s%KH|WjHIgLb^o~X)EeO#B4z1EEWBQ`pfB@gBBY~p|kE`w(m--fD!yVUKGVMSY zt2#J&N6fmQoclRCELXH4+AXl=piOI!3%OvYl~IAc%JxiQ5?cS9&KF0uZGrGEwa=48D?I+0 zq+zWG|2A;0fdGrkTI+&lsa|KqXcxpVZj!)_^4AKbnWNnC~`MVmyAIE_+lbp5=uW zfog@cYFnab@uPf7dNV(`8A>#1a@O%}Ruj()&l9!0`oNl2M7S1!g`qc@VVMgy`S+94 zqx@+Bc`Z@-4q-h5gC=Imx;6<)jPgD}@Mg}469@J#6y?p>qpy)wZh$|BV(beDqP+~UW=`C~EpDj87xk=ZVLt(@!^Df1hIsSw1 zhK}~yw7h5a7!QB>##_~)5HNoXTrTK325yc&=$6P1bsVxbg@opnppK1WE-%gERl-UK zq{Ylj(khx2_h8Jup|g%ugu>gG?1Qt4-syK>AG%^2XRwO0IA{r$)N!lmx~N{;4eJCM z1(`8;(F*)-9fGtBo1Q@(SkyL}ZGjO3x+$cI77_OLDZ1}w;BC1-b;1+td(X3bZL6HY zLhf!%k7{LL)tBC?ey*Uhw{hp7J?*wf1X^EE%1vg%G2&VyLm3BH72mr>+ZG%wYs2Bx zl+K;eKtP5iSnxH^b5m>yOT_6ouSZ8aVq~`1n5_ljU6sTP8-R!B(Bd~u{b>7yb|gq2 zPquOwOb7|OvKm~_X{3QR7&7rdWVX;f3Mi>5_sx!a>=+7$=5z1gakHLMtj1VV=Tr2e z7Eh}}gM~fG)MruuZBW$4qR;Hpe0$D)DrkH4`g#1C5ZM$7NYs&lj11juUZAfv^gO)teN>5JOph|g}M?f{jyaMJdU^dInNyT(wf$1leIcaJFV`iSWB{457A30^ZLo zUi)K8AD0jF$`W{0l+9Nnm7lt1NdOc>iy{u;=i6Xk2kkXxz9KB0>JB*g2I*@Mgb+Xx zxc*jM49?&7*IKxq`DG?J@2f0Wf6A`a%K6{tzr5SZ%01ZrQ7~5`;)Vx-Zm{>czbNr> zOiWVkmH5{$zEnH6=;c$f*zU2cM+hh#7`1^XpT(jzxDRdiR3kYfPI=#?Tg6~U1A)7| z{nEU-k7L^W*?l9%%ZKGB;i9UNtRduhtmrt*eabXX#XMy8@Wcy1bfKwfpMo9R*QvG( zNX?YAls=m(W~~vv%L&j9Lq68N*jN+!8c=Nfl}F>Sx?{*nygSm#*J!_Tec3_itvi49 zvpCDNY;_=NNoyhq4t>S|f44@iIv)Yrbp83%obw%b>n~(*w9xvM<|DA;8J!4MJhXSS zdz)sSi-Pm-Cz}Maz~znASr=@;KrokDt9&o2Ua?(vha2O8k8btE8HYC{Pu!tern$T- z!pN+R?va~r$Ru14p3MDfX!}luypw!SUo3_v+2lI61jD(!qNPcxk5rYR z1lg0X&Nly|vQTN4KYBNB>@&v7!TcE7N|3oJW7U9~TnMOug1G;_7#D;U6fEmOhamVyPd7~qRdZtu1pRpzMP}tHM zzZr5;P%n3CFC~zr1G#t@9vQg>vJZK+T{9YoGHpB`Q!;jqqN2;ipH2d~P;cB?wLlb^ z*)lrw*V!C4)ju|`-C!#t>dwOfsE?V#A8IG{^!lm~al-j}*JVh!C%*uJz$-A@zLKZ$ zO{ppW&+2ulKf5-YQvHkcyp89ZiGB!ve>j7$1m_WQV!B;01s`EJ%6bN50~T?dL<8R8 zuc(UE9)Ef40r7N`R9N`nfk!*dYBKbe8cl&ln6-$yarahmIvf{orSm#u?IzivnzIM` zZ$zxsyDxu2-~^=Kxe@mG>U-|cx6y#HiYw3*1(%+t$7(YlcxzhGHlKMzWVoPgg0(IB z(DbuDG8hmE7S$M`t74ShtY#>y9rSY^bVo^hzSXeFK72fXPzQ)aT&YqtN|jp~VxITv zIW3%OBL#ZppPY_m@`rf%n_L|UrUhI-MEVx8>_ZO*DbYg?-y{`}U-?V}&a ziU|AZq!BDgXW0*5{1U&+Z=TBke;9kGAW@=i+qSA!*|u%lwr$(CZQC|h*|u%lw(mMW z@7;*AZ^Zt|$jIM0bB;bn_Uug&^pR1;H)NjXn_cy|Y-d;b*i5Px#oX*f_kM#mQ?rje zlXgdINn&G6;lh#6^m#hYYT!|I50=B75x(e-;9*mdLo$~tvM2e}C%GFW0y2`v6^k)v z6;qns%QF*-C4lz%D!Qs(F+(Jymkj7yyjeT+ z);v$6uS80sRfm*f%b6Q?H*ETBjrBAES02vsfJ=3fl7%pG0p{CGVF1W>aJSIlvRKe{ zJeADF60j}!_bRz;I*-W416XM(Tp1)#8OpPq_c&c*Jv2xH*@HMQVqov%>iT zY6&EyJX7QmVyPJIgLD=8XhP zT{j{#?m_dS1$LCW)7l9G&Lj2GZFRJgv4!?~HjOD3`*M2b<;~{pI}7u&*0>`P8{)qZx(hJiKjPI0IMMm#rebd=Ew-?E+=uPbcq3`=-x2^3 z&3%Rr^_x!da#`uOWP2ANPk)WCD+;r*Ub&UD1S?U{m(>UoY3kX?pJua9!_*0~yb* z?{?T9HVXLZ1HC`pUtbT4CoSCukopX&jJ5c7Sh3kuTP*|A7FaEqz%*+3-{i>JQBM^E zpe9>GaAsv@RuY%#puL)t3(}Z=>_0w*8iyNCI;B@tGV1q01&nH2s$zk@(T!%&XpHkyaVaJOuDZ@#`x_8vdkQ@o(ZU^Ov6OHscThRc+O~Q@jU&?4O zN?R(4ouWi3;gj_Oc@xZjo7sVqL&krqn9bU1$J)V?7Lw)xowvjy6lXFL(h>L>n?NFR zh{&W@MH3rXzMLq-HyP9v17d&p$jPvb(f~<@JBb&=nL#&hU*M@R%Njnl>(IpeP);AE z12xv&d%=!_AE?WmVhh+2Wx&}^0=cryndpK!DZj}ld7*BZRQMism0&vFeM=hx&;P>2 zk~%e`6BiQ z?pU?!X5N~y+hC}xGYgVMLHr<0;#hH4v?k6hZ=}MlJCK|&LUT-Y)v3b4eU~hEpw9z1 zg?lwCO=0d1e7CJ=6+xOq&LA(vLzY#*$XM7=3oVLEevZcK#KU<^-6g2z&)u&Hz~~kFJL^7pJA-UMN~Fh}?uhJF0&9tR zzp`^pfQ5kGn8Ve8j6Xt|Y}B!&K3|LXCRx25f6XLZ zo;RpsPA^dX+Aw7r0h#*%?NDt&o<%fHT;s$Ej)DtAjFC;`C&f%nDOnvj8lu8lRck8aG*S}}RFqDu)W5UG92niB6=Tf({0=}_8*k1dG~ZtU7sNWV zS9Y&W>zBVebL;)B7%1pO?ME=?m6mV|1J1|dt?d>Q%m}4Fv+S5H5^noMj5%ExVuX0P zonj75_R5M4FxhrO9zW-2I|!(hjcD4u;%32aZY0%9U^?7Q19ti~h!d9oXFS(T*dAI$ zGZ~F~r*fHzs&+(-5RZY zT@LBkz^!pIIFcG=hh`Sa$cALcrzIme3SKStTgxdM6hL)xDDR=nqGbpBz_zRDIhHW1d*zDCp5> zw`SMGl#gM0xh_qlB+ik8s`^~Hfd#43u4pB4wF=3VL24Q{?dEf#S?2TFTuS``{hbbn zZ|nE`;{0H)e*nB_jgrxftivR#mOphFp)cOlpwnC+Nfy$lcxMwNi_e0#nYI%seI6&p zogviGIOxu}6hc3`ue^b@Aj;n>vz-$G2RO#f+tRsVkU9gexqkF71Z>m;@-hRxhg;#7fX|YgpqfDumz!mFYp#FK zGue>BWv)ppbiilk2u)z=?}t-z)Vm|arPMUj@<2!C2v?w-o|vK@D^H)9$_O$ zsY=_Mc7>n#c-*@#UNBn36Qp;ljZpdyxKUUhs( zEsH|86q=eg)Lw=q9X6T3wp9xss;ihi_?^|*Nefx0M2Y~dX}%QRUfc^FDx>7ZJw|FU z%}{QW@e@2lqQmj@LhTljC=8fa&`{tN+7jmD;KMKCp}+2Dk6!@-KP(~(nXFeW_m)Qb*QnTleAHD|YwB}h(b zG3($;>~!Ug{)AKR;mT+$2MJ5%$CQX#UmR`7e7usmRVy#&r$0t1$9ibkSFET&aRyc7 zcs563P>ow3sgTN%l(N8(7qqx2Gnr@g@NwUnoiY`iCjEM+@@(>O*JHa{Cw1U8Sm%Bv3}T$Q^i0y#J*XDd#|rIwRL zALiXlIhTMDO=aM|(3NRsJEv_iO>9hVHaN6}4A%yrKV}5pm&~*vKM@DfR&v@(jV4Z7 z!>FdGTk>WESV=ip3mTb|)e7e9QRs0`z=l1f6S@v9TZ`dV3sn=`^@4K2F5y0}CC=wm zAq>StLTs*g&?*tdhMs%ir0!z#z7TERPXx%{5LadA28=JA$@d}??b&=4O#ZnA_rY`8 ztcjSMYwU^XzsR6T*c zgh$CVwl&n`lch2{Iv)_B(OXBnCj)E8j`J8v&xrLWZ{ck~0eb2!FQI$A6^;*@33sHM zPn=cIERc(7MpIomMV^FJmEGt>g7kIBJnp^iK3(sQU>YSi?G-kU6r}FjzZ4XExS-@n4^_5(Xh-}8X z>$IfGSE6I#&GA=K?i1I}@Yc0=HN**mcBwo{tQ!`gam6a$wKbB(F zSk(?;UEm+3m6q=51rX)$dd?Du#j~=nLn+yF$0izqE}m)uKiR*_cl+WTC606%sI^E< zr;Th*Y=-OKLkHcOmc@3!qn}{SE1W(nwD`#K-4 z?svAp-W-Xs*YDC`eIMd&5|T~)?ol0!czIH1+>71*$9TiBSvlci73ls30JVA@(-gL8 zb^Q8w8_tW!+&ngKHNO$Be!ee4cK=E1v;J>0!T%Tx{ww?Qzrg9(e{_!SQ>v#w1`-iV zK*)fJO%!ulQCt7wQ)jYI=H7pWD5P8s*K>_cw{W{G2=H3PFs6$H9!;Fs?Rc}Xvj7yx z)t!9li;>FR1aY1Wfe_rqPQHwNy@i`}>wCeL# z>C9ZVEk-H)MmuiRM{tf=I%$eV<4MlAuif}&_1M${2#NFb9*e#|ym!9VoBnc$+(}H; zmC5Ali|rM%AU|77KiWP1eP5BpaW1e09B1?K@@1YLd%b8wUv@a_9vgEAzK~(vA+z_W zWRG1YR}kW04&7E|O_%~)3lVTs9Pf5^X)d?Y(4k_Di)o@T%^0472ro-~MR7|_FL@_S zk^7J~sl~cwF~k@Y^0-|I?YL2n2QVA_&@#I;g>qlii-N50n z$cS=#lfMs6Ot0aoZ9Z0a*o|E@6jh&=sG+^(whs?-i{o&WVcmL}afDWYQqiOtYs_6R z7m~g{KnWDx`STu8FZ@U!ctgh5zi%bk>3K|?lxXg8^JDDocUM_d?JtiBFj2zDna^0! z%#|`T%1HmlU$Y{e%n`Sp#oV2pHH7ag({KS&^e4{MUb}pTvq#4LfJ#%^Wifgu<(|*H-XW?^Bli;r-nL1TwB0Ix1F6Fcp z=Uxwb@TkhUilHkJ+)Y*S?!AE6*DFa7yFG<$@iPU96+`4fp#E`)?O$jHe>AoP`v7&P zLMPwTP;SHB43e=v!J3s4=6-NMpUw>xLyw5P&l_v2JI{$TZeka`H5X7+-`*$Oz~KIH zV(^{1_2t4pkQFIi%5y&NZ0svHmUZB|fALpZ!l`Rl#H&}LSW8ufc(Yx_>Xe!pdU9Sr z&m4op_x+j=ahdjd_UfL4j`f}nNRj;9t^vVw-6Phil zY%5ZuMNi5Ns!_iAxmc<`W#^|dP>D>%?lwgpA%4gus_|ph0^`YG_Gn!6M-4qCd5-kTFNE&&-L&8eIJa=Xh)f_x?V}gIt+I0pcgYWKT{k^zWJbFN(too9kD4pisnm3b2j$ zRxu-Y7+&?X?ya&o+$C-@S?RpqRXSc}a=~t@#c`72ZiDntF5z^rwK6iK#*5JGb_KD% zmb?{X>Dp?kDqUOVb%N`&UuC1NnrCLX(jVRM!fT@Ys_*f&woxcPDmOtsHpF%zuNIel z^&QgMjRb2&j#gy}=T6=jr%|?2xObWPHN8FU8qraDn)XIMZSI3Cma1(<+BNN9n1v3p z{Xwva30jF*!_-SJCI4*U1Aln`gUX&^u${;XPFH_olfrerGsbsxDPVJKRUh4HMP9iz z587A@SHDL-hM9sMmDo8^(%fNbV~x9!Ad8#VUPY?ZpnAu;QHVTii4+1Po!$g$U_8dk zA>Jq(BgsxF%JU3$J>)6eiO2L@V3|=<^sO0cEmmJ&0&62YRaJQ999tYNg?q_N-TXS| z^pwFl@oBFaw3ho~Zoe=X>3uS-3+J|^_WIWr%b_;D{lx|4(l|wXt-zJ}KtcW=Jia84*SGuKi7<&*ZoZaHQ6C@chv}YPhS1OoXItS<@Hri!$K&X!9G~|W z2(Zjsmf4sDlnMUZxz$f3p}czVxzvv>#JqV7QaJv+r6shWgxq9Wgv;Kcb5RPC{|H-= zo;x%6b+h8MF|fdP62v6Xw0uGU$4rq&H{G>AhOd#%)Nl z={M`Pcc$%*iWg`xUx$_$y4`R#J~MmpO0kK!20={;+&Xr@LZ(f0OXN)Pfaj#DqAvSD z%vF4srb$VofDy`d^bt%1YSlq&{Fg$ZQrb|93lx|7;P(psYKJ}Hl1v6i zb$mR*Ho5i#URG_kBS>*p9sBJ88<>%E1qfpv?ak4ZdZ&^;To4*pX(?m3(p&!B-xWb~ z*A-3h>HT=Yv)2l;$>pCGidPbh@)ZgawbuM{=H-eGDQPU})KoqsOMDnHFQ7^0V5K^NockU-Mq8!HC3s;Xm1Ceb_K^1xGxqUbUOJFpd(s7(TyUI42X}=OZDQ zCR%WIky2+%?;vTWqmC>NGVqMl&_%8{rFV?o$RYJlo(4IIQIgvwTNND3R}x07I8-WF z@{ptcl0+o=$f^E{pRbQ88_6#B*bR1au!YGGT&wLwnYc$6bIzWwS0&X5`drgoJZ#iO zos>MJp^*6Hf^N7RGo2lZ8Rc((quyV*y^AcLPXleBkCe^d1b{Rm={tDvW4uFbXMgaIidpzJdJ9p zIV=Y(%u%szT4GGwCwj?k*&ceTb<}uf`Bq zU-V>=ctb*Vt~IhY{D6qye1K7}&umW`#Tx^mMx06*lkR#zoMbwmuxHmz)OTladX&Lh zf)?JhX_-?3nU$)zT0TA72EJ3`0PyrmG9Q8=5nL-vyAYhaRavZK$=3_kpVP)-u8vC9 zI1k~pQSw$$#Os--4scpi>b>FxNX&Yx6*&zW~sFt(*vZ;Dj= zFz)YYBsZd(RH?Z@j>N$nLG~06TC!M^Wvq8m9;1Jw-m;ERR3w`%2E|d6p z0cf1bOT#C13OP?xawTox$p1q0S8Y$}ZZJRf`26|2CJo|( z>wTKav#Z4Lm-=$C;Gx|xpxvA0efXS zNbtx|lF6PcbH8llOmlov+j-9zS7STuMGtX#Peyxjig( zv*gS6mMQF_nO_%b`DkIw?~t}V2~Ps=y}c4xv}}$X59cD{ zCF7u1#c1Yv$;f$!s4g;bFIspW{9?CXCpJH2^jH7NZM8@h0d0cD;5LBv_z8uLUT}$Z zU@LUzgUt14(;OUXgV`f17imHaJ!6e!E6+fcbP_=`zbktCIVe6yx9-SJNGu~A9zw-N zvn;1OD3Gs?XJ3$6w5z^{swuT@V4^4*fO8w+V@>H~xvhlVk52jlHag{j{3lt%{=Y#D zjBE`5T{87G)?_SJ`#rDTe7i{i^t9ML2>3wk5yqc(4~A9|*Z>4BFs`*x13x~IhPSKK z4lzqQ$MAjCxN^h#N_9F_m&fzTp)xqQvehs*I!MyVY*ba*x;(M~KKn0ZY_OQzYWOK~ zhHl?1UtW7!7+tb1f2WeWhPT$iPF`NheR#n=Iv}wSc3w?*u)sxkiQwT*?*b0)Spoki zt3KC}$wi)OP%$gmrUj0EilLh1M#k!}^r82+xYb@hd&A4^DAy#T4XvV7cScn7gGp`* zZ4n{}|8#&~P;HQSDEEF9{5do+2jMJWl$(R^djx3gOogm{mW4`|X$0T^Zi|eOd%jqa z%+({iCR5PLuRk`t_I7Z=bk)^G+~EuCl2t9qz&!_T(~pPY6i!6V$87Ky!cRd|^rzf` zZsJvB8uNArJYA3EToMibNYmtNljd>)rMh?`!3$y-_Qn}uIuly~(@adfG?Q$(dqB{{ z5fS-90SyEFO8%@kAsMmc^#GsAz7X*2BmyQG$P^dVOf7>1n>j%4hp-^q>E}S?rrF~i z@%fD~DLDDt5zeAj(ae>^G6@u3mdwdzRg$Edw}c>yOjevW(8&A;>`o&|*qQTCD3?m9q*HsbzA^uVwJ?1& zb{kJNs36(xi9p6yO%)H#QrHG68_4)6+n0Arr*3^H3E_%qHx@C=-G@FXMHbDoTDKhL zR^=1L(-c=Td?c7B48JCb;ht^T*!gpr7V9keSIxUF=K71?TAr+Vv=~H!Agj^3i(j)i z)w+u}_aXy-=$CxAEyybNEyZZS5xsyg2?t9`w%+Sx7W)IJPUx>g4K9DClMJC$unC$+oewAgQt6F~JrL(3EWwHxI4BZUd z-+a6rtYcd0y9XycemdV2dIL<>hpZtnuN=@mYW0)J!{d!Lmzd@_WGC}6&yB9ZdXJD5 zm??N_>v!&K1bteREn-2}R;na?d`*7uS@IT*&E>l}z$UWimOIA~6>13JSNjP+awQVC z9X`tN$FON=eZ*X)W;#;`J#&2E?Dg?U<^yLkL^kyB;da8HGWGtmF4cCVx(Ty*+6PvL9y56JxG&_n|D&ok0 z@lLx!+=0*SZD%aQIepiW#ey?!i zF!aNb+m8B_54{&S$KH~;lZxg}+RjA669q2)5Y(FX?^Y@x0DYLQZ?S@&9H8P3y>ui2 zp|WLeL^KYy*x@>Cv!U4JIm1p-y(Yu)cKChbh~f%^qp+EF{G{1n%tmH~pI7-X2!`iy zOKyTiKIO*Ejy!u;C(mosXxnJ+3;ODd^WNDFPtND#=Lr7uhekh>8i%H z0L5T3Qo+mJWw1Y9DR>OHytn6vQRJYsI1KJQ20=B1Im!=|Fkjc_@#HBU-#5~qm#2Rd z=?OA@MJVJSwvWhyb&!VM1-Cu`1BVWM+$3^iC<%aA01rcqH)bAy6E;DM)o5RsB6m)E zd=n;)R2gf4DJW*4j8Omj*ac6$&3-`@4MK*5aqwLr)J&|NgD-9>Zy2>to}hzjKRLL( zvamQ}6`SH16op)Pub|)5V#+&p!+Y%waaK5qLHa}F_>u#fi=mMD)LlqSOo!h2c7tY7T;1$jpzJ{7?Px&V!^BDl2|J37;&CL`3W8#MbCE zQ2!GQrH+J7d(ZG!J@6-6*NANswqO zjY&E7bXH3w)=9_}C3z~Nv5z-&1=}&s_aaJ#nr@yC1y)XOuEr&fKpCw(GStpn*U&~I za{>N%*3Q-sBndGtQ!$R3XOSR8pZ?@=c*(iZ_4>6a5xQC;R@L3=CCet~etrfBTM|0Y zEKzsY9k-k_>L~yLXpNN9N>eO-(#kwGxu4CI0AkZj(^x%JrR6;ppH*TWrbO~!hG#U$ z=9#6~#zri~H){uGxwl#be4W%bR|J_hL1(^lPV;rPOW{l9U{A#)89Od|QrSg^H|J9O zao)ml5@x`0ZrL5e;k8Z=;G$%jo&Qe337@`p#e1Ch?dEaP#Nqm0DsA2n@y^x8F&2I8 zxQY6&U&mx?O!L-pXHxTbhd0ssW{3A+^>(K>k;=b2B9*jGZ^b>IRoY#D2bo4M^Y%OM zzYP*HcIS8Z_HVh1O)Ce3Ma}nz)l@XRQ&C3UKE0@UcbvS@7{tl|JFKn%^pi@-W-GH89|MR4zo2|B2N^_1Q zf@cBf7M->`frY#G07G?qas$^wV9l5V=|S@nj!p4B!}2N(OV%ca*sQup&Kfz-E^khc0N@^M9_&m3(*FN(E!}i;dxxMv>;?B6& zO!j?}d;9TOH#M0lHV5^O9O>{VsOht8x^p>(le48o!M>4((8((mXnlH$Vb;lRlE{I6|e^9y{^#5sq$M)a-o;Qs-`Hvucm0M?Tr;|S)nOF`64;^1T z4%F?Epf#^FzrBdt@#{x!BGDqkXC~@_jcsNfd60!Hv+i?i{Ca${e|+-T$eM$M+h1{W ztOfQYxS$vRG-r4U5WGCs{dM-!k)){6fqTaIFS9K*_oZ=99*Pq(k)G|vIAdWsE?=DNjx^jMiP;~ z_q*P1h_9i=`r&v+h}Q#i4g0gRw>Vx8&y(UUu}7M*8UiFCfE(fq_>N}+ zCvm5@ahhj)9HQ#$csYN|IhYe|Va5R^>Jq6Vp@j(NjkG;+kBRc+T2%*Jmj1PkfVjn~ z6!0UV8P+z1umlRY6{67_QkqwJoyP47o%gNd_TQgftd5j;atS3v+RXdl>^}p*h!I&C zh@OaDIN=ZL^$ku5NV?XNET(Tho5_~u-_AchBk@ktEg_CJT8iBhV_n~gLB77CyC4S1 ziLMkq8V#^R1U)hHQM6tiF_e=hZ0Kgr8|5crkb)y--wuc2p$XB2{06L7=B(sl&E5CV zy;A@-NIN@yxlFv+d#uydXrsFNqyB_FtQ}pX1+N#`Jl`KBL%r{! z6X5ye3U^?ZK!h4cHi>$7Qc427;&GWW)j*;e}%jmzbrru^sS9HzTYN?UL@A7JF zAzW3#jh+lj(IEQ=lEC{V78Gfihq>BoKQcfoLpDm=<$1MLK|J7`95}`@9>~r*lbN-V zxdP9pb2UYYr^Z>@#pfaq7J3Ca`&I5KI8mehl`{m9sSte`?)-L&Cj1cqzM{*A9VSXc z_n=yut}za?4OVCF2YnWVp0bp&rk(+oDNh6A95S07G-AvxmJ*R9x>fjHtwh9DXz}@@ zd_2R;NfpRavVd|ak$D#;;v;YpV&zVN>=E9>D4uK#>nYv`uGGXyr*=7vQDG>__g`O4 zBBF5*EX3-7a0>hUP5kErxQ`%Xq9~NkP-YBwiFjT(MW%wQoV!M za`(cFs}l3{pgCf}XXfV{E5*nGM#WhT&Q^DMO9nNoK~hu61+-SBeBYI|ZhaG))Ce%_ zEU?Vg2^gYbGG(9-WuyEB=<+z@m~$_7rdZBb&>yJtj^J*>zS#{(y#bKt_F#$DOnNKl|B0SympmyzhG#1x!s}IswVF5UB zn9i)WB4yh|XN{XrQ~`rY3Ld{VbEiIQ&4UEl+y%7ojAf)qnwC}@Rto20BvqLRZrf2P z6vHwsnyQ@pBi8WQ<0yqt)aG18RgA>S(lNC@VQ{)f)(GvE(O(}>56^yL_!6;;T9o&o zKc4v#xli|u7rV9*^GGxIS?Y-7fq?1@VI45#q|CM;0+)Z-OgCV8L zy&OZ&YHjxbNF{ZxmrC@J99@*% zUrW639RJ1Uh!jYC%0$?P!fG_|)#GdLM6Y8CX7`zumNB&y}47)ok3Q;eF+m?WWC zr3sBtmkq~t^EAspKsh>mWi>6}&81vzYLv>&PsA&8jDMHVwSZGG4|Vk`3RbbGqdXP+ zAv#(0YM6Gjz8= z-qSPR)=XvPVX#};h^I(q4L^gM2320?;yMc(lyj?UuY{g9 zERF{3UT#{KJk4~I?#Wz@l{q}Gr6Y7Jlcgicm5rE8`-ZrG7b^=M%Yljx?q*DjGYR&j z*#`ps8B6 zGSELe(1({Y?oI?Wl*clnUG4C@mLp!n&}A^!_4B*-GhCsG_Ub=rsHCH&-G5RBd`}o+ z!nzeK33#wg-Wx1#7wL2SMw-}$G=?xf(_+1p0xHKtG>~>B_qR5sz5d8MF4D;9U>_bY z?m#cjG_eKQ%3CrOmR86LWMN(aR-iD|6uMd*$sAmq@-m<>XN$m+PG1TuV;v!Y_to%gX*KfKHmvMyA4;wqrfh<(5%;n~UxFKt zkLTwyFpafD!nHTEu6sK?J-i>!J!v2y34G|@?{|1VfTG}g&pFHxL9Vaw&%5J&vshPJ zA-O=r1%fGDPNPZKH#DEg-iR8Ncg=nF3XyT6yk0kzmBXPaI=xa%{d8X-I z;FuhwCWWF0-3d!=l<}$Er&W+Ct59#{+N zfHQG~HKndS0!>fC8nFq`J}Sj3CDwk3Knp+R4ax_J-Q&A z;rv{VoDMoqpuwz}LUj_z#34Y8G>%Zp27$&iVuE?Rh$YiW?ZPRJgGloZFhP=b@$RrqP#P;Nhsx*@2D|yQ5*CG}_G3Lf+ZQR7~dkYv{qvY~)%k8CLj16w>B{2cK_DYUEX&rZjb@z|o(0Zmx|`o8p&K zz0!!|ZvD>uIXyW^UdbgU32Xh)bU9PEWi1PdxuMO^iUVoiHMd)a+emO8BKU{yzw44? zGjdYN?Iw36MMusQhnK{Oy=;hs&Hmb851mGxPR0`A{lOsK*b5R#N zECk{PpVQoE)@4i}gKj%vuZ2C8i%WPc95!k9@MMP98U~mUzBg_eEfaazd#s}{&WqBI zT$+!alR!fn`9P}${Y1EN+{xlXNXt4uf&*Gk_DFLTN2#4V>yB-aNMlp6i7Lwzef?#P6ctQK1V>VjeINKQexFf++AEUjxx$}1{|rT z_};J>b}U|fo!sj)B8h0DY)VW^N`ZpW}5SA?K`?owgPhe zH@eo7T8Hbj5GnS?d#Z$70aOx)F19_kn92j$mBEN1*>v_}7Kafvc3wBHVrU5iwaLcC zL9%oppKB`RpWJ9iJnc+3?07;JesN5QQI)x3(WI|B9ZhztsRiDy^3XY6Fx*Ol+U%7Y z%WSu?`PfOb^&}})0Ml5+1<`qJSSezSkUQ{FC!36VOPTp8qa8?!55kekHV4@vr zWO58;cU1KiSa$WWCfDV(@zQjS`lq9{&fXwFX5b3bst?RdTbXT((PU{YI;uA{A?j7o zN=Jzq_p2}2c~}|2>AruRy}ifAdsp7nl~7LzoKajD52yMfN$?0>VjUi`3xW=hOeKCD z8eCO_&qJzUG5%+Rl?~G0JUOF3^_pjUN5^r>o;Y49rkyxEJXYuD#-uLxyMMZ;HHL+a zbXqTCMZ2;XUNpNg-=i9h&eINdF>RR4;fQwrQ#Iykx4W&nvqjsVNqUg^P0s==(Mtp3 zPIOj0iMtp0(Kk4)gd&-L>0^A?>l_JLVc1o;*6qB-=GH(|a&WfOXC5I!>qj+K47a!@ z(Z%$i^Ck(xq?CX`Uy>7)dPk$H?jE6u4#XV4QZH>#UqLEQY-t2cMJ7L$)(HRLHBpO0CK4 zucBUDV%+%#hnYTmd=K|(7cw)4*Du|D|?#|^<~XG`%{lR=GO z-BkkUeaEYdombgS)=q$;Blw$YoVJ1n3n=4Su=5{85<3Iq|8Lv+eFWC)a71T;XeB4oN6U35)wNMF_F|D~;lTJm>L8x~5BBGmp0B0|Q%E3%^ zo4-ee&V)K0MrSYzg<2YY-!RI!x+H4RTfsVB9thu%+LU{8MxB2^wzuQ(A4gO@A|a4U z-Z;rL5XqxJi-9*Oq~OTyiapC0s#^Q|PVJ$RKo3eA8f_&Tw>|opb+vL|Qx^kX2?)`@zy;foIwlVA>YCaJ;w4D3 zG6N2cZ{;Jh!dbyqB^{K1tIVH*{6U6k!soXl+WTcX5RHQM;m6YGXq&m}R}(i`tXtq) zPaW0R-&wL{6H0RiCMBO``i3QKI1R{#+ay*jtb4-3EN#Qol*-tl(u$SThf5YJxPWBg z1-WuE3EtN+l$Eu&0)iFTNJQ`VhB^9=P)?5&FZK#}E!(S>q7CotZOx#eRt{jb>+P)j zR{bYeH@Fd?G^T=W)UT=A^A2uj7)2rWjf1ryz>IDH(oJ$$;OK)3BlMVtFs?AaWwn)7 zX9}H9I)j4o7)UqY??-=*0S}bn=j}drf8Xh}SLOHrCQ}!0<@jdE!sYP{4%PZGWX;UH z&c?=);k z@k`HcRXH&DUHwt{J;0~=hlAkA#j~I4uN2dUJ~(GlkpHD&Af^oaeuRzNz4goJ&UvQm z#Iw&1A@W6Bpa7C^JmKTgc*aWj5<@e#HSZu=kSz8UQ8$S^ymgD~JQ^Zb!JaF1pZ%l7(--k@E4dn9TBX|YmS^A zJCyOTl{|8YkZ1)5u{2%#$};Vx+c zoU&=?3_24C7TuLUnmsO*#~)L!NEj%y%JMOstF^x{j%t?3YAf|N%I^lm7)YWHp^ zg8c*Ca~)uo4K)R%mp<}JXOJuw{4$vGNuWzd2H{}@J=mB4DPa627=Y9m^*7?m(3U$=n+8{rZ^- zh6zFVfXIN<94yJvOW~DG_Teo7C#68C{Scm|h#)Q)F@UMY1;WaEnnF((Fz`3bij|>- zmmK?Vi}M%<#Kag@Hp(B-ELt{@yLX(r{6vnrtpJo-^%vckqFWIU;KQJRupD|60`fp0 zm#jFrWHf*Bkr^mBLIXE)4PkUOpaKMJ^{Gefl}(j(suKw%`7rz85q!g#13T!*AK(Lc z+Qi&p#9an0_V9oL?9n*}Jj17Dcjr-D5J zn?H$^i?gC8ItdHUFbN~KfDo)ARuSrpsf3RT2$6RHEZ91$@%g)3uV^CA)&r3ll(eD* ztGBkT_;RQCd^~ouT|J#SzaQt%hb4Yn>B`8=#+rXM?wi1tO!Xaf;RD$!*p~Z;lx%el z`4w0J=@g{^FECsozLHWXmwhBAV2JHa21vTCB)1F;)#}N^bEl~A2G%D$%Zlc%d7dU< zk4r_D%~{*FE-QI%I_zXFKU+S9OKa_y8Jo-{ec0Ef%ioF$S0ek|{Y-$fpVK5_-|MSC zy`N{g()J@HrvnGZ(v}OV z%3F{xsyNQcDmq zdIO-fQsjXhS%py=GLS*-a0|SR-mCySF_QI@Wg%)?WFUmp%@E*Uh{+r2U82*F_he)N zqk$AbAj#}sYKO4*=H!Y64yS3%zf-gT16aReJR353BOsND+cx1i^JV$(lUpzD*db6+ zf?8R-+J}EiQ8jiXFw~(UJv=L^>+vnP@)IZ@{*XGz7vjrz zo32|%j(TYH7=sw^ERF^ULtf#@z1w+I{xPsaeOIHAq7jBTE7xiUKs33dN+6guICFijE(WA32I3GM+OGkFU|he5!-kvaX86d$=Y$1J|W=dM& zulUjPggpd2_z)9KJ>&IHudT$p6=B0~BoC4Y6#y%M9YEySUkr)|C5Tg6s(RFx>%CrX z0RHukF9IHyLpg%HJ2Bm!2>c#C z-*4ZQcL77ak_R$iYIVu>qB?v(T|W=hC9dw>2PP%VpmcG+U|+#$WJN$N@^8ZXIwiWf zT`IHfIC~}aG`<(FTVkoaYx?ez3%2gVUlK*@Xt%kK;;jWa0_!8dbr#&#ReQ&)ad~u% zRU{(LPjo(ac6NAazdCJ+s#FL;?LRN4A-L*A!4Mz+hq1SesU&K;g>iRxcNyGmaCdhG zcLsMD-0cA8;I4za!{F}jZiD;aAJ3PYo147PkM~cfx;xpucXoAmRi)Nizscc}7-Yxv%@p>ATSLH?g-OOSt@RcN9lYiR)vma|-7S-9 zdmO(igXH+9=5|u*@67|lKtH(K#Oqu7ya%broe-nU&P+mYlUiUTqP#ndD z&*3Q6#$dFzgsOpBI@XK2jEZz8h4oVRy10azO9Y|I%@Jcm2yxd(3_aN}@y&WWIW?R? z5#;6M2&i@L-Ueu14|=3mp-p6D+R&Qd7(%dWuG18 z{OoJAO9j{iJddGLjGqHW)@R~^F>HaBCnZ)PF8vDS$Wcm{LQmRkQAKGZRp)SV04TzLnnidUtD6RH|+ z`77*E62ZWDbNr0bCj#=NG#N>xwt!>&Bz&&;OH4OakIZJX_@(lE#+E@n;?P7@dSM_9 zw8B8u$w}C5{N&*dv}7Zk3zvIkR!W$+N@GhWe00DN_q%cTQp!B7lwXqi6)^^NrW#4E zSFT0odq7LO2w4{tCnmeekKV`K8kfEy)a)vjAGl}MVK{B;hnC+w6mJC`BXrOQTVYy` zVo*dpMf-SAP&`0l(3s*iAUVGDan>5TG$YMWTXE`bjD( zxdGLoF+kv1Od*WEQe5zmp7mulI~7nY*+oR#v*MAg_C!Tjs*B+-Cq<_XK=B1r_QtCa zUTr&@+myDMGm|R)WQ*DdXU+m;&1);%F6A4_rBBtK5w(r^%Wg^JYo5s7%106JDbn1KZ5}%Zu*hWqo72W)AEhWO?FwzkZh$tAGS- zW1SzL(#nK&;X3adB9mLQe>3V$ajxjtmL_xT&f!FdVp!p+&VgMNkKH8FZZK^8aK!G2 zj*QPx>{cLJ7*Afh7A#LvDLDPs1>ck?HMWf*=CU^ZGRMI@wo)jZ&_$>GK+?=6+C^CSE~&aYh40@0QBXAnbFL&vJ!Ut*TRnZf=(e!xSAGQ`-VXU>#ThR7idx z|2Q07Nd!vc@8t$*4|VL55ad)l5dAbeTdy6EG<~kY`;AA74>RO3d?dhN%L+5C;p1Yw zkMkE6)kmK2chV9jrGtEYbpjD}GOr`lw$mjEn!xXRKvrM)>`~&y#{-*KBh-lPfS9S) zDkO$Dt0mN7Ga=lVGAzT$HU{7#^uW(E-n=93V1u8sP3F8A2gfkB?B;FE(+lOBiPWVOHzgA7QaKILk&DOz=b`@(UnH^84mRED6pAj`gXUpw~?vKVQ zgoMie=~`p21s8U_=wuI6*w!lOzuPxI|4_HTqC%%EH!N=G3`LM4=$xVO8GX6K@c6@& ziUKGH?~v|%TLz%c6)BiXy)3-5JLl1enCxYOD;$7(o8hp&OO=xFR}j548~0>}pU#+J zAZ?(k!B}bN=H^OcYr^O@L{K{pfC%{4dEp2V*_4BlhN@FrWUzoF@D7Y z=S||=1+m%0b3ER6g}KPdnfcGvA_Neq5l&FL@+dLM%AZyiB(G+vJ?so(_RaRf)-l@O z;0Xu-@8`e3QnW?tjf?WVLXwxqau8FF=t1*3xB?Yc=&mF?XUB&(PsOU}xP?>S3Q%*8 zBLhY>r^kl`SWKEUPI)(K#?&Mi{-g(5r&=U~@GMu|1RWSPH|Q!fg!fcO9yuStPE><% z6hu^{`Ly%u5?yAC1F5N#kV12)Ar(v`T4WXWde^Czd^&tiPbSsAefJSuqjUPbexK(i zDxqC(I{b?1p>8pA9=E#Qw$e{VCLWen#ZSIJ)1_(WS;84H7qz6lPoe>jLBNn~HJk{# zk3}D0{7V3+)hAu(g$ueJ^ z4d{u8*#!k)sIA(@EV-DB4_{?+YE5UBGZZuDkW$8+lv?y{;yb^`od7`i(uQyw^>OMH za?{eEp~(&?;;WTB0QR;Co7L8Y($O$!#ijZ9-#BgMBKsQpeuFMcuu!=blFOB4C`wKE z4H%m)8bYESDPEy^+#j@kz)8YK=MMW#+*U;#qNH)Ae^E0QcaIJ$h7AYkUK~p^%ut1d z7|7s4cju|=QK1S$XKFL5!ZaO|7Nr~_vC|?lJx=#;^0yYHT$HJ##!~3ml|YM{?kcm~ z|HK@SXx2<#|1BE(DmngN+1mfZy~@e@zr=bMtM@APe__3!7;hmFJxpoSIW93kNTaCP7&;zEZuaDs+JaA<#;msjc z>yE2M(>C+$7q$ja9j1KHb~`M!DuMlR?%3zDPR368toj_e?abb9K=^a%yC_@Y5+FrM_ocp37f?+oBJ zL1jT!R6%7T6bSi0+9f(=IxFamD!Xm)$8)?@9-&n!6UQ);jvovP8D7PE2vpLm;$MastB&BBF6%KnF&g@lEflevYkFoLU_ zi^UHI1g|yC1Vx0t??_TlLXzK1GJ0e!zaubI?f7`?X=!f-+Rfmc?;VCf8DRwDq8Y&I z-EBlT(_`z@d4-AxLL7(I%OP^InDmb5<@f9cP^o1Pa7;$Z$(r()NqQUr=DCGl98&q^ zxMH#w7^R$9oi%P184hVVm5&Y@$EeHUtysGMUfesYhWydvJqQeOnKWi6tUqb~rC*Ob z;r|be@`8uvzpa(?zcgC1^05A|l8ePJ9fS>Ttj%LaOB+hKabNFe7b3{VBKjGNUCE&4 z7|U4-M9s{<%8`5f&wn<@jO;@`lVf}~{LvJ;A&FW}>; z#0ypS(~B@+dMwJk>)CDTC^GkFz*IfSvAX4giI3^~gox$lITfUIQ!j0&6Qi%zp0!Oy zfW1nT3l>P@F;W`AX)P^8DeQ2bBa70<%gkR6=8o6JN4 zH<3X~q+EbEK!KEo@1^|O#bNLteVhF&kwChd&-F2TKNZyB;KT<9u32>2YNoJcCNlXeKtuEw~g0{5__66*% zY~Or_WrzaL>d<&J{*?IXtaRItSniBB^O+k#`4;NKywme^Mnwxv%4>qEtV7q?+9_RI zpFm>?|M+E}`!03i(8-han1Cn&ho5!mSFR||eyoq(BlEq}A(~j1h(hJ^S5dawExKcE zMM=YNSq&*F2kQ$W!^w8p?tU((c4pltY>ZOgnp#*sI6&E{*rav7r{t%$jwB&TY+`}( zm%!_>f*W}KLC%EVqH`*#=>$ri3_h6liVm8bM^vF}&73ORZ~mFG8w|1waz7g>b`|z6 z_@gv~?4omN$W;snzn5IDo-FqA>lDwr4&i&>Elc#-#qa!yrqYUUeSY_t_6fg&a>R}w z`$;65L#y5=4BroAOLDsJHk~!ORH<4yFuPioiKVgF?*lG(s38SGB`^RII-2psbYfwn zRCC&zE&PFciM*JgRiNc$>r2rXY2fm4J0z4wcQ`9EgF$nSvuXTdlJAhmFUfo(1{9uz zSMd0s2(g8<><^mrH3@t^k(PhmPlV4ct&FiNgjUs*AffWIc6FS;_(+jB zo^1x+K3-m4UL0@IOQ8!n%~Yd3)ay5#t2T(G3OELY5fX+>^wOy4s$y)4sjLuyAd;E* zsn%}4-?)lLs$!wj7dn?C#~`5U`XZK??r_0V4u4XN11}OB z0x227LODMln^8^?Y@H=|Q{5(tO6^y?k*abwb(0`>TX3GLg-xc3N7M7`xP~4rMgYJA zbkb*=swmy4-fH8ii4Wj=;n&yG4EG?IQ5rYliAJ&^wLm}bv~klC&7RQK+&N~j#?N41 zT&MIX(VCoJv8nW1olzTc+1Kw{#E)4z-T&E>{_UikXreoOX)h;O0y*^Kvg1)gYR0XS z)4nq5#Lz=@wuM@+D(en=SKB@cIoUDppUHWJ1sSnj+pws3s+S*5xFkS6~NlYP~Vo0r|FsL4ULcHP=N_ zxFR{c(s;&wvaKD>wMfzqInwnKcU74;#<`C{3kNrAQW;w7OU_0#vt9P8l8UX%NxKy| zthA>H1UIqG>E4l7R;g8>+EvKB)HX*Kq1wqe4|u`Z=^v~u?nGtk==&@m+0`}!#A%nf z!RB0`Y%40iy!*Nj?al43^1 zxBEvZsm*Av&$l^3G zrNh2~*TFm`1Q8gMCuARtl`==*| z$mGg!-5%In%Wi)%yX5l__gB)v@S&wNRW&Y?gB{H`hUQgLC!N^Gw>J+ymD-IyC*0dm zzvc3wF@n!9#%oiCjQ}C7k@(MK&P#MaYZ3-c=f7`hOyq+wc1kY!XCb3Aw0T;hGohob zeCi_13QqavBROCqK9Or+qqp#G5%gfpu}t8GC36MP#C4`_i4;R|V`8*Ws?>XE-?eD3 zHIH%yuIpxHBB0abS0X3BkGNOatd59D(DDL5q*=2B_em%=SMV;4;Tpu@WoS8%uwb0a zjS%to^Ea`evh@u^E6R)Xb^rRgmd}sL();g=fR9Y{=6*cisu_dl4EjnmP55&d+S~@J zDnV_F^t`~b=;Uerw-|%_f5sRbY@Gi)D%2`{#e{?AuL@Yr$v#2v997I9s=3g}#EKai z53H}eOD*n-B3MmQg7|r0u5?t9OcNEL8TRDVv6&>sPm@V2Rl@t#ExE;sG-q4H?^*8X zDAelk{^ET&vkw*HGgYGSFjHMlN3G>4*D27Swz%0#Xy2lUs&9O^VOT(td9kO zSx%_iT}l$En!LyKp3#VfG2Vz|n}AtJS|hS%xTojyE<_<@Jz;>K@)si|TOu8oF#f&G z3@u})czh61{C?7X^?TSp%V~6QpUl5vgSh89BXs-unk=+(T90ww9>1m+9EsYsj10ai z*~HmNuWi3i$>5pE=$#Q)#G5`j)JV)PPwf2MQ$xVt?XoF;%Oaa17K_Chx*!W|1@`ID z9qNyu;`a?FlBH-eA2_MqHIWfQS#B2yQ;pPx*;+wwt`8Pa>)RJD`MgnUtUXEQ%D%=l zKNNdJu?m@4HOddc72d~sL>1R=OPNL+uXn{MAz0=*o!%oghCb8@@)W4Ufu63O+OCEk%*9xi?D|RhrEP zJdweLE8k>*q#Wx^(Pkj6a_yTE*c^#nQKl4hw5-Q?`1ihHm-}UZkb0P2+A9kPhZ-8Ts z^B=mY%#78|3)FZcCj;Rx{JK$l4gZ9tsE9Zp-wM(#l#;q)g=OjTrhgHI3Lz$t6*_+m z$1C(dQ&u~m4eH;LLp+B@ggB55>Stu4_cGd=d0<{J%k_51qdbLX$w;syV&PG*UT3*9rA7$;Kmw1laO`l&q=o3pZt-clpaSBSX;R zoRRVst&d&KnQQMuyIQ!P4UX?lIgD3?N6Z4Cr-rx9?T_ z_R@#YF!0H0uf~eZxJqjEMy9iwpoW%}Ds#t&io|@@3w#*F%@ejztmaj9&3iRen*vyppj&p0n1mkN=9J z2%J+_r3nx(-9C*2s|pT@M3?KrE6f&Y{>q}eCq;8|Bs4~kfbb@O#wb4Vsu+M1&vm*< z9y5*@RS!dvO`qS#A{{^eoKgC6bJdt6HbKipzI z<(nG^+YOxG)lOZy3ZgX6R$TFW?fyR43@`F$WJ~#|79$1MX2mVa%hpFTV83`A@&8VN z8DH2&(ihEGws?^@THR&cNjAbe1r=bN)~=T%6w_H#w`z@%3YcQm|2)u$!`m!xv+EU| zjG85pU3BCo2F278$T{F`Gf>e!n1&_&V8^M}UeCYg62}u~{Xs{dCw4P~at^YiuMFGg zWu+Ip&5#_^)#Qg0?>K$>Jy$!6R)Xi+creTnYauhKL+j^kZO%2A#v{XMKc04J->OoK zz!8gI9(rRNUYDlTI*5+Mp+&}Jwmg*33rBVGb;|;`gkb2T-Gn%%P)(6dsxj0%A~qWd z32{~38kQTVdC__CBX;kqfuU8YXhnWe1jeC<;!8S+_ac*oKb3|8N0sWsPN*?n3(R|B zA^!P`1f=02kH2DMK)_!W8hn>L;h7j?1xue^s0R|xr3Sw_u{ym~Q{g(5oXf0TAKZE5 z*b49NrrO^c|Lh;}0Zh>YmKiwCU+?g`J&7;=%*2d3(H@Q|of`ozGoc={(7o(9cNa?b z6?eUXC*qb6$2}Om1iP7w#`yi2i%>^Xz19Ub(L?%g?pal9-q76#^*}XEJtfY>lSkvDE!0z>c^pLi1M zTts@^U%zu4eq==Ux&%&GuSBG~1R_b9$A1ouy-)u6Iv|@@Zft-5GMvBlDp%cSHxXCg zgXUdC$S;9kL=kO0mp>|3WC>Q2P`(C{8c}I#6GZ~O5-#X;-TmYy{zB4imm^in&i-sl zPc)OkwZtM5O*;O11f{tGIG1Vb#&+KS^UAUIBg_PaQsk)oLV>%8%bo!^!Gzn$%O}J{y#Ur~vsb!oa zH#w`9Fu9&1YcL{j-ysfuid$w-xAaf2|2zv4k}FPjx7j9OiN1CqOhI7MZO`fg8ai-d zMK?@RJbeMho+)7K`Lus?gape&R|jSMf)o3nHns;BfNJx8hWWfN-;}%Vw}K0k>=!;E z{yq`1z`FLLHQ;osEgEEtZwMmzeKAyt(Z!|4pDG74P)6T}#+X<@--l2{QF-jQ0BD$E z4WF5n@U6l>Tl7HZ8mx5;uEVn~XYJRyq1=ykNQ|x%UH)=%XCW>#|7Fa#siE$_DW?U) zhd6WYH#g0IctY{GzbT=0<97uaw)`O|74CcyDB};~IkM1Wu(5`dW#7G9un@OVJ4`PH0`;cI{=o?htvIBVZRzE zu+KQSs1wrYKJHKN_c0<;iy609HvcCv#^F3^sHi`8miyw@2)O1ZHvfM5eorKJl{0So zz|&9i_QFgU#%3jV8l2ka0oPO~5kIeMwDcBPiu2aUjI>a)z`M~ur~a|8y~Du}5Lff! z+l^HgxIrSkMbgda2h&HoRh9f0sT5`~`eVA9Zc_1vHxY5jl0P`PZpv##Pq~qkqW1P| z6Zp?7KH4&+ICb<0XxrBY?|(?*q8_l_l8aWGc_t^zuU04gZWh)sOQ&h-ZsGCzw(A<~ z4{@^o*Z<2SkNSa2w(`37)FyB1~e) zQfF9-*XP+{8+oR&4QvbGQ9vcaY{1{K3bgLnlf1o+v^Y9EXqC$e4mNC^520JTLPfE0 zY8DVb)%QIyXI?%byGqnZ^_!S~)Y)2-7cK%+cO>Iq;iXEWxUw92X$@VBiPq27t?{S|xO02rgvk}JXPiW7|Rfq^0 zOWSxRuc*8*C**@{7fwu0fQchI+Kyi zKR$u$Ysr&%Hd(eDIyYLjK(~Hd%LRV6^}Kxqn*NJ5`EOYX@Bb|1b8vC|?;z$)Uu_lC zE$EwPjF)O+tVH!Ad;K}+Wb~?FlrdkN3}DT;9>GwM<`CxGb?*;+g8@mM=a!7BIG&t; z*9T37bdIrPPsg`eUT$AAhZA_5a;rL^uvekl{od9GcM#(O zcDMfo_x2l`adLlsO1~Yv@+?Vo{X0w~-HtWPndEKn_`wh|;jp<)6g(<1O^4%lm(TX$M9`_U4BL9nm4#RtGIaqayR1h#eDB z(^}!Do^@0`Ryb|1gH82X-1DU>@_Xht)TbmzWWzL1ud)M66@M0#j6`}ee3v-gDO##t zkNGx9N~oKljy_EaWs5L6JYZ^U%n%s(wry+g3Z`8g=Ie)M4wb-Z1E64j295HTX7|rZF@?jO7G=+d&@Qi32rUKbpbhyn4x3aA zWsKZQ6nRo$Q6`{4S*AV|dkOyfv||lVtL}*>U7M z(;ZbO%*wbSW)|0`wy%o1B`vB3$x#$BP2fN4FUpSemS2jPZc!gLV1IlSJ#iU-k)paz zJQqPM@;&}cGy4X$(1J^y9;21c-CWV|Z!2`w-lv5x-eGq_MdLQ&1A$YIZGi=!s6?eh z!7q&_6nn2OHr4fS{!HDDDRAYwg^tEq%CW&EnG0D<@dv_Mbn_w)W3-a;9B`GW!s+O{ zK(g)V=(xZMyt0>>o-$K_5jq=ogRd>qLxkX{k9D3NI8g`Ehah^>s*tie&=~(yPi8k( zJ>K80TG8DmL(Sf_wfK3QpqP_S-2W3!-NR}qfX z>8(AK<`h`t>>S4PYJqMDoQnqjK#j=S8F@Dx1gvl z$6B6an+b0Aqv$fhX~Ub8Unr8x*jSbft=$(7KHIe{tdkDocE3LuQv+Y^Tjga#unZvz zd?odZlQU>&J{~_3vtfdt$cfadG1B?oIunt%apA{aG-76$g13DslCW|XDM)dcFZVQ} zhnDcsO6v~`z>jl*hZiEa%=yP~dwF@MdqtEP)C$0Vo5Pubn+9Dtlr$FK0-ycvHc?-0 zwf&xv|CWcH^xReCmU{07ezv}y9oB@LuFLHy!G|llgPQa%c>s2Fn0qPijt_I=R*LZKA)m z1Q^vzH~aZ5Oo^nuXZ#gTFBIUYp=eV&@l7>uNG!D*7%mKLARR~Y-lq86_>0=_>~^o@ z8|5v%g@@PHLcgGFpnKtkOXV8-PK%rxpG4ob*CB)o7HPOmkdKMVBLYuMrQ z8N5uZ#Ka1spl@0~pRV9UFvWD5$+y_+a}G`M=$%|5hq11xqN$lDBC!0-qFm*(>AXIj zah}o>tW@87eCHH#t&9adV*`vgyV$mrMfz^nk83WcYQd}uqn$0l{q3s>-|?dVhRpLc9Ced}o7MQ-XW+OC;<|p7)&E0mDV6$(M{9dmtOMLk$$n%{V(VRc6>0s~} zd`#-FxRO8eTPxQ}wp^(?&D(O9L{{Ld z&&$p84ERA4pjcx)_bH_s!}+v&>BC&;soW#_7Srb&_xDzt^d%fy>co8#?`7tn))Lwl z=(0SXf-Ql(@!+F%T9mg!ymx;-!5pyWf%OnEN{Gf?`&P^-I0pu5bDs^&wUdi; zA|!~I2F&|%|9D8dmz!`R!K8{z78riRbML5g`2HTO%0D_WJH*E?{jQR)hZ^5X8e%FD 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
u5;4Et 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⁡~Rw{zoNNvJQF~7jnDA!mD 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 %zf^W{ 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%0AvB&uUix#GqIW1*LqFu$?)a?}G8L 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≥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 z zm`PwuBBzUUfR^K*rexomet zMSz;BtSa5;(AHk4-Ov=Via9MLSh5jQTyd@Wz#Qr>6coejrA-2lR30%g;!^EOKKif9#CDa$m+3xT<8p# z=bf&3sH`wLmG)oLk#(y%>9}op<`u&ml!U-A+qFEQ%Bdx!>L@4l0u_%|p~?r}uzxrp z5KYu(;wH*?7eK>!H3YEdsu#A(8J9+(=e()1tG|jMo&ky>tH|WdIqe|D5u!0FskY$Z zP$8&DI-!EgIy4eL4Q#>$_C70RH;hL4e}XJsk%W9-~8KShoo zVu+Gu-v3@+Oz2){6@tghD!(v@AGuU3b>_I~L?7MVm!gM_^~M0>WD2HO<6R4tQ(7KW7l!~R*BB6&AQN7`(XBb^aRaX zdh0pugnoMbMx?0pi2G>sS`ZgTnkekCUA>I}p>)5X=t6t#m-^HX8^j9dB6Hr|;KfK< zm~P(${O)jwYVDAnB3@#CTczOI-yYW?(4`Nacah|{-*upvHSg`?kJ#cK;aF!wbj91@;U7 z*1nk^r|id2#ksQ@Q0F8T76AjdpyywBKhn3pKdp6OF0Y%B5;MT{!s{u<)%~f8z@XGzmQ5}-ZL+K_yGXVl=}RM$^br8J3PEP)sh~^pP{ZE*>e^?hwHzn za8zHnXGY|j9ZuZ$3lQaly7-@_Hv505m1bf1@6ejlT9dX$Y)ISxgD^5xH@*kO0NQX} z;&(-MXG>egAE%5Q|D`K=BfaExCYd~^UP|!rhudwjY@r${cIrSg%NtUf1u`e#aCjC`U2p-FxT5>*XFFs6y!<$-R&KeSREW{LR6- zl!P`K9A_tz?^yKv^^Sl?h^nKFGbXQkD(&^<`u=&MlWn0L=}9c%E*BEFicV)PuA(2w zt%4OC71K}>T?iv)B8E(8i35u(67%zIVVtnF_O+DG2|vGmQx>VV>A`CjIpmBjZMDHn zHK~#pS*Y=tR*k$JvU_xD358^SPw+d`T464~T>AazWJ1P%fA&&pNDdK zL+)K1D+4VI7H&R@wb%pe#-dWL1Ap4ssUz=VhW-;V8>O4_RraOh@>e8mUal@Cp0`@M zl7&tTic+i+gO2%LO|@T#lFbX1os1el4|GSZ>!K~WPYW;t*+f(mLQ*zxdjW@t2ZDHj-N~yipSFEKaxRV;4A%_cm7tT?kto%*AXM#)_q8}QM3371^ zK#$egJP-+uWtE_!KxlOmwWCuCMeBI}V~Qk_<^eM{iv7>EAcs^cx1t8yI<5MeyXLf! zRC!N9Fpuyq@!DFvvU+R)lG5rphL&u+{7>V; zhsoX|dav4u7bWd*rQ)1*!m{8LA$Kri#~WRRz9B z5mq;&hlnT8hYISnHly5p=_8i~ZA#!01&zffqnvDE!`v|8<{n=Zl4&nZWhlj}jYY09 zH3Ayi?gmZehg-eq1akc=fEU-56I9W*%uA1!su-EKNON`R7?$eklBmVG@M(!Z*!Xgy zXh6B%;Jp7dij+B;BnM^!FuzlHPJ;eHQOVO}TAk~3A<)9g3N>*r-%vBDyNP}B0WV!f zU0_2_Z@G#FTZfoSWXcR2=mlCWgf7ScgY_^*URmC?ZU%{H(Sxe>m+An3W}_h!3Jytc zo%%HZ+Qz}IFo3~QXiX*A%(d=}bf}}3*Bg7L@YK9R> zNOGyd0R1#gM&yJPC&pK&lf0H>y>Q3INaNxn!4IQL4$5R%`Eha59(Tvm2fo1p(d=U( zspz+L${Y7!vT1={Y3GvBqu%6!PK*QJH6I#l@)5SdLqiI|KghV$v|Npr89IXe`wODv zOcVN?Of;+2%f_QIiG@@-nl^CNL@4h~?#GPhM6)d*SfdUl#59v<)Ef(A1bR{_4Rn!d zM{O^qvpGw@Eh~rwE70ysa0;Q!^9V94=DMjtxfe4~_aO@5QVb@eDW(4nNww4ino7Oi zcOa_cxYlYMc4J?0>y(v?AriH5OlFWls+Dc3M@gT_O3&%R&}Lkw6)uRr!=GxK**iw& z6wkez4oXnK1)>qivR{&l_8Oxvm6EP1ICe9 ztsyy;Bo8YGW^2E*>XfS~j=o8k*9B4Y)lK;q*Vhb+EvraPV;PwM`#+ZgwPDBg6Zo9p zf3Tg@7)>CWz5!>R4hvKSu7Z?pIyRd*5ZgBE(OFC!FA7bHM=pjI6?B?0eJYiF(g*@B z)`J(Uu*_8myRXAMXXFoAyu`(l>#>J+ZR64hw$UJgX~*w#mWo1qQtc?$TO&|GNZ5^9 zJL~d5oB77qPKZ^8RsWb&E)l5vG^~=4&k1@7X$8V%TBlNj)?9Z(+SWO8)>b3iuARfl z69*y^n=9mFP1&IzY9rdMQ-fA-kCtkDHXJVp*TP?g4DLb;kmsZYjYifYdVRea<_#D09Hgi z9deDFp>mXIk?;BR{kga?T~a_-?U$dK$Nr2Aa~@%saqun%XWpuD9U=Iqp7lJSuRJ&1 z2FfM5Jg5;G`^szd&c1Sv6BTclR!TNz>8Wg>qAHUN5=njrSoupT@q2M;_&q1!ann!P zvG>M&fvVrNJM~K=wzU3v!{%#iSgj0*sti+gZTLHs)q7q>WAalsr^4w8`BA(pIb*b3qehk?rVSZvwBrVt&)HM=`vy%w<#99-4zG=6D>Oe|)4_a_Z|c zTvz<7Ut&At-Y)=`9p2h=%z6VQg7bNDK7Bv7BHi6>nRA}RbpOLE?#%8P7W&m(sH~>c zt;cFPa?;zdI+R{{pK5?&kAJpK#t(%-)1<@)RkQ_)V|UFn#psL54+tR`_?-y=MNXtV z_v`LI@Wu@wzlQyb;6KpjNzM91&&SzcWfDv2j)iJ71t-70`|8^_=R5I=O8{V0VR zXKd>MDEx2sDH3mRVa_sv$v2dSP~{ClwW)~Oj8!46Nxk!lkKaqb+Z@cmf7>zbG+8j! zO@z^DjXF`80W|oh?pN_`gUK8H>!rV>2kFHvUt$S^n-$6c8LmF0;k^9GF`Zj}2`J%j zjks6lpRi@ehm6)v3ELKtYS8|L*ZYh)Pr8d5q#MFP3sH3kKHA$==J|!6x$^o?styPJ zf4ENIVE*sy>;KaXvHAZZE~n#$55SmV+OpdM+GXZi`?J6jvmDdDe*bm1lUFpUTXuFj zjrC^=qgr`Xd5UPd?sBd3;N|GT{aX;Z$hs8ZI#TVj3$PP*l8Yi&oMkBtnlE&Ho&9(u zAyahao&+hHOHvDOb9krk1*qhRP@?6X#mWzZghbSu=niL|I*#P7W8m*~JJ4=74}mGe zOH%m{lR19AA4UbxO!#!V^cI&mQHWbtl_@CVi81rgec0}~B>vq->2#%-;*XoEG}H@9 zEJ~3cHYAZpd*>g*aQ?=;JT1guF^2LA{lRMvUo9}5C$oTw9-U<9AoQ(H^;TuabQl*U zM!e^}qPOO4(=3pOOE)Nuj23Wapx!rU_QA?EDZq8UJS_$&z5Aze7BqL ziQGib>a6OqkJ#zwi*o?0EUJ#q34n;=%J+NSgZp!&2o3UPHeeT#-L#UXaMcH8qH9r6&@?akcsQb!Kz z8l&_6p{-LhUapVo7WjdqS2(PaJEzD#iZ@qLrh*U)dhDJN#II8eonE}x=S~+`?-HZR z3W$gV&>l2`A5~~iS~2*jVx%{!tH=4>Na0qP0o-chrM{Y4?ntP6u#otw_Ph}6 zD|3G+x0A-2RTSw;$Z|aJ&lF8$#D7l4(%|0d7GDLxCNS~Upt+0#3l)hhH-Z&nL2#iI zn}|_NR1|!*+WaWX&g?cfBQKgnFg4-<<;<59(Ct|=Ddu?gjH$g+{K)+9*X;>E2{}zS~A90Z8#}TIi=j~t~|{Tn@}|S z-a4e>trDe9B;FfQOGrb2+Mp8Wpl8l+2hET)w33i5bVFANGr5%xUSoD6iATywc+6d# zS|K=pDXB7sMJ>{NX67mNedzy%vCTZwm^>%kC@%LmBh~Z+!=T*>b2_A&2AH!kmP2r| ztYIf27?!0fTrkF_W{F<{j8Gvjbyd_1h@t)C*@NTOg5>Y79N}`^fw9n&xxuIc^jZ$$ zNR=Of8IT31f+3_bLYZ_WWSJ=c?wLFe>ffLD^(JPZRLg)w{dH2r+5I^GQYm!$*<}mYUQ>2qCUy}(?i(moX{*3eCD<~YcY77{DnI4M@pLWIx^hL53 zRWI6Uo`;CKmf(}s*XKUY3s9lx%5A*Wc>lC?L$rwQ_ommKMfX$QZ&oB&T}S|Z&X+NM z2q~9V{K6=VhYw)Obw|X^dc_*u@}%jqcxL2?Aw;)|L$=|L2`njF&Vb={8ZBIPsx{)J zl!|y(E8H0zsLK;j4l%C^&kf-t34@?uZDh0Cs-@wcwY-*r0BnZ)0saKi7RNWppGjY2 zN~!3spR(@~sv#TSN#e+@d8vd}VuzUe>f0vJV%&ScrT=;I2&jYCUc!)yV^5@8OEH@YIhR|NnCD)ol=&GdV6S2*38t!9xP){^oX{5W?aEp6Z$df z?DD9$y{O7-jT_kyn%*~;jq)VXXV-CB@UnMzg3akzcqh}(+-Z!|>Fi49j{tO^Afa&r z%S=asy=~k6JY18;E`>E^N{6!^P~OdOf_T<>Pa}C7}HGi&*e(`{2DUZ-=f9XM<8v{<6rc1%$}%bWk!An!}I&1A+`>UV;sg%>qhnMO|ID)wfih)ueIH=Er8qR%JAq8bN>?X8wumxe|35L105bDw4^&@MR7erUN%TkiXACh~YNTz{E|lsPJj%=Sjpyz*Zu zv;y}KdA3#E_?4Dq(~7TOU{aaF%m1JOaWMSfowxsPZvMOWr+*mh|HT-6RXYRE5JIbL z1Aqm#nRWNyVm#A|Q;Hk6fJ^`7D{A{&AWqY=c{46hjV6L-byzu^Fvu5#)5D9qo5P#U z0;kHZh!)y<8+3r4@Jl%!6be?EM6U^J#}~?{TLdz=8c&y`Xw^ggd;2CEW>$?eE6*)- zk6jEmi-sC&o_d=7##!3g5_Wn=8x!(+au+2@7>#1xhWF$Bc`adT3T>7Liphr&8F(I* zb)S;JFL{(araX_AbnL(>LYX@ggLX`euuz_Yl_4CBqPPFckNVgMYm|Nw@zR9~6?LhxembDEa8Pz$HS3^Tf5BKOXTv&SYOoX0BksEnk4B!X{Hr|pjV6iYL$GiM})>?b1d)-YR z!C6fohJ}2fxbr;$QVJBrApAiWm1d4__hReNwUno z#jRJ@&Sh+3=7e;u-^npYi6zN_Od7TwIGb_AI3eEpxRPm z1V|iZ!jNd~ay=?-wmp>4JKav(`bb7zxy{EWr>BeOd((i?f~sk0P>(NXAQAy7>ev8j zrE>ptcks1zSF2(j>6*t>Z+>e5qoBP#8s8CEgDCE5YHQu3-2Cd!+IXtic7cY^PojSK z-&&qD_(axmX??VLq?{+2%>>$VUEJTqAwMW0$WBf2o}7TKfk;vepsY7)&{ z*LlYl@MAxVT2KDXxJx#$U>G!B}liw>!bj=Yl6)$Zqnqx+!#T|Rf zcjoJ;!6ru*;g~XKN++7=3?%IW&>2_=n4ZL_R^LUb=9s~k;(t*9L^-4S0kMv7nxuK+ zBT2D;gSCo>m7R{-lSx(JEUMv!lKiuF_T%XO+Fz( z%Q2*nh7hg&-2Y9{KvwcskyU=fk78r?&|_IRW8uajlp4u*t5P$0yASnDFx z$TExel*H+4suSmO1^?rD8F^v`s~Opr#+25HlNJ4syX3VUWxI;^V}{x%!zvYXIdjA9 zqOjvYld4VOw01|N7aoDGtwMo=nb(7zI5pjc*zJB<^aOZ zeA_}6F-7SwnZ(t^`I?mBsi3z!5_F7Cn9DDN1hqSoZ2P2v2}wB5cHB^do~AWNn;Rd2 z+V3>&?HL&WzSIHN^fo~VFqr3}#ZgKy7g;rIv0E`J0uqD7YB8#py%(hTX6i7oH$fL0 z=-b%vo0rm}+Lb0&W^V{3Rh-M3xoQ28-g&6iV2?0O2sj}ZJ_Ol4?id_kc$_a{!)P(9 z9{uDaD`Ivf(RrQ0PY{BRgFxLK)zH5ekFw6V$`8$J(IZJ(abM)B(w(8KXz*szlgy=? zk$I5{FK1oU^^(Vo20yMqk%}Bs`^E3PZtZ01RR${-Ni|5D(_Btp@^NU8*Mg@AWm{vjO(@*jdGqcQLDi-=wL+d(2 z&I;%bLjVnv`O$N!R!S=k3L2ZmB#OsNSE7?#&#jtv_63$NTCaQ0HJEfTW?|Cb2DK;M z1DvdHPLqxvXvZifuT5cB|3oRY zxOpDEneAQ~nK;$pEn+F~&hmbJI2t4hOhv<|;kN{Ui;dxzoI7=;d*CP`>lieu%A7Fl z=HW&%KUfHg%pKIL?d3bOzA7y|RZ971xA>q*iGa))l1#}FrxqpJW%!OMWIX!UF{_b7 z&`g#&0g!O4gl!==D#Xn0TP;$*QBqP59V5g&+%SGeV-Bl@+H?-%%eeuOADI^nT*$pn z##AU_GGzhtFW}mz&@bwJa47Y9`FJ_l3y(??6k)Tb(KNx)`uRC3RE4i^qO*os2sC$d z%GYTJ@AuSg3jQ=p;YpfnZk3MC%ka-=kxinUQT}EOnZSO=!9#J#os0_~t12fynvu#a zlMr*6o4f0#GrmgqD9uykt{wy1J3LERaDgpA<-F93NJK6g-M#}>s1VTB(h8_L%7)aB zA-&64(|lk%LqIP=c`Wa5!mJc-Dxk8f-)JPVqV1oliX^Uiz81E>bXjn8*`)ccX^as| z$&OJ+o3AV6ZF3FZoo{La5yt+RW#-qJT^3Y8FMKzJle$iJIk9HYf^_J%iLQomCxN4L zbUYPUe?>7eYT~M;sQc)(XBqT_aWl+P3cm{#8iI~5QTca_zaX-meMo1zgCr7hyO}S3=t)jenXb5CG zQ2d7YFNiKdI?E;n@F>YXUZT|fLJn@SzXbVf%AfShy0~Pz4wL*)b zW*K(@J=q9ceJX2{=+_Jtp_vddJ9M$%H1Z{8=v1!14M@S<$Sjd1*=LQG-o4Njplw~1%v@HB=Oo+ zW%_X-bEDMgRz}qtW58?5diJf(0U^%mABC3vf(?BGq)Izlo(@dQbyc`#;777f>2W;` zSf8zVh7q7jl&Tp66)fp12{pdkbS69FbeoU5o)1Xf8KT&3?gBgQw z&R825r+dMEYfZa5^t&5yIuvAiz!?x6bP*6Kejh63e#S0 zZvy(4d98)1zM_yM;s9|BJ?IvcQ$W$Rr-GYZP7#fAkGnS1JgM(OOf!gH^s15A_&2d? zmq;3`hksiQhK8V5F$k?yP5a1L5F|1_>R^9*=q91N4U|^Yh~#)Q_JOSTgA=697#z=1;0UCHW-7>udal{fhXE1 zTF6mZwR7!ZD9beBGu!g6(1E~61t*eF-51dc9Sk!b(@u?zU#Z4UI))@Frp|fK1fWW2w57K7o zsbblnV@Gw~oQ!030aLw!o3eUN0m%=rjS{f;f0*#>|6NX%f${&BQ>Fi}N@cFKZ0xW{ z5r1y<9Qb>S@VZ(b8ydMp5b)_-u=)gGHvu=WMEND03zQK-BjC3DcFj`${Wn##SkL=F zEC(O{vbA!taWTy@c}*^?g>om6G9$1-ya|XRM8I4j3E~d%&@Sg6AtZq<&MEw{gvCwn zZw$!;HnD)mPYx(^rNI_=RI3C=jkG{nWG*Lo=eK3B9tT!Bi8I$fe@$Vmlh{&#QHf39@LusLE7b8i_@ z8i6mV%QKXmztbEPPC0B`(LrhnZom0v!j59Ou|Zw%++j@{a%91u{O21se$y4qmGh3*wMbzk}d4CfOTPHkI-YC=9P)L_9-K157O3X4nmb zU=$qcoxkPCO_PiuwS`8J-0h0kk&hF^AbbG@gDp-3fJ21zOp!%ohZVvxCPNt8>_Sb- zAhzdeOm1~eIAU@MC#HxW;5CC$qCdNjQ3NU+?QrjpkjeY@^?3j8M|*OZdU_hU{C4#` zPwDIB?fG+S@MT%gold7`ycGQ9__g`A{q_v4`TOAP+vO=x0m)&M61Q{3qGBx79E{@5 z;me_aW_H*bc^Y}2x!-Ph#5PDaz|Mk4S zK3PK_rAIe|Hfe_5c=(Q=&lV+T`VX4q!F%_y+S{Yy^J&eZH4U!mcW3UH#YK5 zLtXMj(H;NGoZPHUc=LIx=gq*YK^v1htwuLOw#$u`JG)!8!djL6Wc;#-Gm=$%a#}g5 z?s84UovlZ!OBZ{ZdKrj}=flUxk?qs$zLsh@Y63C{Nl?y8rRQ3h7Id#0}|lln(#3io{d5$CW80i{NTT{kZ zD>Tp=KZPQrf1JD>HiG1>6KR zpQIS{-k9F5pXY=9@vqkV&-IJbUcIUwp=XUAK?>>KtY|T_$in)MEV&p{+1j#WHDR%r z3AsMFB@l)ZF{U;*SHjW5;|KRI0~b%%4$f@7nBE!H$wf9kTHSB=F7{q+8naSzON=ME z*vrAu>H&Co-YvwwN8_@CL?Qr4$W^#$Wd4t^*nl}Vjzb@!MJ=cl{|^5up@;%q06uvt zdA62IkOw5?LO_Oons(Eq>Fq|L_(XB0xNDd(xPkL=f%`Eg{!Sard{`6ICcs}aRVSiN z3Lf$W#4P6ssEa)Xcv{Ld1k|g};=dAx9rqy~70&K8_|YI1Y&8(9YDXE<1VM_e{B?Vwtf;Uq6S};f-$Kyv1)f0>B2JXYck&7t615##-^g*wbZnsXgo2a% zD*T{21r0=cgn%@0u*NWdsKQQRChbL+H|_Q9EN=X2>6Z;RMFY5+BJ3H5<~mv8hsxJ{ zOiAmN=N$bi$mb@|pqSqgQ0}~gfLtox|L1Iol`ZlLX1^eAG{w%9;6{vit;qvWh?ty< zFkbB=aX~2%*E_mB#TLy>p-O>KyHV(xmmWm<%PmjJ@Hobqw8}Ao($SetPQJ%pN?($L+@H$xow-}m0n1rFKTISy!u6sv=3D1&o|nO>oUfiDr+(g6iwgm0Aq z$=oht?ksc++^(>_>{MfvPwL+0V-m<}@Tug*y0P{Gf4F15{P5pi?ymCRA{&1`DfX9w z&HX!MjC;tKci}MZo498xj!oXUYp9osX^LI4G@#oG+ch`z(tt0Dl?3e#W*ao+^x}*g zYemu12ZL4vn%06I+d}cc`lPJ%e^{2jIL+gWB0{H-(0h$|iUNHYu51CeO<8V@tQ>Js z0->z_PE(KzYXW`vKII`8PB{g=3DPXP+H1XL&HFppe(nV%$H%}-B_bcm(Vo^Jb_h zW~sZk{v(SSt$3M39ixnD?o>-O7aib%uCvX+ZsmP_5`LnxtqHqQ;sstwV~_bR=Zs3E zQ3a41bOWnS1sCdOfmJeZg|C513 z$8x;5t%|rqsF%PO>>aL`NOu}8dM{k4PL?knC?l91{BKNvpL)i=PKYDyj->_y%mGWM zVQse9jBeyRH0U38JMzV;^Ue!;)@x^V@#==K(Vnil2m#5x%nvp`Ev|j%30-M57A9DN z?nxDJ%?PQ|4@UKZxn3A@tomdvRC|KnrlG{ceZ*N>Ut<97e;wLg`v)w7HAsqW1PQGu z0+N*paxK7!g1n7n(g;Iz;>fxVSwwbcjiRs%exOq%5RiO$9KU5CeGqjMQ65@xf+Uu+ z|Da89+_tnP9aA6Bug zH=pK_z#OM2lM~0faU)Ss4}zsmpP$-0oDKQD5;B3(FPdw-?RWv+XV5!p0bFW zq6i!R#Vcu(K%wzCC(p)NQ&v*8@ouiG3iAW!@!sI+z2VJ*h5aX7g$-V=0v?5=^yZn& zKkNY{vCwzT7#|&1v2qoj&aQT*oi32NaRHj&Yv@-_*Iu+1NvMp-|+ddG$KlBTv&=s{DPPX zmQq?ESVJI4Lu?>}XRaU+y5#;$0|HU+j~7P~yqUl~3-D!LR!%_(T_3Hy)Y8m&8+4fa zW}${QM)Nh#MqxtgDy}Csxalnl*5?e|mc#O_#Va{>xC0LSRn@?_f+mCruQH)Mhyz$# z)FH?hM*2B(fOl}}IMX4)NZ8x>8Ci#zUIcOEfQIUUY_&b&s=Ft927s1{^ch8sFyc5# zM9{gL(egm+A3chU?>UK6cagyWzlho;$r|wP6Ck3Hj=ZTzYOEbKV~_qxNOib z)dbb%68OqXH#RH5*g-@Rx^Ko?2&+>MWK&?Z>=H|`8fPNyYL5Gn_Q$2f$@rus(&YHw zE3*^CVsjMh65Khhazgqq_DM2Fn1`VE=^Y?I&00u%wEIeUO8@rafXPiOIy5(-LZ_z~ zhxaHEPydpMi-GD8a!fux4%MZMMrTn-8Kzx&b8l+ai>Jd%e-3N^*uRiG1;Xx>CL zz-5LMW`~qbe0sF#UERq^B(_82qw~m#s`iINwcMlqL~pmsTfz{Jj&}(9iAL!n>~QaI!mFga&l z$h}z8hJwOb5*rc&n&>F^-`!a6osngZz7c&fu75S1}BILo@&1MwMv#nA2a048uQ0VyD33mmlf-ckjy0OVDPhu`G zO0%a?!F78kc|0aT=pj4Jb07?6oQgbE2ZZ+v*iyf`#t<3WONJP!PV0 zpiXSb_e|2SP$4l)Nr~oMZK#oUj*l7TjwxQ&hCqNNwMzFY7SWZ7zCrY}qr9ff?B09) zjpxV4q%)))t83M>0-Y!QODe;a@)}$F4VCMYZL+!U8Zl_rDeG15VPE1Wjiy5Q{vZK9*A(WXj`+CdrDQu`&XxA%$L+K zUM)yn2{vf6qi{#HwOqfrQ!sPpY)U!7uD8~fy4lACsIac~1DBjxqtcaFG)^3)at{Xl z_P%r+=O~S8*z~hL>_t~Tnj6)3>NW4w58~3JkkZASqN#Lg&5cbj2xe9+qc$uWTncNR z!)$qq_ABiX(lwiQf19t=_5ZiOKO5u!SX?kMF#mUitzNBZyAw8;oipk$;9^8lC3u1k zfh0+=^Sa>csJf`OYP!u|{gftB?J^tPy>*%#?CB&4yu?F9Ti!3;^MlXjtFz^G_~>Bu zz=7<8$9llGz|;PM&c(%jz?5bNpC9J0mzq{bpWcU1E$!*_vtQufrHkm$0p0*_0DeFY z-+PE{BjMZEvGwsM>+cI`FSfSQv)d<7LE==*4*rqlyZnBhi<%m>#Zv#}_#W?HpO05d zwH*ynI=HwVAlPC2U!GEMh?1Q6U`8q+xZiKiuji-goYo1Xeqx2dMTJeyB2G`=LC$yy=oq=Uebkk;63{Lk@ZfDEY+M8FKFBG~?WF!OBPTqc?7vdB zA5cC#lrE=8K0&IB!@T#Aa-PxP_lAO0VPLZ)-cN=0nE2_wvG;`>t^dv?3X_?rK5e`H zZp@SjCOyoCXS0MgizjXFNeovAoEb)2u%n%;s*{@CQuC+`M=^xnB$13WYnz<>l193C zN#`CLi`0gR#2pRW4XXt;EnNlDsojW;qWG9D-8@ngvYVz7TOV5!$;Lzx7beT(5gW)8 z4v7!tO@?Csxh|5=uh17lP}Cs%Ywmr`vVJyRZFBv@n?Ha1G;MbNt|B2uVcQs(w;l%_ z>7%!18reKf#@}_bpDBH`sJwQxn7p#17C#kP{FU8 zXD_ySDw(A6!j5>ylzXmm9}_!N0C{mboA-m-FI!C^vR}6&yUf8 z{|Db(w^asP{7+1G(5IHvVe1oHDSxBkwU~pT121x~d^4j0Xeilfty-WjbNqsOjcXR+ z=#W=gUjN1fHt7UnWIwlU(k?ye#&Iok33)@)IoMQS~f!xx-18b3ZVT z30D6oLlx)YcD-w8FHH)EsnLY>5yrCKAq(Nd=A@uDO}Svvyc5SKcr!T5@$vcNE;JQTV(OY#a>%2zgC+o-Bo^arExla@n<(ue5p`ts*4|4#ASl@MWx{Bx1lN6 zQm;m3WedKZa$52hPv0@|6*-WxAsL!!noNl0Jg`3+6sPh$BQ@M-jK-V}z14HZ{AW9W zTWV*ww`WjXQ}d_-_B}iqTGN=6d#%NAc^xA*#c=C69V}AX)g$fN@!;b!D-(&?`LYr& zbGg4UZQbX4cdF zlqC8Z2jKI8<_)_X$*U(WT$lGriCD$%LR32&XPB=SCR*`@oxj?e%-Z>bE|Id{7hbZ& z4Sa&-YmW1SQ~gz(P*vxrdChTctByCyLSmlj37=`NnA6TRyEHZCmutjt1dtY4&l!>; zT7%XT66@g|)kJaTgs4wJ+~;+>BYq~a_D^oUooFe5a}%Oz*f}_^EVL&?OVW0@xGjEzYB}%w)a}hUPR~$qFXmk8 zaI;?di)RE-y5Xm`tYNes^T#?&1qt|);T}4^&NqpdwplUI502rdePue0Q%G3SIwlh!L>+S<+$u$J2Bnad!W7sCNg*p`jguc+ct_pO z{KdCMK6+xhIrqlw;NA!=TMuKR6G8@g>F@7{+m#f5M@OGJAH|b<9e{TE+A$t%20KuxjQGXW;8;+9Uloj z6v!PQX?xHs(Bcct0OLqwT%7MPPcuroMw4f3^^(j!`7oWl+fLqAoVfy$ z3UK9Jx#6|uB6<@7#bE79tJK*fgz4&g;i{$gpju3AeWXPB=g&h^Wu#I|ks+Bf)?HU+ z?2;Nqcf~9Rw<4QH7V@mec)xCKt@0MFXX_JCj%JEG(^+l4_4YyQ=0%p?rWIqexSk|) zb?EtmOskf`)#MxhMS(W7ESJ3%_}YTq#fM*e>sA}*roU{gQksix8V4`3|0$z=HAIJMLGWc#cXf1iH4Ru-r#$>w}&>_7}<3YdORaTfo_SM&N|^FFm+kWLn0UCsGc1b1+4=c^4X47vEl8#%cRLo zvdbxF;8!t1>OAD&f{BvkL|vHBg67JgKavrE=lH-}gl`Alel2nZv4|h+eq z0}*B_s z(4So(?%YhODBY9q5;&P=k*woDVzNhhhc8>_EX4`zRZ2#jQBtMro7I^EyJN~pjL^+~ z^|VR4XdKyAQ#?7rZhK(K?5#6tF*T4F)){P)$!Mcch0>X2q{swcD>7ecnIOO0DQUY5 zm7SS>1u~S1i z1K))cUOkGcTap$F2xE3+3irvZ3Ura>*@)oMe9kTk(0tBM0UMS-+~4$|ltqVSH58676M%$eyU=k%@?51#XCC*z(g?J_gE*+gxp8m(Ozqkx{-hx+4o?m9#t0)ZfIQ$5>O zC~*flNv*U&(7SKAAG0G9DI@vJkv*89$-UzFHwQyVXqW0sRttF&k21-t`UaUB9If1jF@B>?ORa z&%eu*NW8D$%GKgprHrV^OX=*{DSI&CgY+~`lRAWbjjQ0b=Ov#)Yu#q3w!g04Qq@80**_pJx zu(`_euYlM6GbfbK{uKm0OrwCkORO;Kw)0AhQYg_1&c6|?NmBDT4JBCXz5~?%>+X=B zz;NJw(K|MQJJ=ynTzA`9Rczpl@gE3GB*6hRn{eS1K*uk5u(7O3bFq+T6vVLnP~;MU zf6t6Mo-6d0(x!-6al;Fz2hBy@3kA-P>B~~ml^)NVQYb4NI&93gDWYKKuMjI&7oTrQ z1)D_oDqOx7n`J3_aQ5(Ia%EsL2}!2Z*jrF>B{~Zqy`DmcBV%GT0Gi3+l#ZW zl_FC3MBSNIX=#zPjwuC4fH<_%`J~0b1uJknXGmyaNJ()cwnKzRa!{$WXOuo_iy(2g zcVer#```{zqE7>gNPiTmpRTiAT1tkk;wz3V6;${g-6OM3gb4Z_H5VqZn6n_qs(7;_ zM722z_?g#Mq9RBU(l=_zH@HJ@OrlVeIq9LD&X`0ZH*ey@tEdXwkPN6c!>Y%bT^I%3 z=)*MH?nEQuSnb|-qH#%Q^{0KaX>Sdi!1$}j(|NSe!H{jN7ldBlmKvO2B|?Grl+IoF zqZhkA)smC+>7|)KxVzwT^*wM4RtXBuo&&PbS485@Z&h-ln$CTd?v77b%rND~|V(6yvH-(7UIxe>f@u{?Kyg&KRV)O=9eCieveU~ z9WCqJwq6HCcdSbM>@H`(_6^EWrh~7>eFtpYKdi0~#BOY$$<~)^Y5(3EUFG&$h{&8z z&u>=OgnPTwcn7?FV=hMQ{Rs7a@2gbx%^%DWBw#duz%n&RucsG)HXZAwGV-%dxa7xk zT~DevPClB4)^M^Y`?KAz-Ce-k6+BZ;DI70%@YYzsc%^pDGE}QHixFT4HTX#PR(WRL#xt1wSh zslUC*bOfuYq)U~MMDg?>NyX`dcY5>j@Z$67Ab?flfK`K?-vitKmtzV(7AgjZCV(0G z`{n$$6`V5l_jv?eGIApQWH0XS!$rhF2e{lI;;+Uo}9n`&$Qs_oSzrp${Z!i=G!0zZG^?!$K&7e0aSkY#uq`TCpq|ET%$&S z(n)wF3;^r5+r-~6{?5a2fB)Z?t#$tZgT~*GDkp+M77z9>nfNRaDcaS)#QfNXEJb(% z9=EKpn~=4(sMGQK;lPb25UEwFej!XKYm&NGh!%!8lsKsJQBqrq+LW}k-x+9WyD_jM zjVp8^DMlGmlX+>4bL$be^WV%qo-EhWVPPCl=mS{w)XB4|w4Z>K20%^}S0BMR%D2gLl2^rm|J` z9()?cv9M2`w8vKyoAE1i%Ep`QgBSL z=3O>U0$X}_Z;YSKvc=*Jy?-~L?7LDS|AKRxoFkvOB*BK{E0cb&ARfXjHcArT>6Xxy0#jkV5{jfP6Q0b6l6<`O zG`^iqQs0z4R&I2dATOynSKj(+jGG}7J^gWWDndQ}X8CNRV$Z*5XeIL`8E~I;rcf1S zC_Qq?vhsDRyabSLy)7n1%&r^0s7nCsYYr5kdb#L1#3T_HkuLD?`j$UDb$`uxSa`~V zj1hTuJy+>`GOJ&%kij|cDC9+iLN{+)Dlv1!BEZ~El`Ug#?=oxP4OWqhx?g3faEduk z5Ki^pHV0ELWNu05En!6|%hKgo#9?P}c-lz8?NNa>>Kwsp#hy!F8Dqs(j-N?~dD6wm zrzaDsb0Uw0-=(Fz*ky2dD2< z>lyd)c@D9J5q3L<2vf`np9oo&q)~Qn>V|tpCc@%dC5RWzxD_a*ME_gl&Q6M4uf}7x z=S~YKdX!9v2c!srl_JNLjkGoi<{%Abz&24kr`1Wcm$J4lQ=Kt_e4+OUVRvlb9s#;` zQr9p^aS&=sayc$e8#F#y;#lK7Flo@Uzq(394N}v=rVJ6;XB5VV$QyG^Q8-U&K8<9Z zsI>~CRjE4Vu-*`yN;6&!QeAMToR_W2G#WX`JmscDdPM$I{l1gtqAK2yi{9ScbdurY-qc6nW{oiFybEsnp-G(`?Q8wKVq)6L7(D< zanV5+aE#gn?Zi(GwtF#qk|S?Hv}aNv;PxE$-$Plh2qz`H5;aXYUZ{ zTfRj38HZJ8wkO%waQCEAbgV-$S@e1j!$6JWK6$#V#c-SR(yKSH77Q-*=h)YU+a)1v{J;UJ?o!CuCX# zIRG~=b|Xv=$;qfNIf9arMDV2>3*b>EZ&e?7!*XM}zTR+e=>HVhlx>nGC?77J6DAd#o5Wocd*}t>y|yUu5qHFB&b|0`m2Z&zgZj<(vs3rv|wK2=_c|@v-46_&ieXJ#-8?g>ltn6Z!O#DRg5 z9P9l(bLxvO7-#YbW|hOH&lzGd)2PmuyT$Lu-{)JLq7mdsuq({4pF}*W?Ql*2P&MK zsp5CHn7fueh#9b&Q1?xH5a^&<=2^D(tyT=y{K4LR8oeTb7GHb4PZmBOd6_c%6IQt+ zN*@^L-qU-ABhvEw_YnU*GSwlB1J)NLcN)U!cfY;x6VehVik@7}gLFSw0Er<^EBW!X zcl*#6fR(Th7~67i`BtztotlP9uQH2QP1<{=X~Vr`9MS4d-R8Zm&J~v%22F@9uiN%v zoniD>=UUITmhQs}u#IptEUY|}3c)M|Cf%m7WofP93@cC81Ac0f0nOX!+*ea?kUaFy zud3vzp4qvMSDWU-LWpc049vh@y(X1L*~h_aEPAuMd#kcgEbY`My}9({-YqWWtf9L{ zNT=8>Q85@oYRdI`*md)UVu|c*y0pMF!#4ZjJD+C(Ax-x5OHZ%Z8|Q!dxoq(2w^505 zcX}yBC9o#C=M?5^Mz^w3U0fMQ%~%fJ!Fk9R)XE8zz2iU2seyhR{$DV{_cb-how_ku(dbs)j zDNxxM82=|8nTeI@zXdJ+;dNVaRPY+^*41-oTvBB=kyP| zpJ@8p&*=ZzpW+B^4!nNWKXD-t@RQlN=8N{FWk1EGO> zNHjN@x})=N37B+jOhK=f2*dsP{G3;QJ$}7A;^Hl#y)+BcKQss0Ss=Esl=Ow)pp7N7 z8#Ba=5d%FpV;VU85=(&!&YZ<(tm4>tV0Tt)3eo=3Va`)Yq4XPPdyv1{dXHXJ%tcD_ z@j)G=cmNMT8BzIr5Gp`a;AG#BN$@)HZG5%DL_!%YICsnlmcsaFdKqJ5QwpYtY4DX7 zISP@notNI)6qsgidh1b(nD=_D2bGsEyW$iQTmA0|b4UH^#!6b}-NJlITO<5hKD&A_ z&7A1G2^K5QVnL6gF*LZoKT9MfdYSh)N2itWG?eZpJWznJE`sYY=53 z1}{jeiM1`|r_{~kjE=X{*Sjk=<(UN0RmFIsO*8rqg1h{qglhpnhj~KNP{13u@a;j& z4N*Rj`~l4FOm~N|x^ZX@WBOq>^XoHxNS;4gVboCqqd0Y)^Ag@p1XvU$o;gBA|I(1~ z0NR*)R{^6HY6IMXsZX+;uZ$gK6L^ijQHo5E^bgh{N=svNp4jl<5Tm+`T5}x;LaAy=Hbp;z%}5HZZ(l6ka$t6~dWiN&ZO6l1e@%MfbohYKSx> zz2FL?v`W_A5pu1kf0)E>pYCcOvpx4q+m$~qnYggOoLn&wweDIN>R%>Xsdnkg8woq| z=(I5=zzFnV*G`gfzH{Pa2GFV$7%g{YgaDN|tdYPvH|1__@TGQ??^&cgw~$=$s?)>4 zgmAg@@+Uc2D+u}UCpab}yHWT&8e_0?O18fvL%g~i;`(@R9)P-ZCmUqjx;KX}ZZ{wL z%LTfzN3`;NG9gfF?tvQB&h=r8m{+hMQpW%MmT_!NIu~$kJ^!n$)Xj3&cXadJou{6A z>E1-X3}?BuaBM?9T#jxgIau-5sh-1v7O!e<#N)(wcAS>lt_Vu*A&2kO+a-sG zSDnNszAd`HcPP|8$}2!pSbD_d!k5^V)F2S#7});ICZMQ>HQ6*^E|Eyb@kqi;&BjZ` zQ-Kl|9j<&kL@Dr59_`Exw~Dsb2%D94expz}dUwzqA;o6;U1A_}HU|#LO1wgQ_QQ_T zl;L1z3#=MjV8g~~yE2GEo;JKMxjEC35k!l>-6@%HftbkoMbYL+`AktMOEzGBzn=_u z<;|P)JNzb%1n-5RzKFLGJ>SYYjP6{bz+>gK^!}rkZ26M>HFYD&6;E(^HMSBoF9N;7 z{LYBsL$t#m$ySHIrLrU8WRK75O)G=&fk<}$yxG9je*U?KO~2>mlQ$kn2xfCT;KsA2 z#(8JX6mAO#P(;|!vvgnLW@N}I6sbL=BGR9-R*U|u$?QSH1nb7}RA*0BjeEbPMT)6p zM|N8g=N`dF@x(luf%iAsNfyYaluou2PwPzI4CS|_^b~7^F3c&JGJsS-nvPlJvOod! zfpw1wb)EQb;JsX$QOk9%@_w$^| z$PvD{X3~%ai-8Ddmh=bAqjJ;88vC`C+olWE-R6%s^6&&D7xQGTl1C=*PJs>y%HG9$ z+=kd(kZrVLs)0EK!yE-3J%35!5L+PLPV${wZ;wAdq_cHvu=9gwx^k2~MKj59mdsxd zOH-L!?a!LEdi$H0O4kb3(s7JbLZvsubrz%hh~NvEI|O8*v;$rKq{V5P2ou#qi|#e~ z1_Fa>1Y!O|C}<#T?E{;iVE6AfPsKhw2hX@|O=8G}T~kcz%K>@%>h2SVjwBpa!jDH? zrs=ZM$K^WLp_{GyPSSe^zp}7rjpF?5*d!MNw%41t9>qcov&YNZit~wxlAhCE>PErH z_)N@)<3o7A>6V(ptMsMQkA*5@CwPWocn8HXiA9H7qC6>NB`)SlX&4)?Y*cZ06cY3d zxW68k95u$@aFyp+^zt6zc%#M+x7=ZidD)-;{I6z3<_+HjJ=GZaz>J_Ch-$X5_{_>- zy2pi~A9UL!iL(s&;n_*AL!h&VL2JEMq|s)E@oV5{eMXXjI6R7PKxe8DPm-baB5|_G zyx}tO$|qi|L#M(x9nQ%jYostvU48i~z`#sEbU!6n7zzpj#?Oz0GSaMPi&`3WHm*rF zD?^uxKI=!Ws}+T4`WNq?7Es}KePH+gKLb;j?{CrSVa>X@FxF~LSa**+c)EZROwR5d z5bIxw0P1^=H*vUV(z>^uO6mL6HTjdi^+^IX5H@?%XAX8|GMwvknMU3s!fl$4lb@5d zxIZwfpQ%N-UZ$`!YE5+u)qD)6AbB5&d<=M?j>`M_5aM&C{E6=+7AuNrBF0_Ff=u5R zhn^jr+VMKN%0D*sKu=jcZPr2`BzM^Y_XhiyL6IQUzkn#^X14#EQv4?h83^o+te|*! z{%^RG;lE@%-2A^q8h7;>{06EhmFNaE3A*0@iZllPe?=O-W+b!AyBw2+;rCk1SW#ah zz9kij!|8%>`10xL%l7OggHYvzRR<@J0AB(R`UyVE=Yv2H!3;ej)tCPb5P&xRE=c(+Fx>7RHeb%~RcTst z%MNsc0ZSOW*aawsS=fplBN(`bR`8UZG9qR%n|}EFzJ&jl4!Z^eru)$A(CH$7^yKd$ zcJS&2$I+NV0{6zG86#!uDaiq86g$Sh*9WtcD~~T8ff7hy>Roz3se^kNQ-Z=Yp}-|+ zd)uHAHbyI0JOLeFhEMty)JNt#$y!_+SQCS&cLZ~MMiL8{_~7Qpz+}`4eSwx&KZewb zIF;=_h6D>q?#eHv!M_NWeO(AYdINV5l^5d1ymP{8P>I((tw*MQ`c6d=|HphJZEcaN zJB75WMj?Q;yWx~-B7RMwk)|QqcgEeoMz5ASJ@H9A27BSZ5ES8WCh3xv?+wf2X?m|F{}1Vk@Xo#_rLZ?nBhm&nawlwOX{O|5`iD$l2B-XquG zS6!uk=RWQ`uS>ykxZ-A(*y_YnVq?s zmN%IR|Km#{BvBL90bXOhazwyOcp^CaS;78!Q@R|^CDr`&^-Mce#ZC^TmqH$a6B~OAu%JgA>ocy)_yCNEC&NPG=2-(R4S|K@NlN zY!{pz9#c8OZQ;?2`*a74to{EA1d~J$c2ZEznHA;Wi=!wvWLZF6Co&+!Pk1$mmia6a zY;kQ_j7t7!F0{KU=_DVE?7s+D)I2fNs*P8+!J`2}XCoIkfRdwT07I9aA&mB2|0}Br zr4R3Ej_TvS8Z3hVET@Q-v zK9;TH9jFbVi134JZ8PpiZf*i_N?+unOMLvsE5))4MZ`Yq2b{RvM~J|Z5#t*n>x^!87pgM?3sNbS{j!{ zHD0-tPVF7t9GsO{Ac#3Vks|v?^zvl41e9~@`LxsK$)Pn(Ru)@2x2^-Vch;`1>(tt_96AeN4+>kanyb;)DTJ%5e@jW$-o*mVvk|p%KJWC~ zdPi~CYOZ#71lk$pmOuxq`u(xf(@9lo;-x&RO!}+HMJsx8trK1qb$jPYISH##o+dF_ zecky&-k!=IWo_o$e53xND`@-wqvxuA=4RLYa#tU2{KD9L2$Y(P~mIc`G4ZSrv2u<228l@Lc9@QPb zD@8O7%pL0Hfzi6jqja?`G~*1(gZu5}xuZ#nK^Yv)JHamA@y*R?pDm8r7fjvWb;pgm z>B~ZNj@@WA?>fw7yZAKLEf=J@wm@_N_N89Q8X`b5;Y$wiE?)2qImaSWr?VEp`Wzw@ z`T-<#_@Y29NRW(+8}?e!SxLG%GwX+&b9z56)SMHtY_9jel~GymLt3>0q>~-;<=N)V zYfwxp@ld9z*6pd358KeZHwQ!NJYC0{OyU#9UNK0MP{7aSu-@m-}eM z&o*LXD{84^u0vZXty6>?1B^~YE=8|ruN)7Mq)BH_o&qo38%8jmPO9+zEcqI|tK(wJ z%&L7p$+L}1k1X65axTG@rdeq@&uNwN)T};49cNN;>0IVoxwPOtdY-t-nYXjAIZFZb9=S_jjSqS@ngZJke;7-C5 zIti@SGUq>kq>DX&7e9Wfi1au!u9j5kxx-U`dGiH6iia1_Ib;Dhz<2Pn0P$4%*^3L# zgJ$Os;jXmtecuf}i-c_z2o~_p@AJ#29GY<{1ltd`{MY5P?dx4#W}FlTHkWk{0OZad zzuSEn7;z0WZV^O5cmA)-o}0fzr7AjixqxR>Si%|>GbDU0Uo0bLA-p|+9ZewD-KA3+n$!wN30R6oIVM&7oVKEGg z=A}tUNm9Pw;{1N-Ym{~5WNn`*KRMQVQ5Xg20z$Hxo-t(u#VAFVjuTgkv3^UETZy%D zZNY0y^y{aFF6-Zi1%8c8E5_sW%ixR1=ur41ONl98$qgma+PQkIlJk%vjM!84RNJW9 zMLyw2(B9b4(j)&{#;qf1` zF0B`x5YM&7YaiN>~#A(QxN ziZVcaY0Zy+H?nM4cZ_mkTs=%w^5q-n>uiu_tOdbn6uk9;%uX!1M$@QfDgVGm>2Rh& zP)^F8O-h(owm?9U8{wne;$If6G{FmmEt59lnCz{5cEc`7q%@j?47fEAQ+VS~%naKe zNyhiUj5(SOh+)jM>_!~PZZN~Cbj#Fn-AZW17kGP^1nh=yNSAqIkJBi&AvYx{dJy@4 ze)z}S)PUW`+{k=|ZP=wCFP=gF_*t160$i9SSBP~^Q%7o*9${Ijs#}Q zZAD;Sv6RXwv39U&S=H-I5{64gV_jCQzOFpBWc?|RR;^Up%;oCOi|RES=v-n^ zYu0i?sAkdFb0QGOQ=n7H4K;mEyLJV3B5mUl0uNY{p_;;D3b_*(CLI76Ee)kBYz*lE zX-8Sp5-fx#0x_B6!PPQgd=lfulNZkBLPtW9jh3nZn~RpYX{EI!hq2}fI5PrLPe6v} zR4T)|mz!boG2Bw&iI_t|s%eI4Yhwna)pY^hPwNTyDMBR!Y$07OO=#Q7RRd;1o(C3folIg}u_!4_ zYy<5GlYu@KpcbnV^t< za-#9i2rtDfDoYR7%JaIWjlB36Yd!?KB9f^20kIv%Ua|yewIYh$wMvrq!PWr^0f-{Ri8>Z5Aly7A>q*eEkJ_MQ*JO5q7?bh8$7uZ=?fafxDcU&S?^6vAe2?N} z#w=We{52yhpqaq`f_8#(eZc+fzXl)d`}i`$VPC*OL@jOF5AXy8Q6^T{KY(<0n<4Rp z1TycKFd@B;;7~)h9CLylKixkFh5-?v5N{kpN$I!c&aTjei;UPUPDWa7MkFE0Xoh7s zaVaEzDT+FSttlaD1X^=a&t!5yQ5Xeo`8mhvXCyrG?)xOb9Hs-E58+Dbe~}|*&D30| zzd+6{tq+FZAeZ|A`3$uI<}$JSBsk?Unem?lFX8qW7RPHTPRCRCO8&SL8Cm}V z2B$on{?8MV^*^}8|2t=^csiKU%NtoKyV%mp5il|^(2H3*IlKJli}U{u;cWk9PI2`= zge7*Qe}pB${k|u@jA_iI;e$ek1h#ZNKy-8xN(c8a#WzvAZD(5HwCL^reshXi5^*_O z^BaO_f;9{G2~4NmaFsem9f!`b!++!`F4-4M97nK(6-Oola&+bmWG6}#UY1fOZG4A{09RU|$Vl1Z zirNfoLo^^}$BKg0yH1!CMb81!%vL~Yu4pq4n;GM6(+EQN5g-e?0fkj1m$6N|BtaFf z8N=Q0dKlEu!hq3=Kn4rupV@O_jP5Bk zLxu$~CrD^(0piGDSvWvU*LWDzeBu6OUyAt5^6QqzW+uK&xE;jf7j*r zkt(iVCNNzQg>HJ2j}+Y8foOVrGV({@r9(rHKRL(LF@dBWjdzUi zIa7wOLxvyiJMhcy%eSSUWf{&eoMar`K;yu+KUcfEV{EKsw`I`JE-TBXFQ?eaShzg% z*VHRqst<(s2XnQqF7#^4`7`t7=?3R#?EIU*_Pg_E>g)bjUHbE9clL4LlTWX=?b&*F8sK&d%urXKg1?%+`&t4dvsk#(HD;Dmm%`;@l?5kE^`raCpCFhNt{|8XGg^t zkBgQ(7j@?3JM)i^(U0%%$6ei7vhwzFr~NYXew}$U^^80EFU&W$(t~){K0T1}sUkIf z1D8b+<{`*shsB_|M0k8A(ntV)QWnuKo@66d95r zgPF88%t)8-I`{{d#Pb9)Iu>u-M_VI8BZC6gLlePtgZoqBLujFP}3(;tLL$K zM!T&&*7AHK;fob`sSt2~RfcWH?G8y@7WvaNTy9TL^F@!2|3sL98ahz>&mm78D69Xa z@muXU{Y&K=_q*Ek(!b=by@*#KT@ZqIP946a4p&-_Bc;!ovKycN@9{fbn%DWrWQD1x zO91nvQu{%Z-{=x?xKr~dY8Nf+&lP7hpDisysADVygQX3|$e1l8dx`Foe8H(v48|&d z<|t6-v~x}bD(sV#=yIaNz@2Kap;LWsd+)6^M+n39%^mY|bKaPs&()Q1a8t=AsWgKh z>=ps(w=X4=np^vX>I=Im!Q#}1AfXiY&M>Y}%@;tY`b4;jii{XhQhp~vRuF*_#2jUF z7U%+I#hVk2`V*CA-p|As?Wg$24iLtKGoSqi6&!9+9Y+4rIBnVVuObsCjM;MN%uq-thO`(dP z#PR{!TGNF>G(96fK(gXg3XXVU;aX2>;o939Oe-!zEtAU4viQyN_$GN-tNj0A?44pn z3D>3JvDRRXZQHhOduEMo+qP}nwr$(C{mnl4lmFuEi___=PA8po`c2ncRZo=^C7d}j zgkeg5J24m-JmmwLCo&TnvmzAm2568T9A?$MLagi^S-lu+IMeS~e>3!Mnml6VfRn!A zqY;*7ZnAg->}9%I=y4$?KBf$XR}pptZ||F&+95P_c<8w1Y1JuH>QlgRE zJB>X63p6y)xD&VO&N)f=LY)FK_1G#sU{k#Vw!Y1MV+>z=?U6VzB@#=33&cgsvg2iO zL*g2(%X7qj0`rz|DCZ8t1H4sEC8=}-Ca~$0kgS>Ip}kKEC{4V0rs&=U85=UVOKd&> zr>Y=oh*>fXQZi+?mG5!mLo3vo>ncRvehsiCJ{fYjkzjcl zO?^l4-8lWk364kwTmsZj>gyG1zjhF|M*x^V1;X4HBBDA8v>f5loluRcN8}v$kn1XB zE#nNwM}SQKEarDB#;(%3OvmLMI!ZP|82lb&3dD9QatmwnWyyjd3Q~wH$nlyE6mqno z<}C56t?<*S2jy1%^X5`!+*%`;!;L&W@VH zW9_mXW~Pe3%ndN7(K<F8Eo} z_i(p+q?hS`PL5AU9N`X=j?8JgS7^}CWr=y`mz8$1nJZT!Q^}BJ?5)G5;W(@aO;*}M zQpf>G_QS$t(dU139+kvA9ccDMHmm|FZE{LE<80~Wd0RtJ!Xe9xONccSZ9>i<%;EMl z7F%00%-lolrpwMV6a;s8AL>fA1Syv$ve`x-EdZI9VD5&A%*X^}ZmZPjD*W9IG-Z?< z*q3&h!Yu=*q#RK?5`F>9dJhs%&mO)M_nQj2P&Rm&F9;QG0d`{eapL%Ah!TAashI~7 zP|29#hbPGb)Z6!|PA;G*kCuLZfX~)f8~!(LWuasK-^>mJGxPtE+0kT= zp=yJfK2d$dMN`ig!{#gSWBoElu{|C#3?>}tm;>AX!A+&WE-ILQX*WRx=VsPcMjDC< z5tFB;?a@6vN=a#%N$K%2?Nr+nQ*ZVBc9#E-L`3{noEM=ifmTJ6QMmV^N9v;7*N zU_OOA@x$3Yf2B-0VngOFc!yYIU4w$WGe^_qaxx>@Y3|_xGgIub*VfjRA1~$x(p_@; zTr<h+-U;~=EctWw^>EZfYjplw;o(DX7!-egf5WTO53EEK`Gg9vhphAcIdjyK z;`3Nwth40=G)|8pfFZaD04nmgErMRd)PhlN6bLUMkP4bX&v5={Z(FnzL7e;z{hh3o z52ya~?cqhzOtFPBtLSR95Q?xbWl%T@+XQ7+<=-#oAJ zY6sRi5NQt|6Mw8W=w_Xi?7<=Q24IJ@Th`n=_(hYh> z^WXeAQJ>xF7^wd=T)W5_QPal(f$mG58Ea4AwEntwp+7xKW zXXxNkbkd#^Tmy>D9Zud6y{wElyE$$oglKX}I=+;->4W`CyP$hy;fPD%hgcvN2QdqU z1b+>*3tV`f( zva#fm>>&ye;frPv<_cydmb&BR;Sj)j(q_fg^+bwIM^*9h4819gqukW{V$6(a!@Eco z5OuSHid@{R%;P@sO*Pw&G&7*_B8C`6f%4QlC(SU(eO=e+)ZtUoW83gG< zOVn)@o)B2kw_DKQ*2|>&UYKHKhH{tf-I?OEft!Z1C*b%Xu>zYyyoua-so4Yn;ZEVb zjR+Eh#|q5()=Wn`PW$1Z{auxR4>htY%t@uqlk**+SdOruQfpQ%EX}^(%nC9!n?w-IA?l%Q;qws+XrtVKGBoV`j7v4bW->*CjvqC zoFLakSP3F6Cp+={H9OQEz3RnGFw2byR}|u*Bcm5_pgH{On~PFgd?P&Tah5&@ESBJO zOfQo@tC#lz!oHb>SrizfBi_m5qhpv;re|3=KJ?VLY;_Lm6_r3uLA0QYY-#Kgsu+up zShDh-R!OU*5Uw@!TCH+w7)$B5VD@VgF|B$>52|azrsgbABV5Mku5N%Vp~g~;mQR=@96=h2Ls+eAOC%JKSHEKmXRz%d8%12+o$a1Gaf6p&AUrghu z8JUd4H3T7GRP!_GTKbbm?~)%DIh;!^TwZj1c#lc(C+rz}Xf&|yQ1>fmV1TETcg~TZ z1Cu%ksm`S_`8GPM5b?@z1-oxv2_S0pbJta3?NwZRvn9r?bZ`Rkosv;CyZZn!-@G<- ziBi&?{gfLrP`LCqRPmLn1I)-)jbV8%Wnq*k0co@#&-YF3;?hsJH?y8^{p&iDIPGQr z(ouJ)J)fyOgEjQ+Q2ylPv>M;g3$G=Wwg#0Q14&t699lp3p&NfcSk)pZk8+zsz6cK`f%GECU6=n7n=`g1aoV}v0q>ko zM!r{hQ3gwn19GZA47dJWiNCGT89$@!S=6r#o}#061`c6{Dli=2b<7Td_)PpVI5y`+$3SCM=lu_fW{ldYM>nm{OHip04G z@d`-V2x$9))jNUnx)0XNup6Nh>b|MwL)Lksi1_2Mezlz}q{7Gp1D4Sel|fKHv?obRPVGBgXKvJ=l!03^1$YT`; zYJ%*mGGR{C&51qnSWtP+4Cv}Zn*u8k76rFvK4X!I5ovAAb zw*wlmN^NFFl>rFRMN76MELWepn3nwSCr;RPyL5%c&nd3uUux)+Fq2vZpKM0kj9boB`#pYV!!}*&zy{?^IOoKW4C=gXb;Axt zs#=#gT(W_<emH zvs5dPKRNHUqF!KU-L4o9$`(C~D>|{1Ij7Y#bSW}2$et(mhIJmu)u&(AcQNkKrxe?- z-V2UZuxff|rbpiMm*h3+Qac^}t1U9%di9IiJ{0o`TNB}q&#P;uW&akfijsDmOJfZd z0OG3B3KZY1SVpJP>9KBr(1tx0$0a(YwC`Ba4iR|mFu| zM*@l;+H;QLO2aG{*yLbCV4HnfWMOFe{pi@~=)qX(B>vBGwtH2+sD$@c$qp#NVOCj%49|1C>p33Du(vgM9PcaE2iDTRW@7f+AL<`H1Wa*}$K zJk;SH|NBQU+=F#(tB}jy68G_O@S0+|``2gmL*@DQZU5o!fDJh+U>E-KCbZT(=liYpxULIJ)3etst8uoWZ71&=TQTnE9 z;RL5Asjd6nM1P8RWkvNb7M(%u_s9Fp46d##0gDeRRFT2@xiF?)Agv-=?hsf#9{@vb zalk7IZ#Z6`Pbh2ah>g%pg&gaT55I*_ilZuszhK5P1Xvg^o{row^JgfRMYpVYF*fyq z464Lr>ND6sz7Bse6E#*lYA(q~_f(U6;CRSEfh_EY1-{5v_@v_6Z=ENFN9MzmOz^Ta zBsnsB100Od!GITdJa@XQ9HX2w`D^n@;<@adxVtWOw?ET`@1&U;dMD^R37tyh+CDE;lfz7z_%nPt_L1C1LKbhwA!W3bK*{Iw zt^I7l`FdM?!s|hPk%liqfF=DEnr4u#l=z&0Cx6#a5GDq!1k$1sef#rO4f*SPd7Es{ zD@uc#IOZ~M+)yGeD-cCt<3%a*O9@AV>_fcE^Ivm@8Aw@W&t3EJyrKfCDvm59*42si zkcMC_xLfIP6<1KPCBs>@LK-P_fv3X=q!I@{ z(p(LwP(pIX6pC+@6pc+k?WOQGWABN~lk@ov{rI8Y=p@Dz@03}a%@}7$HbkM`ftMFn zlOScvA}?-v2mZUNhM>r#o%P4I=v3nVC@N`rc!RP+HR)WU2) z%S&EC;-BtiJ->^H7(zF(+DOTTUmkNRuS$N934&TFJT;3c(irxUgkqEcCR7LYa@Pu( zmPIQ~GHXRh94xF5BCYjUoQFS~h%l|ahvVseFZx-@<`k`|Bm-wcg>rH=gM6@#d9YfC zTrb#0b9bx0cqDdx4-EK+twjK-5P3rYu=3CrX^1GHyx_Gnt?cV<`MUmV*d^2$ULsIV zs<2Q6;{(N3^P%`q4NR8?%5FC@T*LZ&nUj834jQU-5U1g@9}!Em!cu$Qd)!z#dU#_bB_9KL2tfJYEl=z(#{>9nqw z4PA-SA3X-N_zjoHpRc9$6PMe0Sp+gt-AZ=4ScGL=Z+8cbg(9uCIw-wSK8ku*QDC^` zBruYVbX9S3)O?OXE{n{hGC3X0dQexL!tclVJW*;y?O4di@!xP*hz7E*BMX`_LkvB% zH29lp!fMKVeSNs!9Cl2`9G`W~bOyE$8fo4T5;<29AXx+D964Ezd)k8)@>BmmA5E^E z_ZmE~a5e*(F zf*z)Hqxv|{ZU%ptl7hv3e5nr=&xzg^Im~cJ3f$$2o!w@F(%cT2| z(r}p=s$87BvtPg5nguqAZypsE7lTUY_||jEHPuCH+40}^$dlZy^==hLuJ2a@Z%Oxv_^ogcSsRuFq?d}h=$k|xs& zR_W!36jKHRt?m~8(2w+K#XB(D3b&ng>i=CNH@CBtiv+uVtXHfDFa2TTc8r$ySh8Zb+$`#my>a}*UPU7z zQ`>R%i!+mqPC3LVSn4Mm5QBAFr+M*~MYHbSI9wKyGn^=CDx`|$Np-DQ-d1g3I>_T4 z>kVhwxsEhrmPB$d7jTR+ltorK0aUGNNw05-X__ReWYe2op7iu~fJ@OGRbVb=n4|Pm zJqAXU_4j6ZnNyDK`JRx*`Hn_)iX*}453~ghdncXB@$83VYEy}=|751MZ|An&Mo_nW zS^zcytpplkx)yotygizrj70|K0S< zK>u6+`#;C8xdEPq5%=Mrk6DI>dLr!O{SGT`PV7N(s?XvaO#pPD~y`BLwn@ITP?q57;B2Idkv3$ zFuvaCl2$+wa3=t^!3OogP>U@bY>GHNQ=e72d5oL{ zV6Z-R^U+z4t-OQTY5G1GyCPIm?jHRNBWmgrT3=W4GKsuZebQ#VIO1S;Hi_+ zLT6}ZtS(U~6xCS&CNjD7extWTF9>`bEjyw+m!xK=vr35zW=J!Ck#x4|A!{qLg-FlI z@88>REmwr{so*N1s%f#vKSc&c=YFl37n)<`BrX~YrKqAtY}YI$z(AoS4zoX&L{H-OyfzO zNL65H;hK4ee0RbcRJ%TGnvwDc$=MP;hD z@-Rmx0p}6D1TMx3vm2W2CrE`5s1IG1v~j0@&?;Xpoi#rLwNuV84G|>EFr-m3rW~&? zat?tJucnLTHL_81;}q2m(r^~A8%8&SYa2F<)ytfwR(rsT5fqgta`=R_)HMn6o*`NE zeCiO_bQwAJ=SN_ZF86g!$%-!wJ6$CTHC&209^SuMSCs8*Xfz{Aqa>~vcgvNHGty=( zNUbSsRF}x>IHGWz%WY_Hirnkv@lieo}fs1=5)()h3+=kUlOiZAOlD=JHvExKYR z{PN^AqcP*iNiptUL>N?VhUJ-kUS!fb*5_hf2W1|gTUd5cFv9_E_(V`8_JJb=OUf_2 zlKotDJ}@VOEzU%18eaKYpC-fA$Pi_*DmTdxu22N{!@H00VW-KxQ)Sj842W_$ zv{={Z=H1}&?M&Xhg7_IamiU#s0dL^dZo$AvYGX#P!j47g%*uJ(m61)q1pIG9(H8n) z+bD$WrUeJauSSrr@qvH~NY7O8z*QILM-~rS2~l55pYSV3yj*;*94pHu4z7yPc4Oj; zx1T4GzF%Uh4o3O8^|Bt6MU6My^5gQdJ zoo*ymogxljGFlPvXgrh{jP4E%F4Q(!Tgye0p3mhX>4ma5H6N!pR1Iexdb^SJk_1TV zU3al+P0$~htwQ4;XWYX20`|O;4!vQ{Rq~f&D$yh$UqwdZEUtbN@!-h&Z-@D!6Y-JB zD7@I?k~FG?Sa)bgs!^zxTd2#^NWO~f0zYQ1{Y9`R__$2BX2ru4tJ4DgADx+NNUtQ5 zmlCe?HSQ*pz8PkH`lw1*|47%^{R$Uu{iCkXZNz$Tu4rl1R5y}&5;kp386)yd?bO|A zWOD66xjk>_CKVay{RIBSW1cVanB3AOBlmE)zEX)NuThdncX#D&tRT6j+r)adFHHQ! zC#B@9XBo#OaQ+edV+!NMAT0sv#1l4S^$s)>r!SmnIhCgpS@^{lD2*O$BsmzZVAq2Q5!@E2Oz>F2qy^T2$5-R8-*?_7F-sN3#10Lr+- zHb*G6B7tKUQ1(>5^2rieT~)0*8V?&jzFQwHXVPs$(+)Cuoy;R-NTJ40o3B{luOx$E z7|RySK^Qx4M!C9)hUxAb8@^al=XsIyu+1+``>CNJsUmy{|S;@X-LOx{QA^CR8Qfk1nq-$ zd;5FW)oEun1GtWnSOp|_gaJ`>XkM&uN44{ex7izT2@{L zctifRgA_MnHZn-r(tkdE?PAK26-Qwf8p`b69^C9*?7cWIa;ZL``_>179cWN814@_| zCt^2(fejnxCLUmoK@yoDvDXl3hj%9ooI6+^fE02FlcLYt9?itq2s)fhXgANT_hn(qs7xMGxU{O$b?( zcE=w$KY0%rI8X2KFOEbNo*!g$09a{Z%E59-Q7l#I=%k>oah}!jC`0Bfc#Ie8MHtDp|FCL`F<kUFJd>QG8M%&Hmi^Ihm zXUO5;+#*pny@r8GLv*QB^AMb&QefQUMJ<>Z;bodDR6oc_X?FTvYGrl|x*qw`YJK=(rH>?NGIeF8b<-3kU>fCxw-TTTtp~T_(@xgm%mAHUs@?l)*h=F) zAXTQPVCM;c;0(ol)&zDpFw#i{Se?4-JSp+c>rHNP!k}Xp)H``Bg|E(n6wRxSvBaa>%;T&8N#hxgArA)CnG_ zOVQqSOU#7KPKxuo5u&o;k5zlDX#+a{twgVX4JFlCYNPdZ3rsHnMR+P~8lB5hxN{-@ zOu@hO=pl6|cWT2cLV9sfuWQP*$|Fxl}WGRKlsuTbGZz?nUtA zP#VvN-(4J7aRtROV6IYUxj4#_x1H)t7GrQvuts20N%x_w+;$8&_8}}?Xo$N+sPc?T zMPd<@3tT=Xpc6L}JLyiSr>QVH1+yEwAx;SO`acDxxXdq!}aGY96E=imTpjcb4<@`dA-(DCP`y z_9q@Nf1}yn$4W|Knzt@Y01_bDB|m1rW`OPY%Li|^ zBmDDkxh%JM6(O->MInJdNnCsoW7r_rQO8&hp=$8G6dU~n^WmN01Gg`g8wTOQnSC_S zNX?asr{%+}tC6nSAe?c%ou#LUT6N9Q*54eX_|&#yRSI&|LRke8ZcFv?SY=pG)*o6_ zOzQpo=z+8;Nq9J@8it^8#mXed-`=WdpS z2Yy`s*V{#mqRYw1OEHR2O=Xde+$#p}ADd-~#*(CHrdYVIXt+6gm_7~lk+9+YddjWP7>*hQ7K~pbS{Gnp5r1B2h{jd@u6{|7n~lx<1D){iTf5}LTt_Krp|A`aLscssnEz``ikB);CLm0G@bvlcdD}>Df)GreOo5MOJEOa zV;<6-Znutr#b;3U;teFjgbyVb@R|p@x%}B#Zn{#_NN5h8CDRJe>P9MMiK$rs+nMBv z@*Mwl#Wp46d+srY6SV+=ly}jFhuUT*Q4qE9#BTYIJ%T_Tt@SKg5FyhkTVTJowSg7a z%vKIg!y;;=NMxS=5?yYNuM%!mfkfP&1g}}%#-*36UzkIbLsq+M!iz^hlBA}MQ=~VY zEEum;7Veol2_@OrVFDgm8Y$gwP&1)45F%vll{RW0?y;}; zqC`b*sgHIs!vE;E#rl>{%}vu!2xy~HSK#a$eJE&{`y~6|Ty_->I{(%8a4>W=7kU_B z50PEfWn9SiXOh9(L9kaPE#BG=nvFurcB0!|C&x>pnMEqAWPlT9N1p=@E_B@i3@%L6 zM!2^3@#5a0A>|ObRW^ZS^;Acm#g6-4KBXc&w@pGA?lK+ek&o%7TTDCc3@?R987iW*aY$3VMC2gLQ z4Qi>-!=8Gf3&`m(&C8=bYqPYopY8iU27E!o=Cg}~BfgUL6z8Yc9U1F8DQ`4r7x?!v zC%`%A*55x9FH6yNWeJ+cAB8J;3A1 z;X75|RB#s1QYiH6uYue@aBdFJwQ=dq&DZ8l$hT=dk7MZVGd%U z52LG6PC^ePzbke_&5UC@u+V{~ebC+v4BY9)U(5$gh^wLj*d1zyjHf^Tz^SKCp+)<mmzsuQkyZYtx9$ ziTgw!R_6*0;V$rVO$yFAHKbcQqq|d?fpjg{ay??!Ss>4+EhA2-OC8w$)K(U0?6Y`^ z7Fk{JqAtyZ6DZc3B+S&U=8q`fakdTkH=)ymP6BXNyqs?e?v)=vwe_~H|ALHl}> z5Cc8q|1G}pNMkJe;D5&HU%}J&RJ4490XG(K@LHhXQ4Wy|kC{Rye{dDFgi(my;yOsh zV9h(o>(rjiY13}HuU@Yo7VfUjQX1wtC$JzWU2Jq+fNX3(DcNW+R@L!S<^R1rd%b-8 zIho&e8kBUXM$$p);rtBzYCwR^`TH8!%PDY~Q-#u+ujPFmxWev5(cuI8vaiu<^E{(r z3ljuX9X9YC)1sT>YMjhy)4y`d|Ks81@%~X(PlF76;3DEm(zO2d_C>xq3zS;dI+-S{ z?(^C7@&1Tev<`G2=RO<-c+%^`OLFU@1&$Pn zTOgN|E}}zy3C&g<8zcq8I zOcs~NDVL%(mRr8zW*ZF2UW<1e^O8wkaT0x#C#F(3Xa8uSad6@$*JPxzR-O-_^;RtV!ul_azNrycGcR=&WLj$^BCy%)t&-tssL zw-uh;Tew3$D58Q+1z#-`J{NBc91m_#u6$vVAK%i4+#N*giH_H+l8SQ(3q*LEg)+d(J4u7DWEtB2y~1V zHv@CH@E1DPuNKj$#Bz88t)`5v6?hPf}Q6uPC|DEt(HELROJD?5NB>o z=2#hX)p?-eA2WV)jaDh~H}CYIFd=D-2%suRu%O1&F1`%tLSn>dq+K#g`MU^a!Es3d zfl_-~UNH&;r#!${HRv21Ngi?>4!@Olx}FM=e=@oKcJCHNk+L--1o;m+IFKI z`3k!p_-3)n*Ll+JBi9tzVzW#KUXT1ld4k4y(-R~HfQ@jL5{$V8?WD_(#ed4W@PJqS>PvQc+04%L~0C^226 zK3OVDg-wRmN_EuhRm`B|fioSx4gecbUm&DLa^)97zZkvwJyZM<+Sr<=s_Dn+XCMB}0x+G}hb zDl14vkhfiftf(C8#dy{P+Ww3zivL6IXyvsU;y=3*YjG&n z4N5FRZFEpnj$SG_4B(^uvO0qpg@r6~@3hz^>f(=>1ICT9xE<#TyqES=kWKnjW{hJR z!xMTl6ST;mb?h6n&_pZ?x!!2bdUc0(=%qR)us@EnrVR=OeZ)dWWK$|6k)Zq{Z(66A zDOoPzs<>!T{wbGjE2h9-ikEWDhVoAHo=*h{LCAI6KSC-sG#ogW$X4A=gM<}$6f@UI zvmm9DmYG+Sl8Z>IA_=@LO_#Q4OBmHmypn8YuuaVZ)}oWCPL0#PQ;=~Ri5JgL!>F+# zOEZm622*=Th>DS(*DLSyA6b?KUsgBlT_;vW*91OJ=Z@HQgm?avaqM;aA z$1tXU6zl>PvI%g$T|EX}eahnHP#9u!Pbr7=Z>F6PgNyBjI4$a|exPeR8zoR)8aO=} z=@P32AJBR#c3kIQd%%J0Ve|M)_Yn|Etapb8iJSB^kk+PZH30Y0r!BpOBeNvuiiBVe zBej9j>;iy-wI1VV`C~<+No}y!g~Z5v=BfVme-z2EIo0XB5PN7LIZEqV<^LusKJ9tk z{$=qR7HDLWLLlpoI}xxnh17dAHl%nrdfL?a(fB^U`)UxLi0+arii}*UbSJtGRxJ_I zY+H=(oSgU zek0`*bElg6q4`6#`7rbJRRuz$tmAjxclI4pVq@)!&@2}0Pkx1BMO5GvZb%ddL>rVx zDXyw8hpizAZ&NhiWt(LLBP#|Zd@rGSy)H(2rrLb-uls%msnYY%pv%9|<%r!5^^RKh zrfot|9sX=w7#p3!!fsD$J_lKXswZxFqhqIwFh-sE9*tw7H*A|``<-G8v5-r3MO@KW z#yG(+n5dxzWLuCvphqi82&@Xb2~`1s2@%X4kX$Ywa`d`CK3~AB;!Kq@dJcMk6j3qp zuY5Y7YMP=POhSONiWQb2`Dc^d( z^>o>Imy8GIM~=(Z(nd+fkM+E!JR4=;(Fh#tw;#w*qun0@2fUOWZ=LO(&n{hN_PQS! zI#hxniz+2d@^o?|)G1;{Yw2_obZ^6_(;dM9MJ;)@JBRwD!-;oUF~8$!7mHj30XlN! z8UVTCfed}q0>EI;0tOlQhx}f24}+F|Ls1J!WRXZaEh}g(I%mX9=IUW&2I~){s@p75 zX}qudMkw6<7nKzWptN{(?n1mUnHV!BFjBu{^sNf)#6jiSz_O0EQlbXf59RROVl>+V zZ@GQ?H1QhWhU6h%4VJ26L@KNBO}>38A08(E#?eT4Ov*-Nqn3EKDJ)`pQJ6GR;zz1o zBom8O@J6t^+h(Xxk_mB2^`r|&;+&WQVOV~aS;}LkYzAUEg90X46$iK4VAgXqi1oWe z(T?RR=D7MF#8}U#QaiiE%~GQUSG7Jq^ZRf^0G8j9 zlR#x|`Z9d#FFAYgVIRY%$5;UX2Lug-PiJd{ved@vrJEJql44XSw2^6&o|!c{BYPls z#{0Gy(4t1C`l5G(>CkuazwV+rZm<&nMkGB@CJo&DdIMcmE|3~7ZAltJ zVNMdW8Am~^#H1G@JhiuS0sZ!pKQvg3gGD5umn7sA%qC&uz(YGU)P+PVm1-`HjsT1F zz}&07@sh|`#4Hfo!MK!Oa&IsksawsUtVx8nhh!KBr|ZPA(-up(p7I*|h1)`vzH*D$ zMulJ(&&IGx5dRkPROgM&mRzB|n=%0R^Q6O#GQ=J7`W2qtmbDp=m)_z~JYs*p@ZKJg zy1z!@-e+omqw0L|Y4b9F1%H3s9N{irhlqHCv)<=7b>5s%K%IZp5wcSW2)M&*oBY)1 z?)Wc<42dNK5j8i04~70yn=Q~0YlYrsE9yX?^|e_N7^?gLDCtty+*Y3N8MF=&72Fe= zIhx;!Miy7lm)XETwKmFSnk>DL5$b$p?oG?&xHIc2oA1a2eb(4>hg4$3c29M3)fT>&1&KZ z8JYt?OiY8B>f};Tl$||yUcH2&J7fW+{=JY-XjF=dkgV~{^b9jWSn}ejhgT5KP!TOw z5Oo=T(8_Q^?4>|7?USL(p1T|-Qk91ug$+l$=mhUa(;-oF`{cPE2IB3*irnlYO&PJn z?q}ty%l53OM5lh_<}cwyL)c|G{53b7fOW$q549^y*z-47+#Kg!p;y_OtZqFL(#50p zr3VCYLA-A`t>wVEbAWeid#5VMQ1vIM^Z=z)wxS4#4ykH+Khag>4{0o!&5|7A&8ZR@ zgC4gtrrKRq+)X|+c=w;&i3k%bgD-~$>+Nq|+%x@f9EOyk)@=g~d>D-Tykxq|ELB^q zOXHEhG2!Io7NKw%ikunVA6UzP#8KdXOu7Zph0hDqz&B%GmCeAHgX2f7sZE|y}plKPP9z!zS%h;7vbzdNN@QdiXmL^~;ful|Oc9Lw|B z=Cg=^axbMYB&l0?cmWr#-`DwoXm%qn4$>;7nrAaS*lFeO%$K9Gg_`8bC&f4Bu|b>2 z@nz-zCJyXDkN*u`g(+}j12)1;%|69T_hT5r1u-q@&1v~An zlkarucC@FGh0-<5Coh`F#_;53PyRq;n8vRyYOo7$r(HLgndOs$>@BwSddL_B8?JdQ_p&Rz#UmN}|wG_aUcT`u`Yvrx@L$HNduP?Xqp#wryLxY}>ZYUAAr8wry8+_3eAR zANu6xBrE^ZN>=h`CiCMM);<~D>VPl`PrklsZSlOQ~cnA$^^uY>IXdlr$03 zgd6JCQaRH^e@?n{-gfF7y_H-ZHQp)tl>V9*{}O}S)@-2_XOjgKLDj7<(F#`M`-k_`bG zIHLH9P1xB*&S5vK|L{kVV7cKTDVIhAFX3s9N*6t`IT zjc52+&iJ2VQznl8d(n)AjrG48^I6iGumNs?+dBEhktv8ocmVqQvzI|Txkg^nwzr#i zoELokh)_f`!&`D=ZrD3Eqz&RqAxqrZkItPA;DLL;o}E43Jr1nR_EqTj9qb*v0N=uA z`~)0lPUCX>Ie@|8`QmEzgpqnLhSzO?E%2f*@Zt=fDnuKh*X%D^I7%nf63lz7TcC9#ju znfWy7w0VhM&N3AkgmRudnDV$7h0Y9!YD66k`^PmN+-#}pyFR~rPI!(YNW=~OsJ^1} zFN)54+V_|(pAYxflAC|DuKg_g=gmy%BQPL1DIR>>=RD5$_tovkf-mtBhvFEJ`AMY? z)NWFf)x$b@X(@R_8>E*(oey>H7P87?*}wEhgZIRxj@E|>m}Fr^I4s&-9-RtyFn3}* zVHBqKXSZku(~Y4R%7g{3?5fYC9v!Mqf^B`HYJ}}t?}l}(J$Ls&3Vz+0Kq8bzYd62A zCmrSWVbibj-tuA%b7q@n40dVM6q*wxZ_XF;TB{o?RS;@`eHGmltLIu3(hz8^fs1gxO$?Lr?aHi zdq-Z2(K6r~P*58~#VQWq=8CLy*)zP0Qd~h%#ZHdsrmU8gkG;z<`k;pKQ7!F*BE9w&fF8|R`elAwW5&TPr z*=ZmKoOeTWves3=tHG!nn5$=Kz5HzCZy$3q_tg*=L#J~_Qk+FunPtU)TN#KG7PqEO z6AZ2fZ1?^R4>GgSLYBk=_(UzW{5JM=Gc|1aEYsoGM4jqZ0DleiCV-TrXbbQS4o0Cb zCmks4N_n#pxSL2DH_U;8fv~6WZ@D)ul}0k_mug5}71~@e#hxl&BJtyqgkc;eJkjSc zwoS>FNE`HyuOcqRFj3f78*$auuupZFH;zPQi(2ddKJ~7UsKpY(+5B` zFhuwgXWpLPgvDwoT&yGxen5`>>r*$FAHg-`%22+1P|4g@h4KuTQk3ZN$7=bCNaBF&T>52s zxBA+YsvVGNP?!(6lgXpX|;IqNH!>7QQPo2h2aGflZ zpRT?)V`QIXAW$^Os`mu(l~)7h0|l93i+Kf|aepmnkP2EAqpsg__~iu4!QSSDi~P#N zZ{Pxp##u4l?Fy8?r$=Gv_w*>dKr&-|VktFr3uSQOxlnm9?Vv2rk}GsBN=+YY z>S!zd9eEP6d(weTx{dqhs3L63{vL+0+V?f)EHLa^xC#_e&Ttkms%9OQ+s~BM#@s?#7t+C5Cx=Fu zXOXstGK&)_6Hy!A_K4rrvr_k6O4w&f(RwXAI44ZyAMt8237}_c&xZ+F|RD=lR zw}u6=MO{3un@RC(BgA!wz;~YGIp1|O$4Sov1Dccn-bN6*(R-k2U3Og=4!90pzWUWZ zX@h(4dZcih?>;i_?LAa1+;N|fZaLg?=nbN&?l=k(k)6iK7jQ{G8J~paad%cZr@Py< zX^#FQO@IAMe)W5Jfo_aaGRp1g?&~g#0~nG1DR2bDYNGLagmp9Uz0AUd@z-ZW{6rpFg8$&-pec%cMqPzG}_HyMyEnP9ZtNXuqe)> zWnQGBmsjvJ#X3qPv0a|z-ND(3eKb|UVjC5lw%@gpzE4SfRG@;5uIuwWacV!vjJAL2 zk2DptOv{QygC>(Bw-81%uHpq(j7xrwjhnBwA4t5WI7CcU9Z&-))`K5W z5bRA)OOGafRY8}A%?)I-N)yX zv)r9Z5xU$+uT@RLH;^~3@ulos$O7))*|t$OfRmG6d?MrvN42+3I5nt~lTRItiJgxJ zra+SwQ*rl{hn{U8?|PM01xDfnFV44K(PIn}PadH-stGGvs|{bLlDN^yc7NH!zgpu zr>uq;xWjg9k|O=ik(hPs2V>T;eo8slVZ)^~Z<4<`#dhr4M?3h*m3TeMPWy32g92rBOUe&=c+@tdU zjIl3TSKUY>2Y$EaGwgZg_L%L~G_lCOciZ$ddfHeGEs=~Cl|?4ho3OmvB3WXGMX@O| zbS5xOU;~?7G{OsXbaqT9Oz%wn{drk4UtQEH>0bcho%&3d5cw(+B7XeUOH6{lR)K&H z1Q(OI>OhlV5G~3Jsy2>KD*Xp>dahc5Qo*?jOzZh~lEQ12KG(bwoVJ|3&c)+Idj1&a zgKF@1T?Pl5vxhjcjPe_aVboGjoWp!tClp)Q^;RCP4Q4GS2ltm~hyV=yX*bah5l+ZHhe=?W3f1B}|bLH#d`D$_GMav%CJ=^i+J+cQ= zi(tPcjpzG%`Z$X%^*xn1QE`sn@wnMk^s&tv43kn+X~<1jRP7?b%Tg43+mMr3(=AWd zP>=dSxu6yG$yAvQkJO{0*!@UDcbbY;J(sHsDZt0P>^k>cf&3^_)hQk?{~Kh}Y%27- z^sPUFtYm*pdvvXO6mH@T+8RqGCmVq`EbDGSHSa2DwwQFhgx6Of4J$3yewxUMf$y*&@`>x%EYY=f~xl z6MoN;Hzw^vK+#ZiGehC1`Un#gf8xlCkJSbWM)U|0SYcsVG>_R=#W;2`G1`Zb2E_s| zBz)($HX1(#>swH~3MgwLZb2t4r(6i66*YcS#u1~kDqLM|VI-s#tr@-Gi|^O7#PXph zBq4+2ODK4mh;vqZ1rk?%o)Ab()WS++{7`GIu(C5WXP;Qaj}va<Xwr+1&*2pP5k@BGkcvRr%aMmuxRI;VkrN9nwoU2mE=WcQ= zlq2GCFJv5!{R=(Xd`>jeq_HH|0CqVyKbYo-Vj(aPb1ph`L#y)bZByY51E`s)%1Qrp z$nA`7{6r0{&phFnij{*EL&~f(BmoaJ?Lo_#PvNAnWLf$i6Xi`vQJD|oiVvUTKV3Z= z#df-$PJ$oA_w?PBZky(NNHH+JXswvv^$7kuv&tcqrxl{z8lsjbOHF-=~Wi7&!SO9{DgM5 zKJog@g>NkubJ`N0Z0W}=uUI;I6)3?8Y*y@U`E>Z5`M|DMu5^!C62Dz>7IK6 zFmE0>Q}Sxz(vUH6lZczYHNO+~Q1Z@2MV!X16P!7hSqJuIcHH4D~s= zm`D*!v;IM*jEZz1Vh&s^O<`t~`Xtr}kuhFg0Tz!&g-~5p7s<+@P>c&q8JP6x2RK=Op z5pl1op04u0<7Gtn6{QcsDtQ;Q6PO7<1CuV0fxFJ}{h%7FR{E3x0p7sgUTW*(j32-y zp=mAablpiCe0E8#6bC~}ntjD&-g%dKj105E-4w7w+UyASAxAx4YaV3phf-sK&nh&f zHnd#U=?(p9Ft}6T=_v83;R6R=t=iki+3&089)I%JY5eTKESqSG;zAMs)`1bKJpkbdnA^n=mo|SHFg_H9ez54Ot#i-0k^>A-Pva z+@|C}%O?oL@-nx0Sq!Tn)smiO%Z66SpUD2I*xfaZAf0r7KBMC`k$Dcx3^OkiQ_z4=)n4~6EB?6Q&j!JYY@US$ z>Dlya?@ZFgYsV9{!pD}#ua%cY$fm zY-Z{wCf;_5pMi~*P&6hH1(u$v+X|pDFp@L^A&3a6jCVox5i^7PQrCa~9mI@j6lG$p zKiU?!1|=1h(S&Lw8xZWS(WX=ZfBsIF;OQD!cS{BQL9m)3{Aby&ZWZ*5xyyi`o(Xrn zVKq#w8s~O5yy4XYnR@(r3=48FV7W*dxD#*6pmA$Deq0;GGLZHRga95Et53jxs}(hG zPE2ZKGochIo6kC#Gi)_bD@iSGtz$W7d_$1_A{d*L>-}Nu{HJYbuuihgX8agJxAe1cW(B~@eM5*nG)IXbvs*P zckVPDHeL7klhn^ZhtIqm4h=5$B&~-yJN?b^@FEVr74)W=z<_(>)YHDmizzRcJKGg} z2U`tX`^y5|mtxOLkDe^SStuD+4S29U9X}%{{SBB1vT!~sFwrQ+SMox}QccwQ- zBMAv~$ha6f--tML_iC%IuJ$A<(wX3A!$1nN%vB0=sxZU8d9f(ga#siM_0`5jL!@uV zb;sJL6Q}Kdzrst)^~m*ykfxVA7ta|y1u9;-N%sDpTnzAsF>3zd9-`QmROs1`GvDO) zOuO1OmYaP_)Mp|nN3hZ&p|8)K;Q+c!ce8*_x;1< zhe&twlZboZ$735OcP6GoyVT2ryX-Mu@>Sd^i+6b;;4>NIPsIpQJUd5n;R*#$o4Q z%!ln5!d){=-?qc{G?>#G)M*+n(roxLAkG2J-Uq-){AHk(a7=$Z@pZ|8_Ow~9+1KO1 zr2}Vf8ZI=r$2Vt5O()q7xUr2LjgB}WqS{w(o4l*Ov-xt z7mQ3imEn|DStWPz|M_Tu6T%J3pC9KhPMIiE3hAAIYQk=3jp~Z7hY~{bWO29Tx*KOx zj2@HNBtefJo5)Ec1g7H;+mp^Fan}!wgPa!e+^_qj;gc{4l*G5HqEx+dR#DA!kH3D= z3t0Hek6V+vnQu@n6~;PKpIe898{J~geHVm@PBkn&qe@v~TUON#gH&hOoO$4_c_L}@ zi(;A~Yd43AQvbVriimL%{>`LMHm zDn8ZCbJ?d%I;4=V?6ZuP(})oZmY%dvAuxGY=k zYiz3(FqI7+_f|iJOAbhDS7u_l+g^JG*Ah8NkEk!#yBEm2l1_dP&MYf-i(?;2JQyMT zU@IKX>}l{mtU6WFb6+V^#)7g~bBXds^DNYcysG$G=#tuoHMAU{b-+9&!DsO5Mw36_ z#-NpQa~+KcBsNJtN&pwIo+NH4rHITlrV6DyayOT*27x?HY0TEOh`o%7j+R0=FUs0e z6IM#XHn(3R6{+h>AX^(4@;{eH4|rLyeZ?bByMoV_z`zf?2#?3~k69za^=A1Hyd@(j z>%7VO!bUE3=m0ekSdds-VhnGPwdByK@;}zp?WJJfWpOMi8%tDFL+B1LL)BWrtJpS! z%~HyG)*EK4t`dh$*XH$nJRRp`Xk-iUUzfo9*Ug02ch*5eU@!)mae|Sogkt^BeUTC^ zPxBd+C!=*B(n(?sc$vM2Lk>I;Ag8tE1_`S?C9Uj1k ztiJdc=I2wyldj57nJ^XQxX^O`H+^H6@hU$XFCxotbzI_6w14fP5Aip?`bqebC?-BE zz^`ccd+FR{r8w7chDfY$+NiTzNTA&Vo9Gj5w(BT#Wub2&VK3srnj@57(T zu!&-C#N<^yRkqn_2201k(fzM5K_*6pl!Bp;VgIS(Bi|q?154?LFuR5)v4xSG zx5{nDT|G8NStX=J#yS@YB$=B5dK!mB=qmJ&=J9)P!|AJb5kiq4hJG;w(lZu8Y*nhK zoPLj3A1tJz!-KwGc^*0CdLC`?{(e(YKZNsM4lt;~OfwVk-XP_x zE&!}aX}gX*a%rU2zuqne;rZXOB2_O7t&e+Um5SXuv1c=-QfLm8OanEtD7 z?v=)v4G|l{FGuPfT)F|(#*ctsl^D2<!JHhd51YAG;ec4D{Ha~Jp32Y)w z7#RBv;n(;O+}wc=VdKaEKEOxtT}NMTaE{ndnA*OCyi%@*PF#L^^VX730GjZ{t5w3i+q0>ovr*E~IXHtn(+P_D zr+@?BI||TH zo`B!zW6#Q{a!VXaG;rSanGfYinLBtuD3J!cc#FgH)*Clk&A#=8*{e zXtfbj>``n`tca|2O`x74hmmJrY)zgqP|B2BuNRL}qb8YGJ>gS@@nTbqu2`lC$>>_f zOFqBdqAf0daD0jyJ`+=H)^PW^f|taU9bwoZ5>@j~gho~B(BE;3meIzBj-Kwyh1Ap(fGx#KO>JE@ zfQ%4h(2fw5II-wO7VWx}W)pMjycMFeW?%l^()_7Wnvvi|@S#()3m?U#=%l|qiMq3q zaqNZb>X*NJp%wAEXC7H)OJwv!4^hO#n5pvTHCOVS;J%XER&VhjT;wg+CnLs#Km&^C z=dJ;`Y;oE}OD1;tYU}ALzi5hNc%c!@=r;cO-RL5;W<^m7?^A;fGWilKzWj!q*6}5j zy_*%6Nb8eHV8xNGe?Dl@pTAa7Y}iYxl)?g>dbryGAl4 ztBl$APOY)_Wv*ti5Zs-i+8LSGe`!r$_)(I^oh6F5n;Cr0G&xL$K1N0}xXDOv%+WmR z1`-`xt9o;z4e;~CvKPdUF{8=6R8#F(-$jy)ZA2oEGx!{eh_tUI$M=Lg2eh-|%!W3=AV+CtMZ8g@^zNh%vy15Z9_1 zUw9Mj7vt=?pG~w)0+jLl6_6l7{*+C!KM0~gm{*e9?8H5h2J#O54LbVhT&+y`r|eb% zFdc<&zEGE>o`Hq#ruqp-Ujm%gHz9=Nu{I?~SFM6nQ%1K};UHX5GHF$3i$s2A-wq@FpCwFKKTX$#j!m zRk$y?Z@qyI#~-R_k!=u{bNy0mS&AfEI<5I9v?1mE@a@P(WD0etd#t&(C+W z;K8U^cv}@*zyk0cGw0L%DR@6*H-$(g*_gK2C?tiIKMbTp!;4%$wi2IG>uiEIqw4Xs zw={)Do++De;IB>k|A`{a!1jL+o-?qs{Fm*QUt|3tD@^x^+AF*;RYVbPufCsEhDKfs ztpk+@WjoK)?AK4IA}Yy7Jx{DLVjlQR6h-EK=3?sV-c29e4sLfhuNMaaY@cw*ZpaEA z@Mu7?T&>_EHweJNpO6*bkRAACPP!Gfwoy&twt&x=`>7GJAaXfBZoqmVJ1-az!M=Yp zJQL28JLoa7?$$*|&c0s6wS&n*36ZhBo!{^JDywv*qbI~q{!zD82@wz}!jdW362zip zJ$0KWIv7qeE@mk=$~k0u<^Ur1cNp$DvLn=X-)rLTYpG({v+TA6%;T4`CR*Ef%iS2%JCs5p6?!R@(aCwSkKS{?f|~3Z>73X4c4~9 zw*4;jM%@zz{3|}(BkCCtYoIb2q%R**GJl5*itL|~pGb!n69Qv}!JCxjrS9#e^-~6& z;{r{kbMIn~2S`6M*XXA8{nHxTPYjQo&Pa z^G3FTTpgk$Oa3%xmc$34dtf+(52nEtgEa3yI2%kPN86bcidrvIZgc%byC?r6TQT~p z>r0&eEO<04hMvk7$ z{PoAUNmb>NP!xBoH&xcFzTK74AN^DvB^1+hc2K5nOa5_28!xVF6Sn`Z)oepex@ig; zb|gs(WP+GlYCEvFw|QJ+K`XPuZaqnWu9V`ykBQwrHs?Gsv}gGg5)AC9He7W z9-brH5<51A1v@wC=2grR0cPZLhT*)}pWt2;5X!C`ziE}6p!^A7%%v@NXBU&ls;;V` z0Fkc=es#U0A{9E!h;gQeVY_Lhq@%@*aEpJ?I!2S6z?Ky|9ANeof8v$){ulGmuK6y> z1J}#EZ^oyXR`Na`nlrIS{Gxa?DF)u8?dgXmOQFWeUWo^!Ke|oDCfW%fc zCnjOShXV&BJI3vN#u+o27xvI8tso_7N#LM&tOJ;A#UKJ6%d9%vU$Gy@-%}vf8zIHp zj;<5O^T34tD!IA*R0%TKe%9DEZ5U_vE^A%VIr3at?8O1?_tM3<$_f#ecsIQ)ZZE^W zj_H@EOjWf3`{!}k@Wy_KR>RX$=upf(6==1mlP1bm+;4Tnid7pm)Z4PE&y?1cB#gCT z=e@@3=iuYC+LLZw3G9F+rnM11ccdU(9TwH}>khmzLqIOEud$hVSf&yha~_af33PSv zA7vNoLWa$bv!;(=WkeFC+u_wvbK278D7Af(wdv`jgC~5V*WMU>Hqc`r6Qoku|E5b@ zIGqjP*cvH4f$NOw^5%t16--AlbjS^ol3-xk^Sd&R=Rk8$ z3)oHMw@(IaeyKITg^#xS$SI8EdR-H=17>!8EikxkgL8xV0--J#cyJ4XT7nlo`>7x^ zMYYSPuYaKJg&N$Y8{^G8iaMk2ao!9+n8LGR=#4NK7cE{4%(LQ76pRZDFCfOHOQ#=< zi``XDC`ucGh+XzKb?5w%}!PH;&LHhZl3$X+a`qUoI43JHT+_4*Fusnu8rhe za&@81;@Q8~>&f2VUdNwvD-WUHJC^a+BAElsl07q!cr$&4iGnTz5gE`J>!PbxG%5^* za}Y6D#zqTVbh9+m<~4py!>|spOmciQ-K2Hg$VS7a^vhQog@9>G_NO&!XM0(}&jKxc{fHP7r&pmyL6RV)&CwoRnC>r2_ZFoR7?xFW*!x-O)e& zSab92OKPQUHfoSPqPsY|F9%8Rg$~=5HwhEXaag?J)J)X*4WAm6sXOLqtL-TgMWmy5 z^q3C;LL-Knl%91snn(T2JFHPGyWt={X{c>sZVNA&z|=6Z=&1R0aMkzy?M5~zV%r6D zbJ=tBd5;IBgn#j$va{b({Qnl){(spS$A2qz&}@tO&CaGyezUWbV}(utfnVYP&FMZfYT-nb!d(JW3$VP&yZQxsfjqeJ<1KH)7xS9&fVGh)$p}I3^mp*Q{U{M z`rER9qiiyoJsP$eM;uh#OyGe}7w=(DzXDD-^~VnF!1X-cB?5&qflMRVeLj4t5!$3V z0k}lBE~oehOKYzc%HQ)N%jD^vxq&I(t6=nLkut>(;_(rV-$C}c<8%0t?2&^klgEqN_s*}fAW9IDtH))cs#Ztju_!Iq zgvF_Hb+u~(F^yMMWtbXY-YTi=0MTHe6)z_?OW^Z~JY*{nBeGY)xuRxMKoc>4q6GSysak?8~`j;HV?4!p;dQz2m&JoC)>V$M@3QQ`1}?x>26`{8_v zodXjEA?QVM9hRbyn*$2yJj}U6a;i7daAiTEL#R1^nqgT37XOnm)N%^F%J|OQ8s8RN z&Wp6oN>{}w)QdEHpm>ZfyC6&zMCqqj?|OYVi5Q&*(F(qGq_`1r>yo%#D5+viiz8jW`A}HW zor$oTFt8YdvDEa?ymz4urCEA>QzS>CiENt_T1|3kcSy&jd#gWgtg@X6ccNueDEY9! zuHw7=gcfmbHpRL!1t>k0160QRZ`adM-h zx1r223BaOB2>y2`|4tPcM5`&7=g9W!{EDp5d4fhuCxj$}?I(X&K-@vatVU=}&A>wH zON(#mBwGlDQA$sDPq4jw00kKua-{opDxNRh&bAL$*)eL4M6^*xDIZ^dkjjqc{nK_xMexZ7*NnbKiORC?9+BgNSCwg`6 z7ThH<>I9w&}CAn?|S|;a(f^C-6jv!7gvo_+rtK@yN*A0VQcC4#jZ>+ifZ~`so<05;U9)w{}LW z0M?!34yhD%ih3}K`f>KQKp|oe&k$@h2!NxH;SPwaY_SU+Dv)-zB_1xKU_yckylc2K zgRT2|`N)hb{Uzj&##mz#yd_nY0Chc{LTakzM}V#JDAnNINRi5^#MKfpje-4HHpP5^ z${Vv0hp|4yi%%mK+*YGu>HGUe&`Sp@qXI!jXU{=bVXgf1 zT^qW_tFquqc}{}gMu4XzIn@=oJgQhwI=fY#)$pOuGgTULXKV>Jxs5@>${!uEi)+97 zupOY!9P$mN&cJ%$j~~2o-Xd#(wUebSG!wjp=DbV%D>=cnoQawL`9t;lnx>G(FGLo_ zMKSmYp~XN6D^Qt@jfjkMJ5R=*eMkyx3%Tb>D5X)s71UMtIa?o{JC~B3dV~k zZ~T_XPMRC+Q;`GACds2P0+K9U*|6O3MNX1bGK6VUVS0p+;aI0b&thg|9y>3QlYR=Y z{W>;bVbbfH<=S~3a=4WY-l)DTH?C$@*5qa}Yg+|wt4YBU0}P-RQ^Tds8crGI8y*wIUmK z?hyt~PBoB3`^i)qrI_#Pu)%tVDo~oOWqbEW^{oWb%oYSyH2X^Y{u2i{ogO z6|d9e!cEqBZIQkGuX%*WSDodfiX5h)!(_}Cua=q!kgay7CQ0sgj)R|jX506U53}kW zQKbX8IlnBKstwOg&HB@7SA?T^lyWYx%WsLn>Xh>6jiGtpD!o9;AdVPMykLk;?Lf@) zE18k~iH{B6+Fp{I|9JKP2cHu?Bg21HnC;S>`o+}zX5ti|Koycj|M2wb`4dQ?AD4$V zBXT0HbDn3te}pJB5=ho$vwAq#U5qn}#3Me%HQ@NbIJ~xScwKt372s9b6;VTCZvywR z5`2>n1%v{BwV=uaBQtw7Y!rRB_Pat-;iI8Pe@DzbegektkRo#Bz0}HH=u|6O&M}ax zcY4f0;@%`?LcM=J4q~&V1ts=mT474Rcg~DncB;|l%>DC1eSNO`TSZA``}C0^50-8( zcJ@B5XL2m707e>+=g|v90ecrU$cEkg_m=+wOd%1d`kC%MrPsXmG#hwj12RHEb+0%E zS11-YhPvXD@CyXqM?x6xSDKZwx;KBU&@XeuXcMp6^RzlOTidicRCk2=#xMuv%ikwE z%ARC+^V!2KT1zc`wqSN3zu(qy4!x-Zbw?0AP}zyti#$XhB|I`cR8*eGax=jw zorq|++L4Ku^~`^ax~I|o9POOPG_3CjVtIga%!_uM?SIRGVDZ1TSBU;IJ}JUuqt@iy z|B#7xGLpc(gMtA~BOA3~u#2M@ zO`X?z$&aXSM0(HV{^k;0O*#}2MDmh?#|V^ohlH+@p-Ii6XR2ZpN@!I{9V*qn5;88i z)EeG%XhAb(qKp|c$1=kGFk!C?MXR?O)L}UP=agkRa+#p*omRPs{_dzY#OJf)Ix(*d0SKXb`rDsBeXH>ZVIl&7_~qq@IWlDIOi?BQb`8Gm5)%d4Y=w6% zxOTCZw@8(T)v>XFxEvihBFlzKei?x{UISm5-QubHRO<{iwi;Bgsn5}sBIj|6h_*$z zp!!&n0}M8ojzR<#XH&U0`Sm;um98B5EAvQpeTbkO{kS@n&T@0qx4&c-zRcOav0 z=b|0-OX^Of#&gnRs73^|M~-A=^pSVnU%^->t5)p#Voa$FPE%3IXZtHDBKe9Epu|GG zq-Dj@tA89?ht|hk)I3M&9mg7pn#g^WydOGsZ8EM6!|5HHY|1hPVP}4j*?fI;b4peq zJ>7r&W9|@lp)vp99Dx&=;Dyc=%$i!3Z0{hdWY|M0%Gno_WYpWvbpQFjws{x*qX=B+ z`QFZ`B~lWOuJ20m219-s8uiNsr&*09r_z3@+7kA=z?g5|Hiis=*!p`LKI`*jvdqKr z5&;_#^y{P5Q8HX7traZ1&K+L3vOc$xyzTevQQbMpO4GvlBV{IZ?3TKyQ4il$(L$jD zW*ush2?$_PTcd=}bYW8D8nBZM>DleOJ`Nh^YqDIFXx$K|oF8aZ{}X)9wxod5U;>}0 zs?KtRt|1eY@=VT8K>*Hv4>pwW~fKJO$~p9Nr-|6%&+gnJF!R!f=nVsn%)}!eF};RSR4uk1cH@uBPl8puk(*Z6Ii$Xx@C?qc zoRWPYP$QfiK79!_TOOz~8>~FV4}{xbQ;<2EOl;DOCQ1DtrW-o06v2xFU1R{=g?#x> zMd(TterSz3K;kOLh62HnCRhC}#4{EG6hc6c%AhQNT7<>6@I#PAMu0lEujuSoSYb=B z1UCi!wCBV|XYX)T<3H4!8rWE8Q!*%6hapLqo3yo=VhaArIAojTVZ)wpx0_>?1uB_1zOI zm86y=W>%?ld~>5XG4C{T5lUhin#V3XA*#0{yb^CzzFTy}VWQtEkx^Azq1 zw^GazT-UI2uvqRR_D}z?w(3ErcA~8hKtBUip%~X3)Ly78G}-2Ai8_=As`AMy+dlA= zNKJUXW!`YFXUpMr`~XgI>gfEZkb&d>t`;! zCirhszoH%@pw~Ip26mU>P6OuUHD=E9B8h3;&_Q0szJ zbn13{X(4~(-}NN4o?h-JBToN2nwUAFi&eA?%_Z{Tmo&OPxby6-@b;jm+=UC~LjEpa zTnGezTD`JA`&a-*uOhjLdWDqp{klI1BrYflqxF_aeY<{|*n1g}E&wJ;Qkq!F4SfVg zCy}0wgd9bo_WksJb9vU%o{6fM|^CU#&#?aGgLgfRQ zXvg*3ei>G--aATuEFyZpr8JP=mSo%oMW0DvKmx&mMmsB{8S6z214@8<)l;3Sz27!y z06W4nwK5OLY}BC3VtKe0pw-GMpgs&Y-(W0}sy>`eZe$Cjj;U00!6Pm>T}r&(PrSGI zN^(iEC2o*65qWMKzAOa5Go4IjR~Z}E{nd$`Zg^Q32@e(nwlj)tQOA(W+OasQ)9fUB zhbK&0|6?>yagE_3s*?8@!Vx90NZ=tkBjMmdi)pYIaO91%P2&fl zxpLlX^_O(#LxT5I48!F+wGNhwhc!&F4@xT{xvN3SlMmL7e|stFkJTP%jt1;X8Gm7o zk#HS4ePD&ZB_BeGu@GmQfTV0V`BxN)gvCUr4}*01NOIm^-dak~JPf|lNv_wxOyMt1a8&LptsnsJsDcxaYBLY%A`SA{rYbnLX2VZWNb*WypOg(`E$6`zpQMklSWlo`J+|)(8*hw zQzq{hkL^(DcO7;&P3R1<(nX`3RsgkM;Xn^fIwjz^(Z}3aa%v|km{eS^U^uR|vsu$g z3$0-UEF6pjdeBG?Niavhs{3(rjIFMqI*fnnD`(BksKGvpnr1kql`v{yE$3P(;T|er z%Z;AzywT2GzT8%mpS%1zM6HcGzjp*NN>K7&AS~7kk@e{gj!MV8@g)xz*5Sq@T_gnI zH}^Af%1R#PZC*VZI2d5``s%n5>~u~J@<(^Ap<1O{CUDsk>RQUxI{BwfKaFYkQpL`b z3+R#Qha>mV6utwA=(swOOHLMvnPT7NZ!eCRWa9Nz5NeWC>5_9rMij+eO-ped5{98M zng*#ptwN?Ex47(O^?{?~#`kZFR1F+#mop!c9g8BGQoJQ$&G!9uXzlYRm^_X_6vVvy zu|#@f@K<4sR@UA{D-(mFsN9DAaEAvbv-!q>tUq=ku9lNYWFey2m_Gf=ntIvbAXELw z0xyRyiNTtc;L14M#-I5|wi7CjrN%hi56BXW?*bThm{b{kE-Emj;x()seYwek z>W6%1sk!m;yBEqWy+dFoT-$^h+qP}nwr!)M4xiZW zBputfZQHhO8`Cq(`QOEN7H505Rrjg7FOXVNgiXo#nn3Whcri z#Z>j_nC~I;PR?UzT+mP}SeLZ76d`Pz@}%o45__Jksr70om6v>&fgA<;bAeXf(|E$z z`Nx{G${~f_B77l4a-F!(`&a419Du$XR&{muSqXq<9M9;oJJCzF$Q)|iB;&m0OteP7 zuZC5}@oR1_xE+8tTUE6R#-|w#vm<$8P6F8De$Q#W053Y!wLSc9W$u-`E+q&{TPTYA zhs>re=ka5nSs3LT9Io-aST^^(wguioBB`$dq^?o`*&p`5k}(422y zNnb7mIZNLZ(<&0#4%A3uv)5vz1qURU@ZxhOgLro}u%%6evCHT1u|Fr7Y*8k!7ggCJ zf-HM{-R_f)KZi%~g5dR;{ncqpxM{qohVi9fg4hQ-d@#+Xf=$ooxm(LU za__@^y`a|Sef`LB9tA75wjr7dOSFS2Ab*ekuM+>H-1ymk9`C!i8*!NLil%Vxc^k|O z->J*QRb)7m&6mZi&cdPjy)JoaW8^~t_*k=d5@p+i-oIY6-)E@4b-)K~3I&N;Q3cXk z-x4YDKU`0oOccPfQfg6n=-Nc?d8eWTdvEy8dls%c$OoQh0FU__wB$fkzHY!Vsd{a? zq-PXiBe9H|_cP(=E^W;fM_hMq*z&+s_iTIr&acbUbP}Ig?t?z%5R=(?DXRCALFoeO zif25##b{r61BgLs&hww)?AH@cZaI@vi~KDfhMaX<9U$lu8Pc8QmGRbR*P z3aXmV4PHPb%h3h>IwBG*44j?O(A5-lp}%M$;!wTwZO3|LqA#<2H{nDk^0*vgmT95M zW$5f+*@@}6N&a0iL~z0AL;20oNn8-d`D=64W*}mFvotxe1T+tSI0m)4T8d(-iRC&Q z8aqQ78DtWgTmC8fJpQ7ws93kS4Ci>6^Hv(EajE2) zHB4Ibeyq|nY`(Vf3uZySx0spLR)MtL@!AjA_9Q&zKcpuM(|<@$ZqEOW{nVu^{a3dQ zx%)!1Q;-PZ1>6cM?ob1?&0|+LcAz($7t)J~mHY6fB+`cep8l6BFT~;U0qGz0Asqn> zYJn~VZ%=N$Zam*MYJTqH=-*E7_jV|^fdfB*q6O>;sDaw##f*Z*eteD$^xh1&bD6Z@ zgpfP@pX?5B^+A_PpxprZzz*G$sc$gR$A6I&c9l~b#)yshpRaoq+m|4N05On4engXc3 zlhBN~yva^*g6D}6yUCB!LXDq#dJIack5*EKTk3mrPpM@ER7J0<*dL5f@lbGI<9ZVy zqH!PGH1HasHdMo!bj^mWEw*}FMFe^=;K~ov)zE%?WoTGdfj9 z;-Oy&P{@6JJIvC9w$iiT%i}>o#b3IFOR2ItyM26VwRWpZT8p)9(rTSj1##1avszmo zcF|E8HYb7rauvdmPLBM|nrfuvFUUHHk=lD+kv1q&P*6z2?c2&hool6S`2iHr5&(k~ zm`x4dpE#8%>TBtxsUL-nQR5>4j7YCZuMBM1TYZX`=)O{_$IPh_vY`tT86HTOoQ+Lr z=aBB$Jr>=}X$`={*4FU)mV)HO&@a5QijGXg=X&Bew*Ke9!=C zWL5lnjs7NI2!7IwQf~EOu>fUv!{JmCA-FtB?cn(ak93gp*3#y8w)revg&oC{WwwF* z_X;&fdFr0KuItyXLl+_wBFe-BeYIbjeVKsmk zZ+ECUSo3xXR~v#(A<2k@bsd-?@OT~|swUr&<=(~>mH0m7H11O^N+S6X$U-gM z3GW?i)4g(eWb<;{T~w7Z(>vth6y?`&!gsy){!%~1Fo%Ub=jHOcWuDXhE-)tGSP-x| zSsir$0=!+b{I&T)KGZ&QV*jJvUSAEJvd$)D7A={@oX1JvRt?pxs&PG?@XaD82TkCcvj$HZH!=1RCMhQ>4B?{6+(|q+9*$AKh!MJV==o+7q;a(q$>VE z=L1Z9nwRM;YnjgB(sUH}^a3!zx$eUq)7nYIZG12fN14D*74#|tcggjvSdM7~M4}mj zcT1@ec`+I?QQUw)MSl}sfa)PXz9g80I%d{c$#^Q23t?h-T z#elb&6A(QxJA_d@_q5Z)^rgHVeynFhC)CAR!>#*O1lrR~c zOJc4u8=c|&hQ&K`e*yawEy>C6`bu4cBVdK%N)|HeJB&{Bge8H)c1#C53eM44I1x!o z#YKu-|Hv4wV<%1`6gq6G1X!?KFb~?QxnE{JG~xNHEwqm)_E@zS@hzMqI!-Ug?PFVh zImcU00s`^D-jcvWzlT~^T(g#>(@L6|8NQ1fZjzp&#(R#YV9p1{6Wz(R7TyEf8Q`gh z9jm*^b^fF-p#2>ous^mbDLvu(pJC~TX|n27>F{+)ysdAv*swyIO@XXjRrR7s_K=T1bWf!#@X!-^C6SnNj%4p1 zN^Xs6a^8-yjeu0fxNRp)G}ZCcVd|tuF5;XNfih5PiQDJ|>&+v98*gi7dxKD??fo5y zxHuctq*fOLP6~-9kT6M3~%ruqI!h;H5a;npp0VmE*k)(CO z@vwC9D8yQys?~^^5lvM?47mm6>6_9N1TFW3Hcbn(JWAI1 z{h7}jR^djk!-5B47>=tKwsHdO>v^-0k~~2<-!?j}H8JEIP>k{Uvi&>K&HLud^!(&jOYo7H zSX<)^817DD(Lhj`r^V2@Ou(#1oNw@v@Rs@5i5hi=y;^JgHaJY$ZIg%-l@xk*Y@ntk zpcli39#s@~myJYb)J&aZ(GgKwW?43=M2P5?rY7m6KEE2zNY8!+;Kjr=};g zHTBUG;ifWbKx_E(;seD$gvSFpWCQuTDkNA>LA5?{EC0K&%TyA{l}euhXg`f!CfC+l z{(YLwN}Iy3=HI{}dzb`_dXtG9Ow*;%M|ozoL8HvJ5vDnCNGWNqDC-Y)l4qL zSDqA*q7z2%Ba^2ZD^l_(JJh1n?dD7vWnO}(ZXLm=N*q$n=J%&XO($yk%zDCrWoB)i zSHB5+ywCq4CdX&4-C)s^yMJrRjry@Et}!Yrh5@4rbj~qV5>`h>j8F>lzTyqSi|YKY zOpu`uasfiTYeUYERt+6} zc`^2kOLLlLaoVGt&UsRkE2Sw&pb5p}#BEG)nS8mFD_TZ)!x1{`o;^1h#U3YSCW9(L ziY7h6mSn*9u7K0^Tf=f4u zq?l5zxIGnHq33UUd7L&ibWTs;(4nV>cpURf&8<#|L=nz=%h6~|$&o}Jwh%`6a1;d~tpWj(9ezgB9NAdOw4F`J_CN*RrxegR9MgzY#c8l?fsOL|VIh?%5*k!pVZa^VH5 z2e8u`FGFBR#rgVJN+`_Abs5&cu0u75G2xX+9}0yWYA0+o8`%yug17kZ z5>Po2^@S~f=<{s zl78XVMy|k~kP`AQ!=*Ft#;i zxQX=1o{lqDmm%7N`qupiQ$bGV812#guH|OG>$xWi`xM4HKcQUDN)kJERh65;XAhqU zz0P++$?z}5{}TMnEdM8&#=`MGGU&Q+$Lwi2@2_iS5&1&R9Kqp0<82{RbwPFlx#8ov zkC@(m2GGX#r>~Rg$RXS4IkYQ%NQV@E`0o~G7*lFeas-64=$v)5Jl@|A$Zo+$dIAq} z=O}5xScw!2{jz<%j`VOo^==EeAbbA~{oo5cZ6G2cSVCnI-&P?x2v(xhOyQw^`+ejI z$z)r4erE1`e?8S;Do90RVO3yN(_+1H(%zLlWke}P5E8g)zRDBZj~BHVI~?6-a4G(t z790qNCRI8KX&EnUx-*?SkBf|??6<`pc6UIlDZmK=1agnl4CRN7cq3%sHbT(B@Us7{JF{7;%h zQH35@dfROpxsYs)n6G{S6Acq%&H-E6XK!;*yB6ek0Av1tudUwH{ zLD4Ty(xB(9>D@Y!q5)4LV5F-aljD$^P9~_Qd9)CdKk&6juXanFvq&I?STx8I>9Sl> zyc0EUI~aWL?&0?8;Nr+HVFL+os;~V2h4(=-qCr7eRgD@p>Uh0hyetqh_Cy&$lOICw zrsfL9C2Wn>p!pW~?G0OPX(M0nHS%C1Oy2Gj=VJ^iO8(GippT+Nh$bu|3-+&Cwig*>v*y56}5&5?gbwy1ij9p~2k@|Y&>v1mz=aNW)`k)Gr8HS<(4^9XksXCAQ|X~7$i>mxYt?$V`u&5o!D38dR; zopwnyTQkf0MUq8RKOUi>gQ~Kc%P$N_w_ zE33y`xD`L &;dtQJ1Z!!_ljXpK9R0>n@_YC7B^&(r2$#WFGj#bSc$am)2}I+gVh zCJ_68RMk)T$tZFyfyCme+j3&pG&?Dp;?$mAkH#v?+_B}o5Ka3RdI{>)qnl&WOBWY# z+vLNNi7zO@?jS49>17I&Omj>B6LEPdp(AWg<25>VRBgj+mo~>#U5aq+i#Pj5V@!cJ z=;=qt5QSdxH8R==#ZFsI^Y3q8)bx?WE)E3F=miC4hTh9qAZE>kyPZ+&!{`g zI)v_HuXdwW2tr97INL`gXV{kFuSv5N#pcN~k?h&1a*-nA9y}M5snU$miQwi|i}0ke zx#RODf0fHJ^FHcRE!; ztPJ2gi4@isCvvhlA0(UEAoKMQW0T%Zkt7AiESQX)Elye4`YW#5J9i!&XHJT}dO|x4 zm)>B!txFg_$Y*fB(UPtSsAn`bN$)-n_0QOecx`5F9Q(H;kP8>@ z!~<-1De!aXT}#lE6XY;``qz>*y82Yc@5cXp3msCQk(K@~oGnS{lGNseQz7Q7^d<9Q z3Wa9fYgl8-g<6_X(2%g+kDS20x|a0rdYqK%xqY%o8b`y|(06pIYAwdI-w*_t;}&(x zmn~p=UDdVnQZ2U|TnT6lY-U2H785O?l3UOncsWoX4?Ki<|M@Naa)LwOaM(q`*v2`F zaX!H6lHU~V~$v;wnikq7{s{zG&kPzoGZ`X6cUub*#8>pl3126A~g?Y0f6?Y&@4q zUAy2&e0%{t!+1*@;`9dAl7;-+YX@0ee#hg>mPX&lvpJ081Nh$!MwihkSbUR%{LsXX zw(P@f$A4r%3(s&!`{EpL)t<|4KG|GC%=gPy} z3W_R!UrO(5D610*%73pMek9wmCCJ4fRBJ#jjAEk~JIO*BE8 zmyf}}ll~15e2O$Vx^&A{@#Wb2b!AYq2jGeAin;LkiUAcZC%eWvTaa%08yovma>X%R5S_Nh3@N3bV@T4U`JndDRK~V7}Z+y-x zrZ4>!e5=xF&Fd9-&g0(nFWo+QCz{{3NE7Uaviuwb?3rJ ztmeZCPq}?gZ&DV&SXg;G+#=a}EdXpN(#m8*8E^M?dlMI13nv|jjJX&SnHU-jIXw&@ zhQB`zf8()v)`>8In!J6QzDO)= zhWqmE)FdLGVdeMDCir=On*s14KYhO0llA+X8%^CGjcnb(DtPPnU-C}(@^*b%LJ!DE zRekoSA%jpl9|Ql;`|S=Q{=7dwDH?uLU@?4f${+nPQGvZlCOlInfv`@wIa6k)1=svz zL;$V%hh5jV7FAf<<_vk|MEy}J=b2k^Nc~6ax|;!zgCf`zmt4$60PGd?v;0b(ih>bRxMxie zAL=LylIXrqzv5}yxaE*F9>ogtJ1j;!kxmPyx&DN2{*o8*U$~nX5q&=N4qgDxYbcH+ zJKdTQ1BfCni7J!Ck<+R5`}>}>>LawmAmaw=#6ZeOCgW&ZD{&i$rnK0tqCCx_WK5fN zCex;`O(c4r#Y%0sp;((APVCj%`ZNN!qlWjxB^B3-u~DEuT5bsjGf{MlUT>92$pg~S zX&)q=ta|pn^h9#@wGwZQ{7(;?4sNuD)P*GVJEv97qACF~E{6LlilBVD@MjWR@=6G@ z>N3)@svhbw`-NJXIH^0&l4X^8x=Iy;Dho`d1gqRLuC$O16IAuI z5>esgGX9FIe4dIsBDMx`T{yN> zPU_>Oqd$7@)@RvW4h-v{-2ri#=pUdZl2`Qx;#;cLq7-9%sbqU(OM9jhrB}zX1ZUor z*u@cHX}KeJm6k_ciYVo}qv9jy;T1SC*)ZkfqK{VneWfl|_JQ%@6($=EsE*6rkv3>+ zrQ&@wr82U+3vHFNQ&fFC_*?RO3dQ+O*QWVR2bza2jp4@KR|>bA*9Cp}4k^Mot)?>Q z9<$n~xZ>!yWDTdJJAx8<5D>lllxUATlwvM7x{qE;QfJ~W(T60rG@zu(g5TZV zT_0?L^65b@i25Qtn_`*XX~u^whv>ZRo^z7Ih=obs0ozD4@ove~+UVYf2s%sh7FMB^ ze5k(y@mf#geOt{$4(SH?-e%?I1n&Key|zXjYNC&X-11FqY*Nd8gI~22En4%yu?`!t zG#^`3Sj@7m($C-;EfumdnBRK~+^tea7G6f60xQ~GQ8wJ`iUF?~J&z`7EtazoPO9NY z5xx2DE36EJ>WChH9oJb3jP-=4VWgb4s!M=F^r2bjh?ehkhoaC?eOFqk7^ea*3j>FYGNsDJQF{9yBFwU z*W9R#&>GEpPCFTz{r4gsZ-{AN^u1?E2kDiCF=yYPzdmFmfA=POo4)8d{mw5~Sp-jz;rTGnc7Vl5MGs@nrXXjjflJ^*s7oBP)Zse3@KvY3|_{@!> zSW^r-I^HXs41A6USm^6Xsm2}`UlaG3sZ7?Lm6V^T$TV$6{Bh`3F6f6t;&f1hYbngW zouHuijCoWlSL?RD>77?DUDoQf#*C;YI4@R@=5SAy?_(sl6^&mR%#y+f2p`bgu)yYq z^A6*0;}WQJuViqQjX^7+9uX%+5o&2#9$@(ntCLyS2pBicz*Lnrv~TxjOc#jccQOs= z`;djNMiH@?{rkk)2e;yXee;aOi!s9Yfd}vHWLzm4&u+mdstJ)v$@d##zE){s*(I!^ zV>XTcHZ{Wy5#?qcEXF#kHiJpLr%emw;&qUD`jizRl z^IJG|sL6;RDO3IxD>~3^JWg?lrobbabt z7&VTmkY#e1#l?Ow=}q8-n>1r*Ks?2NgeNo!$L5^FW6S8{TObtiAdAqPt)pW}ygfYRSZ#h}9@S_0^*z9}YTneI@?4^UOUg0XBxBCKaMAxzK z1yfot)8T0+^h>IHug7>5#$KQ*cp0Q0^Q_0e8P|HwgsSW-IK{2A9BNS3=d^sS)Ww_{ zVv3G24lDK88)!))q`zTDy#quxcVro}vB?&tQJ*}IadtIx!cWFRbWlhToS}l8z%{)b z)mN(RUjKm9@h01)s$>Jn&-~C?;p*5w(h60+5C<-)a;UDe0_PCyZ3=y`UnlDxn;o}X zx3BKBHvk`+KC0f7Jf?m#MJv1EzNsg7;&udm$}ZmrRW_TTt8)5A#xOwa;_PC!y=3_>tj#-_vwR|H5v?<6aFQ ziElc$U&BiUGgV6%QHJ2?a4nmA+v#N9nZ$gUXiCI|@8g`{7NU)%%Vu^#xVl$d)ABV6 z(y4`|#lGLA_u@eIP9O4fOflIE%m_qXM#K7{lqiN?eS9gOP$I0L#Pg8%3>E55+iDei zu`ZvRo8E4H$Ar{10IvmFaVp;Whj$~9KQtT?A14-3)L5^In~=M}@RJfS`UlM*AM!H& zFiZo{OMLf|czsP&j}ysMyQdk?^(*2Ff;z`FZgx|7TF#Bkq?=xX|xz(aY!F;fplc2$fV?^ z4(pe`gm+y9o=VcbzqPcTTDsW=i26A3B%B2}d+_;4U9#CwmJdLi*vE_xt zvwYYWm^W!+<kd}`Tx^N>~m~B{ud>rz|B)3edHLJ@TF>O;`YN@rdA^psIo8tod zTOkKJBS6(u%dK~CJ>}URP&GNnyHN(*`Lk?C)z;U&v{@3y9*=D(nzf2(R&?~K$D)O( zK^qXh+}h6azUkV|>OO7%UHb7E#?Kw2Q@u;DP7Q#1hZNkH>CProtYz{g53=6@TT*bo)=Qvq5@1al3PGK3 z64&WIUYb;5pCjQOYhV>{NES;6jCV)|Av)QP{e%7mEA2M6fUz`S{|!@Aah|o&{PKc+ zkUPzf?ZuKwR&98TfebMb91<4@53K<*@Qc^vhaC)y?MNPSz4?$cVxyxDxzQMf|3}mo ztR1HbOIp5*D&<|1gKSN?y6`5+U1n}YmgTI48KWo&MFBMMrF#UK2Rw@(Wz^H^Jf!G} zIR(2w3kJ^1p9k=~sbJkL?%B(-6!G{*6V?ssBq~HI%<`9oP3gfGSYG3;#ZHr!VtA|H z`P>C3BgF(u&ToCig<%VqVFUpIpOv7_+9nd_Z}0)u)emMc3qH<&Sqs+xYb{t<|1p&Q zzr!eDZR=w0#3*5F>|!ovZt7rWE+7Eo?BZl@YzO1MKBY4eLraOYHKX~62p5p=E=?-S z+U-_&>BQbaRYApBK^OmHSm+-J(Y|3Xc&&~>;Kj7~M|FsL-Ra#X{@<{iFo#hvi(Ns% zy#P-xXNN-EQ0l#c3|@zoyC`_+*ZZf}`<1**?c;kcrc4=o7oN}aqdh{6jz@Z)RcO9L z5>F?On!^+xt{|a-GUzA^>+FU5>(@gH=9q*!tPrf}fEhlFjwT(EeE4Gw*<7p{>dqAL z83&Ed-hPYLx9ousX{dqWJx`;f-B)tqE@VwvfqUVPZCpyDmcdpPo08^gB6Dn@L{em7Y<+75t+^?beVLwkx2EMlI8M!M^n)#toN4T ze_fJ#{_@p@t2K(qM&#{1F(?!Ut>!b)bmJz@ii$a?M|&;(DuoWu;#Ti5Mmu*urWitl zswibhY(e2qHNImXHJXpragi9_Wc+&%zG>nP)a0YM7vn8UC=D)CiHapm5rI~FNiEI; z(hVgGb+vbv_)nH7=;oEzz$7l4VKT3U>xOYCI}3zVi>@1Shhfod-8%VeT>e~68Q&Te z$csd|Ii1Tgn10hLT7DSbPR4VQzQje6%|E3US0JE2ntV+hlx*N#kn+|VVa0qZ6)3vv z%Ym~~n?a@iHsRwJl43=3QKbVm^-n0}^-(^hEW#1~$G~dXmf-a5sG48rm71Jxqk$Bj zeR^9q;s>loVmJ}8>Bj@i1$4gEB{$4|gooc=AIWU3AKjA9GjSN-GtTsEXamCCR~ zA;#Li0Nd_1)4z>zCdDjI5#LBeqPS*m>_Kz=Dh)y(M<9VOydfT04kb`&r!@F=sn*B;*LIhnvCZGhpd;o(9nU61M7?r-JYsU8 zCg8j^(7OrrjR>5|mGQn~iCc*fk3_&fR(b_wF3*mcODhg7^WMH>Hl9_(fMF@z<#b~% z-sSS6P|_K95LmVfbUm4%BW3u*MNKW|y}06|*be!@N;FT77%;+z;IIKLlI@?i zfz7*6uEOf9vq;ufPg^kpN(o(eA44wVE4)E?vWr(=e-+~}xi$nr;r|@bJXe7un!!ap z$6hra_u||9QJ;t)Q?yy@sr-lbNnj=gT$2ex2KL4=k+0>g0&9X;Z(;c|E*_H#(51F2 zv`0@&9#fLl&RMv1E-t0{X6t?8g&vVI02@cm(0B=b!#*WQ*QrrL<6`OFu_XI!^r2Ct z@jEktAqJS0MnHx!bdzfD(CWorY(~e|D4ZF}#oZyiV`*aAy48agKtpcFp0c3#RgE`C z1cZqL$XnxhNvXa8cnpj4UQ|x6XMoDy!z_8-F>@=0yBYMDpySONQXU&4op9m7^kgbA8_20OslX~LT-!9Q`h9!oU% z8)>{M=_N3B!RK_wF_=jweQuBJT4IW z^$ap9VH@kGqIKb36#M;Tc6WX9MB3%x6zvmLu@{FGp@%vN;WB3GctG@JZ8JZ}z4a|8 zh^t7&3lF-#bN;%N=q`3T)MO{&KAaSb;$xR%N5os0I)($$Y0%m;~D7p~?Q7UIPnZgZaN*5`HPwsA~sol6da zKrX$FZr*mKl#<9ykcTk*9l@c7dbiB(Zl>^#df_)d)HMTr<=k)k`gGu)O5NoiHN-lM%~mo-opc z+Npsi!b4sk_3fT<4xN_TY4~+~0lse#<7<_t?QZZT?VkmEh(+}+4TaP!f12ud1uA%7 zoOFPQgS99bmI=4Y$FZb8;ywz{lw1EK%6Fh?$pA+hj~*VT2*U->AD8IS@7AIXZ%fi| zbLU7WZ;Q;ZU`VLA^MPDbxyx2RyLNoGn58+x0j{h>S)R0`GenuT{_TaMQgT`*Oh9%r za)DcxiVD!WlcF9SIk)PUAcsnnUmU9`y%CMWmM%Xm`J*nJmYP!Bb*_KE%L{@VoNq>0 zXb5Lp?KlugZ_wT6oP^MC-QiC33g#Y&N(>%dcfx&tc9}Zs|>t8hFo;M!$ujxv@V|DM9{fuw3Cz)D- z&ek`GLZXV6{joL(q7W8X!vjX~ctj@EhVrX+#EexTa->a>4fmNiI8K(1ST+~Zl+Qk* zKm)NV4)7Bv?HqLbF7QLQ*o`7Qr&o=&R=)> zyUc!QN7s?7L`NAHlb=9bXcaKS+L0z2CvT$RIf|jy}ygow3Xm-aP^~(xzYX$$ zn60BVg~EwIG=h5AOcq}*oO>~=WmcIWm@k;73vY~IlHM^aAv=3E@#(mC*-*WQXHc7= zaJloyd^OKnqLiQwdMjoY(_9q82jj$6)Wuj>i7%>R5mFnNP(bc~L(lV42+6T}q*t+G zkJj>k%D`A;VdsSh;%>(Kn1A#V;Re7c!WI8 L2DwSV6_N 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%0DPs4DB;3X&2 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�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

sB*jGKtiW#aWqKC+5O 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 { + if ($(this).siblings("section").is(":visible")) { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + } else { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + articleToggleTitle = "Collapse docstring"; + } + + $(this) + .find(".docstring-article-toggle-button") + .prop("title", articleToggleTitle); + $(this).siblings("section").slideToggle(); + }); +}); + +$(document).on("click", ".docs-article-toggle-button", function () { + let articleToggleTitle = "Expand docstring"; + let navArticleToggleTitle = "Expand all docstrings"; + + debounce(() => { + if (isExpanded) { + $(this).removeClass("fa-chevron-up").addClass("fa-chevron-down"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + + isExpanded = false; + + $(".docstring section").slideUp(); + } else { + $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + isExpanded = true; + articleToggleTitle = "Collapse docstring"; + navArticleToggleTitle = "Collapse all docstrings"; + + $(".docstring section").slideDown(); + } + + $(this).prop("title", navArticleToggleTitle); + $(".docstring-article-toggle-button").prop("title", articleToggleTitle); + }); +}); + +function debounce(callback, timeout = 300) { + if (Date.now() - timer > timeout) { + callback(); + } + + clearTimeout(timer); + + timer = Date.now(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require([], function() { +function addCopyButtonCallbacks() { + for (const el of document.getElementsByTagName("pre")) { + const button = document.createElement("button"); + button.classList.add("copy-button", "fa-solid", "fa-copy"); + button.setAttribute("aria-label", "Copy this code block"); + button.setAttribute("title", "Copy"); + + el.appendChild(button); + + const success = function () { + button.classList.add("success", "fa-check"); + button.classList.remove("fa-copy"); + }; + + const failure = function () { + button.classList.add("error", "fa-xmark"); + button.classList.remove("fa-copy"); + }; + + button.addEventListener("click", function () { + copyToClipboard(el.innerText).then(success, failure); + + setTimeout(function () { + button.classList.add("fa-copy"); + button.classList.remove("success", "fa-check", "fa-xmark"); + }, 5000); + }); + } +} + +function copyToClipboard(text) { + // clipboard API is only available in secure contexts + if (window.navigator && window.navigator.clipboard) { + return window.navigator.clipboard.writeText(text); + } else { + return new Promise(function (resolve, reject) { + try { + const el = document.createElement("textarea"); + el.textContent = text; + el.style.position = "fixed"; + el.style.opacity = 0; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + + resolve(); + } catch (err) { + reject(err); + } finally { + document.body.removeChild(el); + } + }); + } +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", addCopyButtonCallbacks); +} else { + addCopyButtonCallbacks(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) { + +// Manages the top navigation bar (hides it when the user starts scrolling down on the +// mobile). +window.Headroom = Headroom; // work around buggy module loading? +$(document).ready(function () { + $("#documenter .docs-navbar").headroom({ + tolerance: { up: 10, down: 10 }, + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'minisearch'], function($, minisearch) { + +// In general, most search related things will have "search" as a prefix. +// To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +let results = []; +let timer = undefined; + +let data = documenterSearchIndex["docs"].map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; +}); + +// list below is the lunr 2.1.3 list minus the intersect with names(Base) +// (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) +// ideally we'd just filter the original list but it's not available as a variable +const stopWords = new Set([ + "a", + "able", + "about", + "across", + "after", + "almost", + "also", + "am", + "among", + "an", + "and", + "are", + "as", + "at", + "be", + "because", + "been", + "but", + "by", + "can", + "cannot", + "could", + "dear", + "did", + "does", + "either", + "ever", + "every", + "from", + "got", + "had", + "has", + "have", + "he", + "her", + "hers", + "him", + "his", + "how", + "however", + "i", + "if", + "into", + "it", + "its", + "just", + "least", + "like", + "likely", + "may", + "me", + "might", + "most", + "must", + "my", + "neither", + "no", + "nor", + "not", + "of", + "off", + "often", + "on", + "or", + "other", + "our", + "own", + "rather", + "said", + "say", + "says", + "she", + "should", + "since", + "so", + "some", + "than", + "that", + "the", + "their", + "them", + "then", + "there", + "these", + "they", + "this", + "tis", + "to", + "too", + "twas", + "us", + "wants", + "was", + "we", + "were", + "what", + "when", + "who", + "whom", + "why", + "will", + "would", + "yet", + "you", + "your", +]); + +let index = new minisearch({ + fields: ["title", "text"], // fields to index for full-text search + storeFields: ["location", "title", "text", "category", "page"], // fields to return with search results + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not find anything if searching for "add!", only for the entire qualification + tokenize: (string) => string.split(/[\s\-\.]+/), + // options which will be applied during the search + searchOptions: { + boost: { title: 100 }, + fuzzy: 2, + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + tokenize: (string) => string.split(/[\s\-\.]+/), + }, +}); + +index.addAll(data); + +let filters = [...new Set(data.map((x) => x.category))]; +var modal_filters = make_modal_body_filters(filters); +var filter_results = []; + +$(document).on("keyup", ".documenter-search-input", function (event) { + // Adding a debounce to prevent disruptions from super-speed typing! + debounce(() => update_search(filter_results), 300); +}); + +$(document).on("click", ".search-filter", function () { + if ($(this).hasClass("search-filter-selected")) { + $(this).removeClass("search-filter-selected"); + } else { + $(this).addClass("search-filter-selected"); + } + + // Adding a debounce to prevent disruptions from crazy clicking! + debounce(() => get_filters(), 300); +}); + +/** + * A debounce function, takes a function and an optional timeout in milliseconds + * + * @function callback + * @param {number} timeout + */ +function debounce(callback, timeout = 300) { + clearTimeout(timer); + timer = setTimeout(callback, timeout); +} + +/** + * Make/Update the search component + * + * @param {string[]} selected_filters + */ +function update_search(selected_filters = []) { + let initial_search_body = ` +
Type something to get started!
+ `; + + let querystring = $(".documenter-search-input").val(); + + if (querystring.trim()) { + results = index.search(querystring, { + filter: (result) => { + // Filtering results + if (selected_filters.length === 0) { + return result.score >= 1; + } else { + return ( + result.score >= 1 && selected_filters.includes(result.category) + ); + } + }, + }); + + let search_result_container = ``; + let search_divider = `
`; + + if (results.length) { + let links = []; + let count = 0; + let search_results = ""; + + results.forEach(function (result) { + if (result.location) { + // Checking for duplication of results for the same page + if (!links.includes(result.location)) { + search_results += make_search_result(result, querystring); + count++; + } + + links.push(result.location); + } + }); + + let result_count = `
${count} result(s)
`; + + search_result_container = ` +
+ ${modal_filters} + ${search_divider} + ${result_count} +
+ ${search_results} +
+
+ `; + } else { + search_result_container = ` +
+ ${modal_filters} + ${search_divider} +
0 result(s)
+
+
No result found!
+ `; + } + + if ($(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").removeClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(search_result_container); + } else { + filter_results = []; + modal_filters = make_modal_body_filters(filters, filter_results); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(initial_search_body); + } +} + +/** + * Make the modal filter html + * + * @param {string[]} filters + * @param {string[]} selected_filters + * @returns string + */ +function make_modal_body_filters(filters, selected_filters = []) { + let str = ``; + + filters.forEach((val) => { + if (selected_filters.includes(val)) { + str += `
${val}`; + } else { + str += `${val}`; + } + }); + + let filter_html = ` +
+ Filters: + ${str} +
+ `; + + return filter_html; +} + +/** + * Make the result component given a minisearch result data object and the value of the search input as queryString. + * To view the result object structure, refer: https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult + * + * @param {object} result + * @param {string} querystring + * @returns string + */ +function make_search_result(result, querystring) { + let search_divider = `
`; + let display_link = + result.location.slice(Math.max(0), Math.min(50, result.location.length)) + + (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div + + if (result.page !== "") { + display_link += ` (${result.page})`; + } + + let textindex = new RegExp(`\\b${querystring}\\b`, "i").exec(result.text); + let text = + textindex !== null + ? result.text.slice( + Math.max(textindex.index - 100, 0), + Math.min( + textindex.index + querystring.length + 100, + result.text.length + ) + ) + : ""; // cut-off text before and after from the match + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`\\b${querystring}\\b`, "i"), // For first occurrence + '$&' + ) + + "..." + : ""; // highlights the match + + let in_code = false; + if (!["page", "section"].includes(result.category.toLowerCase())) { + in_code = true; + } + + // We encode the full url to escape some special characters which can lead to broken links + let result_div = ` + +
+
${result.title}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; +} + +/** + * Get selected filters, remake the filter html and lastly update the search modal + */ +function get_filters() { + let ele = $(".search-filters .search-filter-selected").get(); + filter_results = ele.map((x) => $(x).text().toLowerCase()); + modal_filters = make_modal_body_filters(filters, filter_results); + update_search(filter_results); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Modal settings dialog +$(document).ready(function () { + var settings = $("#documenter-settings"); + $("#documenter-settings-button").click(function () { + settings.toggleClass("is-active"); + }); + // Close the dialog if X is clicked + $("#documenter-settings button.delete").click(function () { + settings.removeClass("is-active"); + }); + // Close dialog if ESC is pressed + $(document).keyup(function (e) { + if (e.keyCode == 27) settings.removeClass("is-active"); + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +let search_modal_header = ` + +`; + +let initial_search_body = ` +
Type something to get started!
+`; + +let search_modal_footer = ` +
+ + Ctrl + + / to search + + esc to close +
+`; + +$(document.body).append( + ` + + ` +); + +document.querySelector(".docs-search-query").addEventListener("click", () => { + openModal(); +}); + +document.querySelector(".close-search-modal").addEventListener("click", () => { + closeModal(); +}); + +$(document).on("click", ".search-result-link", function () { + closeModal(); +}); + +document.addEventListener("keydown", (event) => { + if ((event.ctrlKey || event.metaKey) && event.key === "/") { + openModal(); + } else if (event.key === "Escape") { + closeModal(); + } + + return false; +}); + +// Functions to open and close a modal +function openModal() { + let searchModal = document.querySelector("#search-modal"); + + searchModal.classList.add("is-active"); + document.querySelector(".documenter-search-input").focus(); +} + +function closeModal() { + let searchModal = document.querySelector("#search-modal"); + let initial_search_body = ` +
Type something to get started!
+ `; + + searchModal.classList.remove("is-active"); + document.querySelector(".documenter-search-input").blur(); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".documenter-search-input").val(""); + $(".search-modal-card-body").html(initial_search_body); +} + +document + .querySelector("#search-modal .modal-background") + .addEventListener("click", () => { + closeModal(); + }); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Manages the showing and hiding of the sidebar. +$(document).ready(function () { + var sidebar = $("#documenter > .docs-sidebar"); + var sidebar_button = $("#documenter-sidebar-button"); + sidebar_button.click(function (ev) { + ev.preventDefault(); + sidebar.toggleClass("visible"); + if (sidebar.hasClass("visible")) { + // Makes sure that the current menu item is visible in the sidebar. + $("#documenter .docs-menu a.is-active").focus(); + } + }); + $("#documenter > .docs-main").bind("click", function (ev) { + if ($(ev.target).is(sidebar_button)) { + return; + } + if (sidebar.hasClass("visible")) { + sidebar.removeClass("visible"); + } + }); +}); + +// Resizes the package name / sitename in the sidebar if it is too wide. +// Inspired by: https://github.com/davatron5000/FitText.js +$(document).ready(function () { + e = $("#documenter .docs-autofit"); + function resize() { + var L = parseInt(e.css("max-width"), 10); + var L0 = e.width(); + if (L0 > L) { + var h0 = parseInt(e.css("font-size"), 10); + e.css("font-size", (L * h0) / L0); + // TODO: make sure it survives resizes? + } + } + // call once and then register events + resize(); + $(window).resize(resize); + $(window).on("orientationchange", resize); +}); + +// Scroll the navigation bar to the currently selected menu item +$(document).ready(function () { + var sidebar = $("#documenter .docs-menu").get(0); + var active = $("#documenter .docs-menu .is-active").get(0); + if (typeof active !== "undefined") { + sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15; + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Theme picker setup +$(document).ready(function () { + // onchange callback + $("#documenter-themepicker").change(function themepick_callback(ev) { + var themename = $("#documenter-themepicker option:selected").attr("value"); + if (themename === "auto") { + // set_theme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + window.localStorage.removeItem("documenter-theme"); + } else { + // set_theme(themename); + window.localStorage.setItem("documenter-theme", themename); + } + // We re-use the global function from themeswap.js to actually do the swapping. + set_theme_from_local_storage(); + }); + + // Make sure that the themepicker displays the correct theme when the theme is retrieved + // from localStorage + if (typeof window.localStorage !== "undefined") { + var theme = window.localStorage.getItem("documenter-theme"); + if (theme !== null) { + $("#documenter-themepicker option").each(function (i, e) { + e.selected = e.value === theme; + }); + } + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// update the version selector with info from the siteinfo.js and ../versions.js files +$(document).ready(function () { + // If the version selector is disabled with DOCUMENTER_VERSION_SELECTOR_DISABLED in the + // siteinfo.js file, we just return immediately and not display the version selector. + if ( + typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === "boolean" && + DOCUMENTER_VERSION_SELECTOR_DISABLED + ) { + return; + } + + var version_selector = $("#documenter .docs-version-selector"); + var version_selector_select = $("#documenter .docs-version-selector select"); + + version_selector_select.change(function (x) { + target_href = version_selector_select + .children("option:selected") + .get(0).value; + window.location.href = target_href; + }); + + // add the current version to the selector based on siteinfo.js, but only if the selector is empty + if ( + typeof DOCUMENTER_CURRENT_VERSION !== "undefined" && + $("#version-selector > option").length == 0 + ) { + var option = $( + "" + ); + version_selector_select.append(option); + } + + if (typeof DOC_VERSIONS !== "undefined") { + var existing_versions = version_selector_select.children("option"); + var existing_versions_texts = existing_versions.map(function (i, x) { + return x.text; + }); + DOC_VERSIONS.forEach(function (each) { + var version_url = documenterBaseURL + "/../" + each + "/"; + var existing_id = $.inArray(each, existing_versions_texts); + // if not already in the version selector, add it as a new option, + // otherwise update the old option with the URL and enable it + if (existing_id == -1) { + var option = $( + "" + ); + version_selector_select.append(option); + } else { + var option = existing_versions[existing_id]; + option.value = version_url; + option.disabled = false; + } + }); + } + + // only show the version selector if the selector has been populated + if (version_selector_select.children("option").length > 0) { + version_selector.toggleClass("visible"); + } +}); + +}) diff --git a/previews/PR2418/assets/latency.png b/previews/PR2418/assets/latency.png new file mode 100644 index 0000000000000000000000000000000000000000..9b51f3b25fc63c559400a3fe628a33348b6e30ff GIT binary patch literal 25175 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,html.theme--documenter-dark .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus,html.theme--documenter-dark .pagination-ellipsis:focus,html.theme--documenter-dark .file-cta:focus,html.theme--documenter-dark .file-name:focus,html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .button:focus,html.theme--documenter-dark .is-focused.pagination-previous,html.theme--documenter-dark .is-focused.pagination-next,html.theme--documenter-dark .is-focused.pagination-link,html.theme--documenter-dark .is-focused.pagination-ellipsis,html.theme--documenter-dark .is-focused.file-cta,html.theme--documenter-dark .is-focused.file-name,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-focused.button,html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active,html.theme--documenter-dark .pagination-ellipsis:active,html.theme--documenter-dark .file-cta:active,html.theme--documenter-dark .file-name:active,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .button:active,html.theme--documenter-dark .is-active.pagination-previous,html.theme--documenter-dark .is-active.pagination-next,html.theme--documenter-dark .is-active.pagination-link,html.theme--documenter-dark .is-active.pagination-ellipsis,html.theme--documenter-dark .is-active.file-cta,html.theme--documenter-dark .is-active.file-name,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .is-active.button{outline:none}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-ellipsis[disabled],html.theme--documenter-dark .file-cta[disabled],html.theme--documenter-dark .file-name[disabled],html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--documenter-dark .pagination-next,html.theme--documenter-dark fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--documenter-dark .pagination-link,html.theme--documenter-dark fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--documenter-dark .file-cta,html.theme--documenter-dark fieldset[disabled] .file-cta,fieldset[disabled] html.theme--documenter-dark .file-name,html.theme--documenter-dark fieldset[disabled] .file-name,fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark fieldset[disabled] .select select,html.theme--documenter-dark .select fieldset[disabled] select,html.theme--documenter-dark fieldset[disabled] .textarea,html.theme--documenter-dark fieldset[disabled] .input,html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--documenter-dark .button,html.theme--documenter-dark fieldset[disabled] .button{cursor:not-allowed}html.theme--documenter-dark .tabs,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .breadcrumb,html.theme--documenter-dark .file,html.theme--documenter-dark .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after,html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--documenter-dark .admonition:not(:last-child),html.theme--documenter-dark .tabs:not(:last-child),html.theme--documenter-dark .pagination:not(:last-child),html.theme--documenter-dark .message:not(:last-child),html.theme--documenter-dark .level:not(:last-child),html.theme--documenter-dark .breadcrumb:not(:last-child),html.theme--documenter-dark .block:not(:last-child),html.theme--documenter-dark .title:not(:last-child),html.theme--documenter-dark .subtitle:not(:last-child),html.theme--documenter-dark .table-container:not(:last-child),html.theme--documenter-dark .table:not(:last-child),html.theme--documenter-dark .progress:not(:last-child),html.theme--documenter-dark .notification:not(:last-child),html.theme--documenter-dark .content:not(:last-child),html.theme--documenter-dark .box:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before,html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before{height:2px;width:50%}html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{height:50%;width:2px}html.theme--documenter-dark .modal-close:hover,html.theme--documenter-dark .delete:hover,html.theme--documenter-dark .modal-close:focus,html.theme--documenter-dark .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--documenter-dark .modal-close:active,html.theme--documenter-dark .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--documenter-dark .is-small.modal-close,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--documenter-dark .is-small.delete,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--documenter-dark .is-medium.modal-close,html.theme--documenter-dark .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--documenter-dark .is-large.modal-close,html.theme--documenter-dark .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--documenter-dark .control.is-loading::after,html.theme--documenter-dark .select.is-loading::after,html.theme--documenter-dark .loader,html.theme--documenter-dark .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdee0;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--documenter-dark .hero-video,html.theme--documenter-dark .modal-background,html.theme--documenter-dark .modal,html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--documenter-dark .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#ecf0f1 !important}a.has-text-light:hover,a.has-text-light:focus{color:#cfd9db !important}.has-background-light{background-color:#ecf0f1 !important}.has-text-dark{color:#282f2f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#111414 !important}.has-background-dark{background-color:#282f2f !important}.has-text-primary{color:#375a7f !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#28415b !important}.has-background-primary{background-color:#375a7f !important}.has-text-primary-light{color:#f1f5f9 !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#cddbe9 !important}.has-background-primary-light{background-color:#f1f5f9 !important}.has-text-primary-dark{color:#4d7eb2 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#7198c1 !important}.has-background-primary-dark{background-color:#4d7eb2 !important}.has-text-link{color:#1abc9c !important}a.has-text-link:hover,a.has-text-link:focus{color:#148f77 !important}.has-background-link{background-color:#1abc9c !important}.has-text-link-light{color:#edfdf9 !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c0f6ec !important}.has-background-link-light{background-color:#edfdf9 !important}.has-text-link-dark{color:#15987e !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#1bc5a4 !important}.has-background-link-dark{background-color:#15987e !important}.has-text-info{color:#024c7d !important}a.has-text-info:hover,a.has-text-info:focus{color:#012d4b !important}.has-background-info{background-color:#024c7d !important}.has-text-info-light{color:#ebf7ff !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#b9e2fe !important}.has-background-info-light{background-color:#ebf7ff !important}.has-text-info-dark{color:#0e9dfb !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#40b1fc !important}.has-background-info-dark{background-color:#0e9dfb !important}.has-text-success{color:#008438 !important}a.has-text-success:hover,a.has-text-success:focus{color:#005122 !important}.has-background-success{background-color:#008438 !important}.has-text-success-light{color:#ebfff3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#b8ffd6 !important}.has-background-success-light{background-color:#ebfff3 !important}.has-text-success-dark{color:#00eb64 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#1fff7e !important}.has-background-success-dark{background-color:#00eb64 !important}.has-text-warning{color:#ad8100 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#7a5b00 !important}.has-background-warning{background-color:#ad8100 !important}.has-text-warning-light{color:#fffaeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#ffedb8 !important}.has-background-warning-light{background-color:#fffaeb !important}.has-text-warning-dark{color:#d19c00 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#ffbf05 !important}.has-background-warning-dark{background-color:#d19c00 !important}.has-text-danger{color:#9e1b0d !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#6f1309 !important}.has-background-danger{background-color:#9e1b0d !important}.has-text-danger-light{color:#fdeeec !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#fac3bd !important}.has-background-danger-light{background-color:#fdeeec !important}.has-text-danger-dark{color:#ec311d !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#f05c4c !important}.has-background-danger-dark{background-color:#ec311d !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#282f2f !important}.has-background-grey-darker{background-color:#282f2f !important}.has-text-grey-dark{color:#343c3d !important}.has-background-grey-dark{background-color:#343c3d !important}.has-text-grey{color:#5e6d6f !important}.has-background-grey{background-color:#5e6d6f !important}.has-text-grey-light{color:#8c9b9d !important}.has-background-grey-light{background-color:#8c9b9d !important}.has-text-grey-lighter{color:#dbdee0 !important}.has-background-grey-lighter{background-color:#dbdee0 !important}.has-text-white-ter{color:#ecf0f1 !important}.has-background-white-ter{background-color:#ecf0f1 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--documenter-dark{/*! + Theme: a11y-dark + Author: @ericwbailey + Maintainer: @ericwbailey + + Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css +*/}html.theme--documenter-dark html{background-color:#1f2424;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark article,html.theme--documenter-dark aside,html.theme--documenter-dark figure,html.theme--documenter-dark footer,html.theme--documenter-dark header,html.theme--documenter-dark hgroup,html.theme--documenter-dark section{display:block}html.theme--documenter-dark body,html.theme--documenter-dark button,html.theme--documenter-dark input,html.theme--documenter-dark optgroup,html.theme--documenter-dark select,html.theme--documenter-dark textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--documenter-dark code,html.theme--documenter-dark pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark body{color:#fff;font-size:1em;font-weight:400;line-height:1.5}html.theme--documenter-dark a{color:#1abc9c;cursor:pointer;text-decoration:none}html.theme--documenter-dark a strong{color:currentColor}html.theme--documenter-dark a:hover{color:#1dd2af}html.theme--documenter-dark code{background-color:rgba(255,255,255,0.05);color:#ececec;font-size:.875em;font-weight:normal;padding:.1em}html.theme--documenter-dark hr{background-color:#282f2f;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--documenter-dark img{height:auto;max-width:100%}html.theme--documenter-dark input[type="checkbox"],html.theme--documenter-dark input[type="radio"]{vertical-align:baseline}html.theme--documenter-dark small{font-size:.875em}html.theme--documenter-dark span{font-style:inherit;font-weight:inherit}html.theme--documenter-dark strong{color:#f2f2f2;font-weight:700}html.theme--documenter-dark fieldset{border:none}html.theme--documenter-dark pre{-webkit-overflow-scrolling:touch;background-color:#282f2f;color:#fff;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--documenter-dark pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--documenter-dark table td,html.theme--documenter-dark table th{vertical-align:top}html.theme--documenter-dark table td:not([align]),html.theme--documenter-dark table th:not([align]){text-align:inherit}html.theme--documenter-dark table th{color:#f2f2f2}html.theme--documenter-dark .box{background-color:#343c3d;border-radius:8px;box-shadow:none;color:#fff;display:block;padding:1.25rem}html.theme--documenter-dark a.box:hover,html.theme--documenter-dark a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #1abc9c}html.theme--documenter-dark a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1abc9c}html.theme--documenter-dark .button{background-color:#282f2f;border-color:#4c5759;border-width:1px;color:#375a7f;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--documenter-dark .button strong{color:inherit}html.theme--documenter-dark .button .icon,html.theme--documenter-dark .button .icon.is-small,html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--documenter-dark .button .icon.is-medium,html.theme--documenter-dark .button .icon.is-large{height:1.5em;width:1.5em}html.theme--documenter-dark .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--documenter-dark .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button:hover,html.theme--documenter-dark .button.is-hovered{border-color:#8c9b9d;color:#f2f2f2}html.theme--documenter-dark .button:focus,html.theme--documenter-dark .button.is-focused{border-color:#8c9b9d;color:#17a689}html.theme--documenter-dark .button:focus:not(:active),html.theme--documenter-dark .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button:active,html.theme--documenter-dark .button.is-active{border-color:#343c3d;color:#f2f2f2}html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;color:#fff;text-decoration:underline}html.theme--documenter-dark .button.is-text:hover,html.theme--documenter-dark .button.is-text.is-hovered,html.theme--documenter-dark .button.is-text:focus,html.theme--documenter-dark .button.is-text.is-focused{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .button.is-text:active,html.theme--documenter-dark .button.is-text.is-active{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .button.is-text[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#1abc9c;text-decoration:none}html.theme--documenter-dark .button.is-ghost:hover,html.theme--documenter-dark .button.is-ghost.is-hovered{color:#1abc9c;text-decoration:underline}html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:hover,html.theme--documenter-dark .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus,html.theme--documenter-dark .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus:not(:active),html.theme--documenter-dark .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--documenter-dark .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-white.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:hover,html.theme--documenter-dark .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus,html.theme--documenter-dark .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus:not(:active),html.theme--documenter-dark .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:hover,html.theme--documenter-dark .button.is-light.is-hovered{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus,html.theme--documenter-dark .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus:not(:active),html.theme--documenter-dark .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light.is-active{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:#ecf0f1;box-shadow:none}html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-outlined.is-focused{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-dark,html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover,html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus:not(:active),html.theme--documenter-dark .content kbd.button:focus:not(:active),html.theme--documenter-dark .button.is-dark.is-focused:not(:active),html.theme--documenter-dark .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark[disabled],html.theme--documenter-dark .content kbd.button[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark,fieldset[disabled] html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:#282f2f;box-shadow:none}html.theme--documenter-dark .button.is-dark.is-inverted,html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted:hover,html.theme--documenter-dark .content kbd.button.is-inverted:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-dark.is-inverted[disabled],html.theme--documenter-dark .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-loading::after,html.theme--documenter-dark .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined,html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-outlined.is-focused{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus:not(:active),html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--documenter-dark .button.is-primary.is-focused:not(:active),html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary[disabled],html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;box-shadow:none}html.theme--documenter-dark .button.is-primary.is-inverted,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--documenter-dark .button.is-primary.is-inverted[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:hover,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-light.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e8eef5;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:active,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-light.is-active,html.theme--documenter-dark .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#dfe8f1;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:hover,html.theme--documenter-dark .button.is-link.is-hovered{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus,html.theme--documenter-dark .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus:not(:active),html.theme--documenter-dark .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link.is-active{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:#1abc9c;box-shadow:none}html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-outlined.is-focused{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:hover,html.theme--documenter-dark .button.is-link.is-light.is-hovered{background-color:#e2fbf6;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:active,html.theme--documenter-dark .button.is-link.is-light.is-active{background-color:#d7f9f3;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:hover,html.theme--documenter-dark .button.is-info.is-hovered{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus,html.theme--documenter-dark .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus:not(:active),html.theme--documenter-dark .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info.is-active{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:#024c7d;box-shadow:none}html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;color:#024c7d}html.theme--documenter-dark .button.is-info.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-outlined.is-focused{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:hover,html.theme--documenter-dark .button.is-info.is-light.is-hovered{background-color:#def2fe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:active,html.theme--documenter-dark .button.is-info.is-light.is-active{background-color:#d2edfe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:hover,html.theme--documenter-dark .button.is-success.is-hovered{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus,html.theme--documenter-dark .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus:not(:active),html.theme--documenter-dark .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success.is-active{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:#008438;box-shadow:none}html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;color:#008438}html.theme--documenter-dark .button.is-success.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-outlined.is-focused{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:hover,html.theme--documenter-dark .button.is-success.is-light.is-hovered{background-color:#deffec;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:active,html.theme--documenter-dark .button.is-success.is-light.is-active{background-color:#d1ffe5;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:hover,html.theme--documenter-dark .button.is-warning.is-hovered{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus,html.theme--documenter-dark .button.is-warning.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus:not(:active),html.theme--documenter-dark .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning.is-active{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:#ad8100;box-shadow:none}html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-outlined.is-focused{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:hover,html.theme--documenter-dark .button.is-warning.is-light.is-hovered{background-color:#fff7de;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:active,html.theme--documenter-dark .button.is-warning.is-light.is-active{background-color:#fff3d1;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:hover,html.theme--documenter-dark .button.is-danger.is-hovered{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus,html.theme--documenter-dark .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus:not(:active),html.theme--documenter-dark .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger.is-active{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;box-shadow:none}html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-outlined.is-focused{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:hover,html.theme--documenter-dark .button.is-danger.is-light.is-hovered{background-color:#fce3e0;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:active,html.theme--documenter-dark .button.is-danger.is-light.is-active{background-color:#fcd8d5;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--documenter-dark .button.is-small:not(.is-rounded),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--documenter-dark .button.is-normal{font-size:1rem}html.theme--documenter-dark .button.is-medium{font-size:1.25rem}html.theme--documenter-dark .button.is-large{font-size:1.5rem}html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .button{background-color:#8c9b9d;border-color:#5e6d6f;box-shadow:none;opacity:.5}html.theme--documenter-dark .button.is-fullwidth{display:flex;width:100%}html.theme--documenter-dark .button.is-loading{color:transparent !important;pointer-events:none}html.theme--documenter-dark .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--documenter-dark .button.is-static{background-color:#282f2f;border-color:#5e6d6f;color:#dbdee0;box-shadow:none;pointer-events:none}html.theme--documenter-dark .button.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--documenter-dark .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .buttons .button{margin-bottom:0.5rem}html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--documenter-dark .buttons:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .buttons:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--documenter-dark .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--documenter-dark .buttons.has-addons .button:last-child{margin-right:0}html.theme--documenter-dark .buttons.has-addons .button:hover,html.theme--documenter-dark .buttons.has-addons .button.is-hovered{z-index:2}html.theme--documenter-dark .buttons.has-addons .button:focus,html.theme--documenter-dark .buttons.has-addons .button.is-focused,html.theme--documenter-dark .buttons.has-addons .button:active,html.theme--documenter-dark .buttons.has-addons .button.is-active,html.theme--documenter-dark .buttons.has-addons .button.is-selected{z-index:3}html.theme--documenter-dark .buttons.has-addons .button:focus:hover,html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover,html.theme--documenter-dark .buttons.has-addons .button:active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--documenter-dark .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .buttons.is-centered{justify-content:center}html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .buttons.is-right{justify-content:flex-end}html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:1rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1.25rem}}html.theme--documenter-dark .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--documenter-dark .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--documenter-dark .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--documenter-dark .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--documenter-dark .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--documenter-dark .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--documenter-dark .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--documenter-dark .content li+li{margin-top:0.25em}html.theme--documenter-dark .content p:not(:last-child),html.theme--documenter-dark .content dl:not(:last-child),html.theme--documenter-dark .content ol:not(:last-child),html.theme--documenter-dark .content ul:not(:last-child),html.theme--documenter-dark .content blockquote:not(:last-child),html.theme--documenter-dark .content pre:not(:last-child),html.theme--documenter-dark .content table:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .content h1,html.theme--documenter-dark .content h2,html.theme--documenter-dark .content h3,html.theme--documenter-dark .content h4,html.theme--documenter-dark .content h5,html.theme--documenter-dark .content h6{color:#f2f2f2;font-weight:600;line-height:1.125}html.theme--documenter-dark .content h1{font-size:2em;margin-bottom:0.5em}html.theme--documenter-dark .content h1:not(:first-child){margin-top:1em}html.theme--documenter-dark .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--documenter-dark .content h2:not(:first-child){margin-top:1.1428em}html.theme--documenter-dark .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--documenter-dark .content h3:not(:first-child){margin-top:1.3333em}html.theme--documenter-dark .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--documenter-dark .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--documenter-dark .content h6{font-size:1em;margin-bottom:1em}html.theme--documenter-dark .content blockquote{background-color:#282f2f;border-left:5px solid #5e6d6f;padding:1.25em 1.5em}html.theme--documenter-dark .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ol:not([type]){list-style-type:decimal}html.theme--documenter-dark .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--documenter-dark .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--documenter-dark .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--documenter-dark .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--documenter-dark .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--documenter-dark .content ul ul ul{list-style-type:square}html.theme--documenter-dark .content dd{margin-left:2em}html.theme--documenter-dark .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--documenter-dark .content figure:not(:first-child){margin-top:2em}html.theme--documenter-dark .content figure:not(:last-child){margin-bottom:2em}html.theme--documenter-dark .content figure img{display:inline-block}html.theme--documenter-dark .content figure figcaption{font-style:italic}html.theme--documenter-dark .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--documenter-dark .content sup,html.theme--documenter-dark .content sub{font-size:75%}html.theme--documenter-dark .content table{width:100%}html.theme--documenter-dark .content table td,html.theme--documenter-dark .content table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .content table th{color:#f2f2f2}html.theme--documenter-dark .content table th:not([align]){text-align:inherit}html.theme--documenter-dark .content table thead td,html.theme--documenter-dark .content table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .content table tfoot td,html.theme--documenter-dark .content table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .content table tbody tr:last-child td,html.theme--documenter-dark .content table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .content .tabs li+li{margin-top:0}html.theme--documenter-dark .content.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--documenter-dark .content.is-normal{font-size:1rem}html.theme--documenter-dark .content.is-medium{font-size:1.25rem}html.theme--documenter-dark .content.is-large{font-size:1.5rem}html.theme--documenter-dark .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--documenter-dark .icon.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--documenter-dark .icon.is-medium{height:2rem;width:2rem}html.theme--documenter-dark .icon.is-large{height:3rem;width:3rem}html.theme--documenter-dark .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--documenter-dark .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--documenter-dark .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--documenter-dark div.icon-text{display:flex}html.theme--documenter-dark .image,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--documenter-dark .image img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--documenter-dark .image img.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--documenter-dark .image.is-fullwidth,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--documenter-dark .image.is-square,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--documenter-dark .image.is-1by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--documenter-dark .image.is-5by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--documenter-dark .image.is-4by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--documenter-dark .image.is-3by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--documenter-dark .image.is-5by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--documenter-dark .image.is-16by9,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--documenter-dark .image.is-2by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--documenter-dark .image.is-3by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--documenter-dark .image.is-4by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--documenter-dark .image.is-3by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--documenter-dark .image.is-2by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--documenter-dark .image.is-3by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--documenter-dark .image.is-9by16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--documenter-dark .image.is-1by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--documenter-dark .image.is-1by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--documenter-dark .image.is-16x16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--documenter-dark .image.is-24x24,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--documenter-dark .image.is-32x32,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--documenter-dark .image.is-48x48,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--documenter-dark .image.is-64x64,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--documenter-dark .image.is-96x96,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--documenter-dark .image.is-128x128,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--documenter-dark .notification{background-color:#282f2f;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .notification strong{color:currentColor}html.theme--documenter-dark .notification code,html.theme--documenter-dark .notification pre{background:#fff}html.theme--documenter-dark .notification pre code{background:transparent}html.theme--documenter-dark .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--documenter-dark .notification .title,html.theme--documenter-dark .notification .subtitle,html.theme--documenter-dark .notification .content{color:currentColor}html.theme--documenter-dark .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .notification.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .notification.is-dark,html.theme--documenter-dark .content kbd.notification{background-color:#282f2f;color:#fff}html.theme--documenter-dark .notification.is-primary,html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .notification.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .notification.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .notification.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .notification.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .notification.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .notification.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .notification.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .notification.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .notification.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .notification.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .notification.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--documenter-dark .progress::-webkit-progress-bar{background-color:#343c3d}html.theme--documenter-dark .progress::-webkit-progress-value{background-color:#dbdee0}html.theme--documenter-dark .progress::-moz-progress-bar{background-color:#dbdee0}html.theme--documenter-dark .progress::-ms-fill{background-color:#dbdee0;border:none}html.theme--documenter-dark .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--documenter-dark .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--documenter-dark .progress.is-white::-ms-fill{background-color:#fff}html.theme--documenter-dark .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-light::-webkit-progress-value{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-moz-progress-bar{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-ms-fill{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light:indeterminate{background-image:linear-gradient(to right, #ecf0f1 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-dark::-webkit-progress-value,html.theme--documenter-dark .content kbd.progress::-webkit-progress-value{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-moz-progress-bar,html.theme--documenter-dark .content kbd.progress::-moz-progress-bar{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-ms-fill,html.theme--documenter-dark .content kbd.progress::-ms-fill{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark:indeterminate,html.theme--documenter-dark .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #282f2f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-primary::-webkit-progress-value,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-moz-progress-bar,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-ms-fill,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary:indeterminate,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #375a7f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-link::-webkit-progress-value{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-moz-progress-bar{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-ms-fill{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1abc9c 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-info::-webkit-progress-value{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-moz-progress-bar{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-ms-fill{background-color:#024c7d}html.theme--documenter-dark .progress.is-info:indeterminate{background-image:linear-gradient(to right, #024c7d 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-success::-webkit-progress-value{background-color:#008438}html.theme--documenter-dark .progress.is-success::-moz-progress-bar{background-color:#008438}html.theme--documenter-dark .progress.is-success::-ms-fill{background-color:#008438}html.theme--documenter-dark .progress.is-success:indeterminate{background-image:linear-gradient(to right, #008438 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-warning::-webkit-progress-value{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-moz-progress-bar{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-ms-fill{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ad8100 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-danger::-webkit-progress-value{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-moz-progress-bar{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-ms-fill{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #9e1b0d 30%, #343c3d 30%)}html.theme--documenter-dark .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#343c3d;background-image:linear-gradient(to right, #fff 30%, #343c3d 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-ms-fill{animation-name:none}html.theme--documenter-dark .progress.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--documenter-dark .progress.is-medium{height:1.25rem}html.theme--documenter-dark .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--documenter-dark .table{background-color:#343c3d;color:#fff}html.theme--documenter-dark .table td,html.theme--documenter-dark .table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .table td.is-white,html.theme--documenter-dark .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .table td.is-black,html.theme--documenter-dark .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .table td.is-light,html.theme--documenter-dark .table th.is-light{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .table td.is-dark,html.theme--documenter-dark .table th.is-dark{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .table td.is-primary,html.theme--documenter-dark .table th.is-primary{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-link,html.theme--documenter-dark .table th.is-link{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .table td.is-info,html.theme--documenter-dark .table th.is-info{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .table td.is-success,html.theme--documenter-dark .table th.is-success{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .table td.is-warning,html.theme--documenter-dark .table th.is-warning{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .table td.is-danger,html.theme--documenter-dark .table th.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .table td.is-narrow,html.theme--documenter-dark .table th.is-narrow{white-space:nowrap;width:1%}html.theme--documenter-dark .table td.is-selected,html.theme--documenter-dark .table th.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-selected a,html.theme--documenter-dark .table td.is-selected strong,html.theme--documenter-dark .table th.is-selected a,html.theme--documenter-dark .table th.is-selected strong{color:currentColor}html.theme--documenter-dark .table td.is-vcentered,html.theme--documenter-dark .table th.is-vcentered{vertical-align:middle}html.theme--documenter-dark .table th{color:#f2f2f2}html.theme--documenter-dark .table th:not([align]){text-align:left}html.theme--documenter-dark .table tr.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table tr.is-selected a,html.theme--documenter-dark .table tr.is-selected strong{color:currentColor}html.theme--documenter-dark .table tr.is-selected td,html.theme--documenter-dark .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--documenter-dark .table thead{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table thead td,html.theme--documenter-dark .table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .table tfoot{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tfoot td,html.theme--documenter-dark .table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .table tbody{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tbody tr:last-child td,html.theme--documenter-dark .table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .table.is-bordered td,html.theme--documenter-dark .table.is-bordered th{border-width:1px}html.theme--documenter-dark .table.is-bordered tr:last-child td,html.theme--documenter-dark .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--documenter-dark .table.is-fullwidth{width:100%}html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#2d3435}html.theme--documenter-dark .table.is-narrow td,html.theme--documenter-dark .table.is-narrow th{padding:0.25em 0.5em}html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#282f2f}html.theme--documenter-dark .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--documenter-dark .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .tags .tag,html.theme--documenter-dark .tags .content kbd,html.theme--documenter-dark .content .tags kbd,html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--documenter-dark .tags .tag:not(:last-child),html.theme--documenter-dark .tags .content kbd:not(:last-child),html.theme--documenter-dark .content .tags kbd:not(:last-child),html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--documenter-dark .tags:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .tags:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--documenter-dark .tags.is-centered{justify-content:center}html.theme--documenter-dark .tags.is-centered .tag,html.theme--documenter-dark .tags.is-centered .content kbd,html.theme--documenter-dark .content .tags.is-centered kbd,html.theme--documenter-dark .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--documenter-dark .tags.is-right{justify-content:flex-end}html.theme--documenter-dark .tags.is-right .tag:not(:first-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--documenter-dark .tags.is-right .tag:not(:last-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--documenter-dark .tags.has-addons .tag,html.theme--documenter-dark .tags.has-addons .content kbd,html.theme--documenter-dark .content .tags.has-addons kbd,html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--documenter-dark .tags.has-addons .tag:not(:first-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--documenter-dark .tags.has-addons .tag:not(:last-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--documenter-dark .tag:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#282f2f;border-radius:.4em;color:#fff;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .tag:not(body) .delete,html.theme--documenter-dark .content kbd:not(body) .delete,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--documenter-dark .tag.is-white:not(body),html.theme--documenter-dark .content kbd.is-white:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .tag.is-black:not(body),html.theme--documenter-dark .content kbd.is-black:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .tag.is-light:not(body),html.theme--documenter-dark .content kbd.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .tag.is-dark:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--documenter-dark .content .docstring>section>kbd:not(body){background-color:#282f2f;color:#fff}html.theme--documenter-dark .tag.is-primary:not(body),html.theme--documenter-dark .content kbd.is-primary:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){background-color:#375a7f;color:#fff}html.theme--documenter-dark .tag.is-primary.is-light:not(body),html.theme--documenter-dark .content kbd.is-primary.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .tag.is-link:not(body),html.theme--documenter-dark .content kbd.is-link:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1abc9c;color:#fff}html.theme--documenter-dark .tag.is-link.is-light:not(body),html.theme--documenter-dark .content kbd.is-link.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .tag.is-info:not(body),html.theme--documenter-dark .content kbd.is-info:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#024c7d;color:#fff}html.theme--documenter-dark .tag.is-info.is-light:not(body),html.theme--documenter-dark .content kbd.is-info.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .tag.is-success:not(body),html.theme--documenter-dark .content kbd.is-success:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#008438;color:#fff}html.theme--documenter-dark .tag.is-success.is-light:not(body),html.theme--documenter-dark .content kbd.is-success.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .tag.is-warning:not(body),html.theme--documenter-dark .content kbd.is-warning:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ad8100;color:#fff}html.theme--documenter-dark .tag.is-warning.is-light:not(body),html.theme--documenter-dark .content kbd.is-warning.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .tag.is-danger:not(body),html.theme--documenter-dark .content kbd.is-danger:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .tag.is-danger.is-light:not(body),html.theme--documenter-dark .content kbd.is-danger.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .tag.is-normal:not(body),html.theme--documenter-dark .content kbd.is-normal:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--documenter-dark .tag.is-medium:not(body),html.theme--documenter-dark .content kbd.is-medium:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--documenter-dark .tag.is-large:not(body),html.theme--documenter-dark .content kbd.is-large:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child,html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--documenter-dark .tag.is-delete:not(body),html.theme--documenter-dark .content kbd.is-delete:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--documenter-dark .tag.is-delete:not(body):hover,html.theme--documenter-dark .content kbd.is-delete:not(body):hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--documenter-dark .tag.is-delete:not(body):focus,html.theme--documenter-dark .content kbd.is-delete:not(body):focus,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1d2122}html.theme--documenter-dark .tag.is-delete:not(body):active,html.theme--documenter-dark .content kbd.is-delete:not(body):active,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#111414}html.theme--documenter-dark .tag.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--documenter-dark .content kbd.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--documenter-dark a.tag:hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--documenter-dark .title,html.theme--documenter-dark .subtitle{word-break:break-word}html.theme--documenter-dark .title em,html.theme--documenter-dark .title span,html.theme--documenter-dark .subtitle em,html.theme--documenter-dark .subtitle span{font-weight:inherit}html.theme--documenter-dark .title sub,html.theme--documenter-dark .subtitle sub{font-size:.75em}html.theme--documenter-dark .title sup,html.theme--documenter-dark .subtitle sup{font-size:.75em}html.theme--documenter-dark .title .tag,html.theme--documenter-dark .title .content kbd,html.theme--documenter-dark .content .title kbd,html.theme--documenter-dark .title .docstring>section>a.docs-sourcelink,html.theme--documenter-dark .subtitle .tag,html.theme--documenter-dark .subtitle .content kbd,html.theme--documenter-dark .content .subtitle kbd,html.theme--documenter-dark .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--documenter-dark .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--documenter-dark .title strong{color:inherit;font-weight:inherit}html.theme--documenter-dark .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--documenter-dark .title.is-1{font-size:3rem}html.theme--documenter-dark .title.is-2{font-size:2.5rem}html.theme--documenter-dark .title.is-3{font-size:2rem}html.theme--documenter-dark .title.is-4{font-size:1.5rem}html.theme--documenter-dark .title.is-5{font-size:1.25rem}html.theme--documenter-dark .title.is-6{font-size:1rem}html.theme--documenter-dark .title.is-7{font-size:.75rem}html.theme--documenter-dark .subtitle{color:#8c9b9d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--documenter-dark .subtitle strong{color:#8c9b9d;font-weight:600}html.theme--documenter-dark .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--documenter-dark .subtitle.is-1{font-size:3rem}html.theme--documenter-dark .subtitle.is-2{font-size:2.5rem}html.theme--documenter-dark .subtitle.is-3{font-size:2rem}html.theme--documenter-dark .subtitle.is-4{font-size:1.5rem}html.theme--documenter-dark .subtitle.is-5{font-size:1.25rem}html.theme--documenter-dark .subtitle.is-6{font-size:1rem}html.theme--documenter-dark .subtitle.is-7{font-size:.75rem}html.theme--documenter-dark .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--documenter-dark .number{align-items:center;background-color:#282f2f;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#1f2424;border-color:#5e6d6f;border-radius:.4em;color:#dbdee0}html.theme--documenter-dark .select select::-moz-placeholder,html.theme--documenter-dark .textarea::-moz-placeholder,html.theme--documenter-dark .input::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select::-webkit-input-placeholder,html.theme--documenter-dark .textarea::-webkit-input-placeholder,html.theme--documenter-dark .input::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:-moz-placeholder,html.theme--documenter-dark .textarea:-moz-placeholder,html.theme--documenter-dark .input:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select:-ms-input-placeholder,html.theme--documenter-dark .textarea:-ms-input-placeholder,html.theme--documenter-dark .input:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:hover,html.theme--documenter-dark .textarea:hover,html.theme--documenter-dark .input:hover,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:hover,html.theme--documenter-dark .select select.is-hovered,html.theme--documenter-dark .is-hovered.textarea,html.theme--documenter-dark .is-hovered.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#8c9b9d}html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1abc9c;box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#8c9b9d;border-color:#282f2f;box-shadow:none;color:#fff}html.theme--documenter-dark .select select[disabled]::-moz-placeholder,html.theme--documenter-dark .textarea[disabled]::-moz-placeholder,html.theme--documenter-dark .input[disabled]::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-moz-placeholder,html.theme--documenter-dark .textarea[disabled]:-moz-placeholder,html.theme--documenter-dark .input[disabled]:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder,html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder,html.theme--documenter-dark .input[disabled]:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--documenter-dark .textarea[readonly],html.theme--documenter-dark .input[readonly],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--documenter-dark .is-white.textarea,html.theme--documenter-dark .is-white.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--documenter-dark .is-white.textarea:focus,html.theme--documenter-dark .is-white.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--documenter-dark .is-white.is-focused.textarea,html.theme--documenter-dark .is-white.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-white.textarea:active,html.theme--documenter-dark .is-white.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--documenter-dark .is-white.is-active.textarea,html.theme--documenter-dark .is-white.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .is-black.textarea,html.theme--documenter-dark .is-black.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--documenter-dark .is-black.textarea:focus,html.theme--documenter-dark .is-black.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--documenter-dark .is-black.is-focused.textarea,html.theme--documenter-dark .is-black.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-black.textarea:active,html.theme--documenter-dark .is-black.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--documenter-dark .is-black.is-active.textarea,html.theme--documenter-dark .is-black.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .is-light.textarea,html.theme--documenter-dark .is-light.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#ecf0f1}html.theme--documenter-dark .is-light.textarea:focus,html.theme--documenter-dark .is-light.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--documenter-dark .is-light.is-focused.textarea,html.theme--documenter-dark .is-light.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-light.textarea:active,html.theme--documenter-dark .is-light.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--documenter-dark .is-light.is-active.textarea,html.theme--documenter-dark .is-light.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .is-dark.textarea,html.theme--documenter-dark .content kbd.textarea,html.theme--documenter-dark .is-dark.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--documenter-dark .content kbd.input{border-color:#282f2f}html.theme--documenter-dark .is-dark.textarea:focus,html.theme--documenter-dark .content kbd.textarea:focus,html.theme--documenter-dark .is-dark.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--documenter-dark .content kbd.input:focus,html.theme--documenter-dark .is-dark.is-focused.textarea,html.theme--documenter-dark .content kbd.is-focused.textarea,html.theme--documenter-dark .is-dark.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .content kbd.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--documenter-dark .is-dark.textarea:active,html.theme--documenter-dark .content kbd.textarea:active,html.theme--documenter-dark .is-dark.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--documenter-dark .content kbd.input:active,html.theme--documenter-dark .is-dark.is-active.textarea,html.theme--documenter-dark .content kbd.is-active.textarea,html.theme--documenter-dark .is-dark.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .content kbd.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .is-primary.textarea,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink{border-color:#375a7f}html.theme--documenter-dark .is-primary.textarea:focus,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.is-focused.textarea,html.theme--documenter-dark .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--documenter-dark .is-primary.textarea:active,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:active,html.theme--documenter-dark .is-primary.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:active,html.theme--documenter-dark .is-primary.is-active.textarea,html.theme--documenter-dark .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .is-link.textarea,html.theme--documenter-dark .is-link.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1abc9c}html.theme--documenter-dark .is-link.textarea:focus,html.theme--documenter-dark .is-link.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--documenter-dark .is-link.is-focused.textarea,html.theme--documenter-dark .is-link.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-link.textarea:active,html.theme--documenter-dark .is-link.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--documenter-dark .is-link.is-active.textarea,html.theme--documenter-dark .is-link.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .is-info.textarea,html.theme--documenter-dark .is-info.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#024c7d}html.theme--documenter-dark .is-info.textarea:focus,html.theme--documenter-dark .is-info.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--documenter-dark .is-info.is-focused.textarea,html.theme--documenter-dark .is-info.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-info.textarea:active,html.theme--documenter-dark .is-info.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--documenter-dark .is-info.is-active.textarea,html.theme--documenter-dark .is-info.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .is-success.textarea,html.theme--documenter-dark .is-success.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#008438}html.theme--documenter-dark .is-success.textarea:focus,html.theme--documenter-dark .is-success.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--documenter-dark .is-success.is-focused.textarea,html.theme--documenter-dark .is-success.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-success.textarea:active,html.theme--documenter-dark .is-success.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--documenter-dark .is-success.is-active.textarea,html.theme--documenter-dark .is-success.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .is-warning.textarea,html.theme--documenter-dark .is-warning.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ad8100}html.theme--documenter-dark .is-warning.textarea:focus,html.theme--documenter-dark .is-warning.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--documenter-dark .is-warning.is-focused.textarea,html.theme--documenter-dark .is-warning.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-warning.textarea:active,html.theme--documenter-dark .is-warning.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--documenter-dark .is-warning.is-active.textarea,html.theme--documenter-dark .is-warning.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .is-danger.textarea,html.theme--documenter-dark .is-danger.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#9e1b0d}html.theme--documenter-dark .is-danger.textarea:focus,html.theme--documenter-dark .is-danger.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--documenter-dark .is-danger.is-focused.textarea,html.theme--documenter-dark .is-danger.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-danger.textarea:active,html.theme--documenter-dark .is-danger.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--documenter-dark .is-danger.is-active.textarea,html.theme--documenter-dark .is-danger.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .is-small.textarea,html.theme--documenter-dark .is-small.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .is-medium.textarea,html.theme--documenter-dark .is-medium.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--documenter-dark .is-large.textarea,html.theme--documenter-dark .is-large.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--documenter-dark .is-fullwidth.textarea,html.theme--documenter-dark .is-fullwidth.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--documenter-dark .is-inline.textarea,html.theme--documenter-dark .is-inline.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--documenter-dark .input.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--documenter-dark .input.is-static,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--documenter-dark .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--documenter-dark .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--documenter-dark .textarea[rows]{height:initial}html.theme--documenter-dark .textarea.has-fixed-size{resize:none}html.theme--documenter-dark .radio,html.theme--documenter-dark .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--documenter-dark .radio input,html.theme--documenter-dark .checkbox input{cursor:pointer}html.theme--documenter-dark .radio:hover,html.theme--documenter-dark .checkbox:hover{color:#8c9b9d}html.theme--documenter-dark .radio[disabled],html.theme--documenter-dark .checkbox[disabled],fieldset[disabled] html.theme--documenter-dark .radio,fieldset[disabled] html.theme--documenter-dark .checkbox,html.theme--documenter-dark .radio input[disabled],html.theme--documenter-dark .checkbox input[disabled]{color:#fff;cursor:not-allowed}html.theme--documenter-dark .radio+.radio{margin-left:.5em}html.theme--documenter-dark .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--documenter-dark .select:not(.is-multiple){height:2.5em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border-color:#1abc9c;right:1.125em;z-index:4}html.theme--documenter-dark .select.is-rounded select,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--documenter-dark .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--documenter-dark .select select::-ms-expand{display:none}html.theme--documenter-dark .select select[disabled]:hover,fieldset[disabled] html.theme--documenter-dark .select select:hover{border-color:#282f2f}html.theme--documenter-dark .select select:not([multiple]){padding-right:2.5em}html.theme--documenter-dark .select select[multiple]{height:auto;padding:0}html.theme--documenter-dark .select select[multiple] option{padding:0.5em 1em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#8c9b9d}html.theme--documenter-dark .select.is-white:not(:hover)::after{border-color:#fff}html.theme--documenter-dark .select.is-white select{border-color:#fff}html.theme--documenter-dark .select.is-white select:hover,html.theme--documenter-dark .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--documenter-dark .select.is-white select:focus,html.theme--documenter-dark .select.is-white select.is-focused,html.theme--documenter-dark .select.is-white select:active,html.theme--documenter-dark .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select:hover,html.theme--documenter-dark .select.is-black select.is-hovered{border-color:#000}html.theme--documenter-dark .select.is-black select:focus,html.theme--documenter-dark .select.is-black select.is-focused,html.theme--documenter-dark .select.is-black select:active,html.theme--documenter-dark .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .select.is-light:not(:hover)::after{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select:hover,html.theme--documenter-dark .select.is-light select.is-hovered{border-color:#dde4e6}html.theme--documenter-dark .select.is-light select:focus,html.theme--documenter-dark .select.is-light select.is-focused,html.theme--documenter-dark .select.is-light select:active,html.theme--documenter-dark .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .select.is-dark:not(:hover)::after,html.theme--documenter-dark .content kbd.select:not(:hover)::after{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select,html.theme--documenter-dark .content kbd.select select{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select:hover,html.theme--documenter-dark .content kbd.select select:hover,html.theme--documenter-dark .select.is-dark select.is-hovered,html.theme--documenter-dark .content kbd.select select.is-hovered{border-color:#1d2122}html.theme--documenter-dark .select.is-dark select:focus,html.theme--documenter-dark .content kbd.select select:focus,html.theme--documenter-dark .select.is-dark select.is-focused,html.theme--documenter-dark .content kbd.select select.is-focused,html.theme--documenter-dark .select.is-dark select:active,html.theme--documenter-dark .content kbd.select select:active,html.theme--documenter-dark .select.is-dark select.is-active,html.theme--documenter-dark .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .select.is-primary:not(:hover)::after,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select:hover,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:hover,html.theme--documenter-dark .select.is-primary select.is-hovered,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#2f4d6d}html.theme--documenter-dark .select.is-primary select:focus,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:focus,html.theme--documenter-dark .select.is-primary select.is-focused,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--documenter-dark .select.is-primary select:active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:active,html.theme--documenter-dark .select.is-primary select.is-active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .select.is-link:not(:hover)::after{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select:hover,html.theme--documenter-dark .select.is-link select.is-hovered{border-color:#17a689}html.theme--documenter-dark .select.is-link select:focus,html.theme--documenter-dark .select.is-link select.is-focused,html.theme--documenter-dark .select.is-link select:active,html.theme--documenter-dark .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select.is-info:not(:hover)::after{border-color:#024c7d}html.theme--documenter-dark .select.is-info select{border-color:#024c7d}html.theme--documenter-dark .select.is-info select:hover,html.theme--documenter-dark .select.is-info select.is-hovered{border-color:#023d64}html.theme--documenter-dark .select.is-info select:focus,html.theme--documenter-dark .select.is-info select.is-focused,html.theme--documenter-dark .select.is-info select:active,html.theme--documenter-dark .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .select.is-success:not(:hover)::after{border-color:#008438}html.theme--documenter-dark .select.is-success select{border-color:#008438}html.theme--documenter-dark .select.is-success select:hover,html.theme--documenter-dark .select.is-success select.is-hovered{border-color:#006b2d}html.theme--documenter-dark .select.is-success select:focus,html.theme--documenter-dark .select.is-success select.is-focused,html.theme--documenter-dark .select.is-success select:active,html.theme--documenter-dark .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .select.is-warning:not(:hover)::after{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select:hover,html.theme--documenter-dark .select.is-warning select.is-hovered{border-color:#946e00}html.theme--documenter-dark .select.is-warning select:focus,html.theme--documenter-dark .select.is-warning select.is-focused,html.theme--documenter-dark .select.is-warning select:active,html.theme--documenter-dark .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .select.is-danger:not(:hover)::after{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select:hover,html.theme--documenter-dark .select.is-danger select.is-hovered{border-color:#86170b}html.theme--documenter-dark .select.is-danger select:focus,html.theme--documenter-dark .select.is-danger select.is-focused,html.theme--documenter-dark .select.is-danger select:active,html.theme--documenter-dark .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .select.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .select.is-medium{font-size:1.25rem}html.theme--documenter-dark .select.is-large{font-size:1.5rem}html.theme--documenter-dark .select.is-disabled::after{border-color:#fff !important;opacity:0.5}html.theme--documenter-dark .select.is-fullwidth{width:100%}html.theme--documenter-dark .select.is-fullwidth select{width:100%}html.theme--documenter-dark .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--documenter-dark .select.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .select.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--documenter-dark .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:hover .file-cta,html.theme--documenter-dark .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:focus .file-cta,html.theme--documenter-dark .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--documenter-dark .file.is-white:active .file-cta,html.theme--documenter-dark .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:hover .file-cta,html.theme--documenter-dark .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:focus .file-cta,html.theme--documenter-dark .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--documenter-dark .file.is-black:active .file-cta,html.theme--documenter-dark .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-light .file-cta{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:hover .file-cta,html.theme--documenter-dark .file.is-light.is-hovered .file-cta{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:focus .file-cta,html.theme--documenter-dark .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(236,240,241,0.25);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:active .file-cta,html.theme--documenter-dark .file.is-light.is-active .file-cta{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-dark .file-cta,html.theme--documenter-dark .content kbd.file .file-cta{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:hover .file-cta,html.theme--documenter-dark .content kbd.file:hover .file-cta,html.theme--documenter-dark .file.is-dark.is-hovered .file-cta,html.theme--documenter-dark .content kbd.file.is-hovered .file-cta{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:focus .file-cta,html.theme--documenter-dark .content kbd.file:focus .file-cta,html.theme--documenter-dark .file.is-dark.is-focused .file-cta,html.theme--documenter-dark .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(40,47,47,0.25);color:#fff}html.theme--documenter-dark .file.is-dark:active .file-cta,html.theme--documenter-dark .content kbd.file:active .file-cta,html.theme--documenter-dark .file.is-dark.is-active .file-cta,html.theme--documenter-dark .content kbd.file.is-active .file-cta{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:hover .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--documenter-dark .file.is-primary.is-hovered .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:focus .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--documenter-dark .file.is-primary.is-focused .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(55,90,127,0.25);color:#fff}html.theme--documenter-dark .file.is-primary:active .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--documenter-dark .file.is-primary.is-active .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link .file-cta{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:hover .file-cta,html.theme--documenter-dark .file.is-link.is-hovered .file-cta{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:focus .file-cta,html.theme--documenter-dark .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(26,188,156,0.25);color:#fff}html.theme--documenter-dark .file.is-link:active .file-cta,html.theme--documenter-dark .file.is-link.is-active .file-cta{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info .file-cta{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:hover .file-cta,html.theme--documenter-dark .file.is-info.is-hovered .file-cta{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:focus .file-cta,html.theme--documenter-dark .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(2,76,125,0.25);color:#fff}html.theme--documenter-dark .file.is-info:active .file-cta,html.theme--documenter-dark .file.is-info.is-active .file-cta{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success .file-cta{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:hover .file-cta,html.theme--documenter-dark .file.is-success.is-hovered .file-cta{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:focus .file-cta,html.theme--documenter-dark .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(0,132,56,0.25);color:#fff}html.theme--documenter-dark .file.is-success:active .file-cta,html.theme--documenter-dark .file.is-success.is-active .file-cta{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning .file-cta{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:hover .file-cta,html.theme--documenter-dark .file.is-warning.is-hovered .file-cta{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:focus .file-cta,html.theme--documenter-dark .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(173,129,0,0.25);color:#fff}html.theme--documenter-dark .file.is-warning:active .file-cta,html.theme--documenter-dark .file.is-warning.is-active .file-cta{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger .file-cta{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:hover .file-cta,html.theme--documenter-dark .file.is-danger.is-hovered .file-cta{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:focus .file-cta,html.theme--documenter-dark .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(158,27,13,0.25);color:#fff}html.theme--documenter-dark .file.is-danger:active .file-cta,html.theme--documenter-dark .file.is-danger.is-active .file-cta{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--documenter-dark .file.is-normal{font-size:1rem}html.theme--documenter-dark .file.is-medium{font-size:1.25rem}html.theme--documenter-dark .file.is-medium .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-large{font-size:1.5rem}html.theme--documenter-dark .file.is-large .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--documenter-dark .file.has-name.is-empty .file-name{display:none}html.theme--documenter-dark .file.is-boxed .file-label{flex-direction:column}html.theme--documenter-dark .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--documenter-dark .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--documenter-dark .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--documenter-dark .file.is-boxed .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--documenter-dark .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--documenter-dark .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--documenter-dark .file.is-centered{justify-content:center}html.theme--documenter-dark .file.is-fullwidth .file-label{width:100%}html.theme--documenter-dark .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--documenter-dark .file.is-right{justify-content:flex-end}html.theme--documenter-dark .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--documenter-dark .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--documenter-dark .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--documenter-dark .file-label:hover .file-cta{background-color:#232829;color:#f2f2f2}html.theme--documenter-dark .file-label:hover .file-name{border-color:#596668}html.theme--documenter-dark .file-label:active .file-cta{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .file-label:active .file-name{border-color:#535f61}html.theme--documenter-dark .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--documenter-dark .file-cta{background-color:#282f2f;color:#fff}html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--documenter-dark .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--documenter-dark .file-icon .fa{font-size:14px}html.theme--documenter-dark .label{color:#f2f2f2;display:block;font-size:1rem;font-weight:700}html.theme--documenter-dark .label:not(:last-child){margin-bottom:0.5em}html.theme--documenter-dark .label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--documenter-dark .label.is-medium{font-size:1.25rem}html.theme--documenter-dark .label.is-large{font-size:1.5rem}html.theme--documenter-dark .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--documenter-dark .help.is-white{color:#fff}html.theme--documenter-dark .help.is-black{color:#0a0a0a}html.theme--documenter-dark .help.is-light{color:#ecf0f1}html.theme--documenter-dark .help.is-dark,html.theme--documenter-dark .content kbd.help{color:#282f2f}html.theme--documenter-dark .help.is-primary,html.theme--documenter-dark .docstring>section>a.help.docs-sourcelink{color:#375a7f}html.theme--documenter-dark .help.is-link{color:#1abc9c}html.theme--documenter-dark .help.is-info{color:#024c7d}html.theme--documenter-dark .help.is-success{color:#008438}html.theme--documenter-dark .help.is-warning{color:#ad8100}html.theme--documenter-dark .help.is-danger{color:#9e1b0d}html.theme--documenter-dark .field:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.has-addons{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--documenter-dark .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.has-addons.has-addons-centered{justify-content:center}html.theme--documenter-dark .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .field.is-grouped{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.is-grouped>.control{flex-shrink:0}html.theme--documenter-dark .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--documenter-dark .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field.is-horizontal{display:flex}}html.theme--documenter-dark .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--documenter-dark .field-label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-normal{padding-top:0.375em}html.theme--documenter-dark .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--documenter-dark .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--documenter-dark .field-body .field{margin-bottom:0}html.theme--documenter-dark .field-body>.field{flex-shrink:1}html.theme--documenter-dark .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--documenter-dark .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--documenter-dark .control.has-icons-left .input:focus~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-left .select:focus~.icon,html.theme--documenter-dark .control.has-icons-right .input:focus~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-right .select:focus~.icon{color:#282f2f}html.theme--documenter-dark .control.has-icons-left .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-small~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--documenter-dark .control.has-icons-left .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--documenter-dark .control.has-icons-left .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon{color:#5e6d6f;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--documenter-dark .control.has-icons-left .input,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--documenter-dark .control.has-icons-left .select select{padding-left:2.5em}html.theme--documenter-dark .control.has-icons-left .icon.is-left{left:0}html.theme--documenter-dark .control.has-icons-right .input,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--documenter-dark .control.has-icons-right .select select{padding-right:2.5em}html.theme--documenter-dark .control.has-icons-right .icon.is-right{right:0}html.theme--documenter-dark .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--documenter-dark .control.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .control.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--documenter-dark .breadcrumb a{align-items:center;color:#1abc9c;display:flex;justify-content:center;padding:0 .75em}html.theme--documenter-dark .breadcrumb a:hover{color:#1dd2af}html.theme--documenter-dark .breadcrumb li{align-items:center;display:flex}html.theme--documenter-dark .breadcrumb li:first-child a{padding-left:0}html.theme--documenter-dark .breadcrumb li.is-active a{color:#f2f2f2;cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb li+li::before{color:#8c9b9d;content:"\0002f"}html.theme--documenter-dark .breadcrumb ul,html.theme--documenter-dark .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .breadcrumb .icon:first-child{margin-right:.5em}html.theme--documenter-dark .breadcrumb .icon:last-child{margin-left:.5em}html.theme--documenter-dark .breadcrumb.is-centered ol,html.theme--documenter-dark .breadcrumb.is-centered ul{justify-content:center}html.theme--documenter-dark .breadcrumb.is-right ol,html.theme--documenter-dark .breadcrumb.is-right ul{justify-content:flex-end}html.theme--documenter-dark .breadcrumb.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--documenter-dark .breadcrumb.is-medium{font-size:1.25rem}html.theme--documenter-dark .breadcrumb.is-large{font-size:1.5rem}html.theme--documenter-dark .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--documenter-dark .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--documenter-dark .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--documenter-dark .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--documenter-dark .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#fff;max-width:100%;position:relative}html.theme--documenter-dark .card-footer:first-child,html.theme--documenter-dark .card-content:first-child,html.theme--documenter-dark .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-footer:last-child,html.theme--documenter-dark .card-content:last-child,html.theme--documenter-dark .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--documenter-dark .card-header-title{align-items:center;color:#f2f2f2;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--documenter-dark .card-header-title.is-centered{justify-content:center}html.theme--documenter-dark .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--documenter-dark .card-image{display:block;position:relative}html.theme--documenter-dark .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--documenter-dark .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--documenter-dark .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--documenter-dark .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--documenter-dark .dropdown.is-active .dropdown-menu,html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--documenter-dark .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--documenter-dark .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--documenter-dark .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .dropdown-content{background-color:#282f2f;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--documenter-dark .dropdown-item{color:#fff;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--documenter-dark a.dropdown-item,html.theme--documenter-dark button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--documenter-dark a.dropdown-item:hover,html.theme--documenter-dark button.dropdown-item:hover{background-color:#282f2f;color:#0a0a0a}html.theme--documenter-dark a.dropdown-item.is-active,html.theme--documenter-dark button.dropdown-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--documenter-dark .level{align-items:center;justify-content:space-between}html.theme--documenter-dark .level code{border-radius:.4em}html.theme--documenter-dark .level img{display:inline-block;vertical-align:top}html.theme--documenter-dark .level.is-mobile{display:flex}html.theme--documenter-dark .level.is-mobile .level-left,html.theme--documenter-dark .level.is-mobile .level-right{display:flex}html.theme--documenter-dark .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level{display:flex}html.theme--documenter-dark .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--documenter-dark .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--documenter-dark .level-item .title,html.theme--documenter-dark .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--documenter-dark .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--documenter-dark .level-left,html.theme--documenter-dark .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .level-left .level-item.is-flexible,html.theme--documenter-dark .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left .level-item:not(:last-child),html.theme--documenter-dark .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--documenter-dark .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left{display:flex}}html.theme--documenter-dark .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-right{display:flex}}html.theme--documenter-dark .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--documenter-dark .media .content:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .media .media{border-top:1px solid rgba(94,109,111,0.5);display:flex;padding-top:.75rem}html.theme--documenter-dark .media .media .content:not(:last-child),html.theme--documenter-dark .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--documenter-dark .media .media .media{padding-top:.5rem}html.theme--documenter-dark .media .media .media+.media{margin-top:.5rem}html.theme--documenter-dark .media+.media{border-top:1px solid rgba(94,109,111,0.5);margin-top:1rem;padding-top:1rem}html.theme--documenter-dark .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--documenter-dark .media-left,html.theme--documenter-dark .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .media-left{margin-right:1rem}html.theme--documenter-dark .media-right{margin-left:1rem}html.theme--documenter-dark .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .media-content{overflow-x:auto}}html.theme--documenter-dark .menu{font-size:1rem}html.theme--documenter-dark .menu.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--documenter-dark .menu.is-medium{font-size:1.25rem}html.theme--documenter-dark .menu.is-large{font-size:1.5rem}html.theme--documenter-dark .menu-list{line-height:1.25}html.theme--documenter-dark .menu-list a{border-radius:3px;color:#fff;display:block;padding:0.5em 0.75em}html.theme--documenter-dark .menu-list a:hover{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .menu-list a.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .menu-list li ul{border-left:1px solid #5e6d6f;margin:.75em;padding-left:.75em}html.theme--documenter-dark .menu-label{color:#fff;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--documenter-dark .menu-label:not(:first-child){margin-top:1em}html.theme--documenter-dark .menu-label:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .message{background-color:#282f2f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .message strong{color:currentColor}html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .message.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--documenter-dark .message.is-medium{font-size:1.25rem}html.theme--documenter-dark .message.is-large{font-size:1.5rem}html.theme--documenter-dark .message.is-white{background-color:#fff}html.theme--documenter-dark .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .message.is-white .message-body{border-color:#fff}html.theme--documenter-dark .message.is-black{background-color:#fafafa}html.theme--documenter-dark .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .message.is-black .message-body{border-color:#0a0a0a}html.theme--documenter-dark .message.is-light{background-color:#f9fafb}html.theme--documenter-dark .message.is-light .message-header{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .message.is-light .message-body{border-color:#ecf0f1}html.theme--documenter-dark .message.is-dark,html.theme--documenter-dark .content kbd.message{background-color:#f9fafa}html.theme--documenter-dark .message.is-dark .message-header,html.theme--documenter-dark .content kbd.message .message-header{background-color:#282f2f;color:#fff}html.theme--documenter-dark .message.is-dark .message-body,html.theme--documenter-dark .content kbd.message .message-body{border-color:#282f2f}html.theme--documenter-dark .message.is-primary,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink{background-color:#f1f5f9}html.theme--documenter-dark .message.is-primary .message-header,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-header{background-color:#375a7f;color:#fff}html.theme--documenter-dark .message.is-primary .message-body,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-body{border-color:#375a7f;color:#4d7eb2}html.theme--documenter-dark .message.is-link{background-color:#edfdf9}html.theme--documenter-dark .message.is-link .message-header{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .message.is-link .message-body{border-color:#1abc9c;color:#15987e}html.theme--documenter-dark .message.is-info{background-color:#ebf7ff}html.theme--documenter-dark .message.is-info .message-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .message.is-info .message-body{border-color:#024c7d;color:#0e9dfb}html.theme--documenter-dark .message.is-success{background-color:#ebfff3}html.theme--documenter-dark .message.is-success .message-header{background-color:#008438;color:#fff}html.theme--documenter-dark .message.is-success .message-body{border-color:#008438;color:#00eb64}html.theme--documenter-dark .message.is-warning{background-color:#fffaeb}html.theme--documenter-dark .message.is-warning .message-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .message.is-warning .message-body{border-color:#ad8100;color:#d19c00}html.theme--documenter-dark .message.is-danger{background-color:#fdeeec}html.theme--documenter-dark .message.is-danger .message-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .message.is-danger .message-body{border-color:#9e1b0d;color:#ec311d}html.theme--documenter-dark .message-header{align-items:center;background-color:#fff;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--documenter-dark .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--documenter-dark .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--documenter-dark .message-body{border-color:#5e6d6f;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#fff;padding:1.25em 1.5em}html.theme--documenter-dark .message-body code,html.theme--documenter-dark .message-body pre{background-color:#fff}html.theme--documenter-dark .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--documenter-dark .modal.is-active{display:flex}html.theme--documenter-dark .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--documenter-dark .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--documenter-dark .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--documenter-dark .modal-card-head,html.theme--documenter-dark .modal-card-foot{align-items:center;background-color:#282f2f;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--documenter-dark .modal-card-head{border-bottom:1px solid #5e6d6f;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--documenter-dark .modal-card-title{color:#f2f2f2;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--documenter-dark .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5e6d6f}html.theme--documenter-dark .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--documenter-dark .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--documenter-dark .navbar{background-color:#375a7f;min-height:4rem;position:relative;z-index:30}html.theme--documenter-dark .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-white .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--documenter-dark .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-black .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--documenter-dark .navbar.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-light .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}}html.theme--documenter-dark .navbar.is-dark,html.theme--documenter-dark .content kbd.navbar{background-color:#282f2f;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-burger,html.theme--documenter-dark .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-dark .navbar-start>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-end>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#282f2f;color:#fff}}html.theme--documenter-dark .navbar.is-primary,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-burger,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-primary .navbar-start>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-end>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#375a7f;color:#fff}}html.theme--documenter-dark .navbar.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-link .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c;color:#fff}}html.theme--documenter-dark .navbar.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-info .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#024c7d;color:#fff}}html.theme--documenter-dark .navbar.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-success .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#008438;color:#fff}}html.theme--documenter-dark .navbar.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-warning .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ad8100;color:#fff}}html.theme--documenter-dark .navbar.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-danger .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#9e1b0d;color:#fff}}html.theme--documenter-dark .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--documenter-dark .navbar.has-shadow{box-shadow:0 2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-bottom,html.theme--documenter-dark .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-top{top:0}html.theme--documenter-dark html.has-navbar-fixed-top,html.theme--documenter-dark body.has-navbar-fixed-top{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom,html.theme--documenter-dark body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--documenter-dark .navbar-brand,html.theme--documenter-dark .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--documenter-dark .navbar-brand a.navbar-item:focus,html.theme--documenter-dark .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--documenter-dark .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--documenter-dark .navbar-burger{color:#fff;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--documenter-dark .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--documenter-dark .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--documenter-dark .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--documenter-dark .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--documenter-dark .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--documenter-dark .navbar-menu{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{color:#fff;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--documenter-dark .navbar-item .icon:only-child,html.theme--documenter-dark .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--documenter-dark a.navbar-item,html.theme--documenter-dark .navbar-link{cursor:pointer}html.theme--documenter-dark a.navbar-item:focus,html.theme--documenter-dark a.navbar-item:focus-within,html.theme--documenter-dark a.navbar-item:hover,html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link:focus,html.theme--documenter-dark .navbar-link:focus-within,html.theme--documenter-dark .navbar-link:hover,html.theme--documenter-dark .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-item{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .navbar-item img{max-height:1.75rem}html.theme--documenter-dark .navbar-item.has-dropdown{padding:0}html.theme--documenter-dark .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--documenter-dark .navbar-item.is-tab:focus,html.theme--documenter-dark .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c}html.theme--documenter-dark .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c;border-bottom-style:solid;border-bottom-width:3px;color:#1abc9c;padding-bottom:calc(0.5rem - 3px)}html.theme--documenter-dark .navbar-content{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--documenter-dark .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--documenter-dark .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar>.container{display:block}html.theme--documenter-dark .navbar-brand .navbar-item,html.theme--documenter-dark .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--documenter-dark .navbar-link::after{display:none}html.theme--documenter-dark .navbar-menu{background-color:#375a7f;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--documenter-dark .navbar-menu.is-active{display:block}html.theme--documenter-dark .navbar.is-fixed-bottom-touch,html.theme--documenter-dark .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-touch{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-touch{top:0}html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu,html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--documenter-dark html.has-navbar-fixed-top-touch,html.theme--documenter-dark body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-touch,html.theme--documenter-dark body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar,html.theme--documenter-dark .navbar-menu,html.theme--documenter-dark .navbar-start,html.theme--documenter-dark .navbar-end{align-items:stretch;display:flex}html.theme--documenter-dark .navbar{min-height:4rem}html.theme--documenter-dark .navbar.is-spaced{padding:1rem 2rem}html.theme--documenter-dark .navbar.is-spaced .navbar-start,html.theme--documenter-dark .navbar.is-spaced .navbar-end{align-items:center}html.theme--documenter-dark .navbar.is-spaced a.navbar-item,html.theme--documenter-dark .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover,html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover,html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-burger{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{align-items:center;display:flex}html.theme--documenter-dark .navbar-item.has-dropdown{align-items:stretch}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--documenter-dark .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--documenter-dark .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--documenter-dark .navbar-dropdown{background-color:#375a7f;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--documenter-dark .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}.navbar.is-spaced html.theme--documenter-dark .navbar-dropdown,html.theme--documenter-dark .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--documenter-dark .navbar-dropdown.is-right{left:auto;right:0}html.theme--documenter-dark .navbar-divider{display:block}html.theme--documenter-dark .navbar>.container .navbar-brand,html.theme--documenter-dark .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--documenter-dark .navbar>.container .navbar-menu,html.theme--documenter-dark .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop,html.theme--documenter-dark .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-desktop{top:0}html.theme--documenter-dark html.has-navbar-fixed-top-desktop,html.theme--documenter-dark body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop,html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-top,html.theme--documenter-dark body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom,html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link.is-active{color:#1abc9c}html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover),html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--documenter-dark .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--documenter-dark .pagination{font-size:1rem;margin:-.25rem}html.theme--documenter-dark .pagination.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--documenter-dark .pagination.is-medium{font-size:1.25rem}html.theme--documenter-dark .pagination.is-large{font-size:1.5rem}html.theme--documenter-dark .pagination.is-rounded .pagination-previous,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--documenter-dark .pagination.is-rounded .pagination-next,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--documenter-dark .pagination.is-rounded .pagination-link,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--documenter-dark .pagination,html.theme--documenter-dark .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link{border-color:#5e6d6f;color:#1abc9c;min-width:2.5em}html.theme--documenter-dark .pagination-previous:hover,html.theme--documenter-dark .pagination-next:hover,html.theme--documenter-dark .pagination-link:hover{border-color:#8c9b9d;color:#1dd2af}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus{border-color:#8c9b9d}html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-previous.is-disabled,html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-next.is-disabled,html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-link.is-disabled{background-color:#5e6d6f;border-color:#5e6d6f;box-shadow:none;color:#fff;opacity:0.5}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--documenter-dark .pagination-link.is-current{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .pagination-ellipsis{color:#8c9b9d;pointer-events:none}html.theme--documenter-dark .pagination-list{flex-wrap:wrap}html.theme--documenter-dark .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--documenter-dark .pagination{flex-wrap:wrap}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination-previous{order:2}html.theme--documenter-dark .pagination-next{order:3}html.theme--documenter-dark .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination.is-centered .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--documenter-dark .pagination.is-centered .pagination-next{order:3}html.theme--documenter-dark .pagination.is-right .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-right .pagination-next{order:2}html.theme--documenter-dark .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--documenter-dark .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--documenter-dark .panel:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--documenter-dark .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--documenter-dark .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--documenter-dark .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--documenter-dark .panel.is-light .panel-heading{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .panel.is-light .panel-tabs a.is-active{border-bottom-color:#ecf0f1}html.theme--documenter-dark .panel.is-light .panel-block.is-active .panel-icon{color:#ecf0f1}html.theme--documenter-dark .panel.is-dark .panel-heading,html.theme--documenter-dark .content kbd.panel .panel-heading{background-color:#282f2f;color:#fff}html.theme--documenter-dark .panel.is-dark .panel-tabs a.is-active,html.theme--documenter-dark .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#282f2f}html.theme--documenter-dark .panel.is-dark .panel-block.is-active .panel-icon,html.theme--documenter-dark .content kbd.panel .panel-block.is-active .panel-icon{color:#282f2f}html.theme--documenter-dark .panel.is-primary .panel-heading,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#375a7f;color:#fff}html.theme--documenter-dark .panel.is-primary .panel-tabs a.is-active,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#375a7f}html.theme--documenter-dark .panel.is-primary .panel-block.is-active .panel-icon,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#375a7f}html.theme--documenter-dark .panel.is-link .panel-heading{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .panel.is-link .panel-tabs a.is-active{border-bottom-color:#1abc9c}html.theme--documenter-dark .panel.is-link .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel.is-info .panel-heading{background-color:#024c7d;color:#fff}html.theme--documenter-dark .panel.is-info .panel-tabs a.is-active{border-bottom-color:#024c7d}html.theme--documenter-dark .panel.is-info .panel-block.is-active .panel-icon{color:#024c7d}html.theme--documenter-dark .panel.is-success .panel-heading{background-color:#008438;color:#fff}html.theme--documenter-dark .panel.is-success .panel-tabs a.is-active{border-bottom-color:#008438}html.theme--documenter-dark .panel.is-success .panel-block.is-active .panel-icon{color:#008438}html.theme--documenter-dark .panel.is-warning .panel-heading{background-color:#ad8100;color:#fff}html.theme--documenter-dark .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ad8100}html.theme--documenter-dark .panel.is-warning .panel-block.is-active .panel-icon{color:#ad8100}html.theme--documenter-dark .panel.is-danger .panel-heading{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#9e1b0d}html.theme--documenter-dark .panel.is-danger .panel-block.is-active .panel-icon{color:#9e1b0d}html.theme--documenter-dark .panel-tabs:not(:last-child),html.theme--documenter-dark .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--documenter-dark .panel-heading{background-color:#343c3d;border-radius:8px 8px 0 0;color:#f2f2f2;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--documenter-dark .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--documenter-dark .panel-tabs a{border-bottom:1px solid #5e6d6f;margin-bottom:-1px;padding:0.5em}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#343c3d;color:#17a689}html.theme--documenter-dark .panel-list a{color:#fff}html.theme--documenter-dark .panel-list a:hover{color:#1abc9c}html.theme--documenter-dark .panel-block{align-items:center;color:#f2f2f2;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--documenter-dark .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--documenter-dark .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--documenter-dark .panel-block.is-wrapped{flex-wrap:wrap}html.theme--documenter-dark .panel-block.is-active{border-left-color:#1abc9c;color:#17a689}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--documenter-dark a.panel-block,html.theme--documenter-dark label.panel-block{cursor:pointer}html.theme--documenter-dark a.panel-block:hover,html.theme--documenter-dark label.panel-block:hover{background-color:#282f2f}html.theme--documenter-dark .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#fff;margin-right:.75em}html.theme--documenter-dark .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--documenter-dark .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--documenter-dark .tabs a{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;color:#fff;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--documenter-dark .tabs a:hover{border-bottom-color:#f2f2f2;color:#f2f2f2}html.theme--documenter-dark .tabs li{display:block}html.theme--documenter-dark .tabs li.is-active a{border-bottom-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .tabs ul{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--documenter-dark .tabs ul.is-left{padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--documenter-dark .tabs .icon:first-child{margin-right:.5em}html.theme--documenter-dark .tabs .icon:last-child{margin-left:.5em}html.theme--documenter-dark .tabs.is-centered ul{justify-content:center}html.theme--documenter-dark .tabs.is-right ul{justify-content:flex-end}html.theme--documenter-dark .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--documenter-dark .tabs.is-boxed a:hover{background-color:#282f2f;border-bottom-color:#5e6d6f}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5e6d6f;border-bottom-color:rgba(0,0,0,0) !important}html.theme--documenter-dark .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .tabs.is-toggle a{border-color:#5e6d6f;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--documenter-dark .tabs.is-toggle a:hover{background-color:#282f2f;border-color:#8c9b9d;z-index:2}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li.is-active a{background-color:#1abc9c;border-color:#1abc9c;color:#fff;z-index:1}html.theme--documenter-dark .tabs.is-toggle ul{border-bottom:none}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--documenter-dark .tabs.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--documenter-dark .tabs.is-medium{font-size:1.25rem}html.theme--documenter-dark .tabs.is-large{font-size:1.5rem}html.theme--documenter-dark .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--documenter-dark .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--documenter-dark .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--documenter-dark .column.is-narrow-mobile{flex:none;width:unset}html.theme--documenter-dark .column.is-full-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-mobile{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--documenter-dark .column.is-0-mobile{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-mobile{margin-left:0%}html.theme--documenter-dark .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-mobile{margin-left:25%}html.theme--documenter-dark .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-mobile{margin-left:50%}html.theme--documenter-dark .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-mobile{margin-left:75%}html.theme--documenter-dark .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .column.is-narrow,html.theme--documenter-dark .column.is-narrow-tablet{flex:none;width:unset}html.theme--documenter-dark .column.is-full,html.theme--documenter-dark .column.is-full-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters,html.theme--documenter-dark .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds,html.theme--documenter-dark .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half,html.theme--documenter-dark .column.is-half-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third,html.theme--documenter-dark .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter,html.theme--documenter-dark .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth,html.theme--documenter-dark .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths,html.theme--documenter-dark .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths,html.theme--documenter-dark .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths,html.theme--documenter-dark .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters,html.theme--documenter-dark .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds,html.theme--documenter-dark .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half,html.theme--documenter-dark .column.is-offset-half-tablet{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third,html.theme--documenter-dark .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter,html.theme--documenter-dark .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth,html.theme--documenter-dark .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths,html.theme--documenter-dark .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths,html.theme--documenter-dark .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths,html.theme--documenter-dark .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--documenter-dark .column.is-0,html.theme--documenter-dark .column.is-0-tablet{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0,html.theme--documenter-dark .column.is-offset-0-tablet{margin-left:0%}html.theme--documenter-dark .column.is-1,html.theme--documenter-dark .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1,html.theme--documenter-dark .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2,html.theme--documenter-dark .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2,html.theme--documenter-dark .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3,html.theme--documenter-dark .column.is-3-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3,html.theme--documenter-dark .column.is-offset-3-tablet{margin-left:25%}html.theme--documenter-dark .column.is-4,html.theme--documenter-dark .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4,html.theme--documenter-dark .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5,html.theme--documenter-dark .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5,html.theme--documenter-dark .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6,html.theme--documenter-dark .column.is-6-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6,html.theme--documenter-dark .column.is-offset-6-tablet{margin-left:50%}html.theme--documenter-dark .column.is-7,html.theme--documenter-dark .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7,html.theme--documenter-dark .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8,html.theme--documenter-dark .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8,html.theme--documenter-dark .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9,html.theme--documenter-dark .column.is-9-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9,html.theme--documenter-dark .column.is-offset-9-tablet{margin-left:75%}html.theme--documenter-dark .column.is-10,html.theme--documenter-dark .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10,html.theme--documenter-dark .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11,html.theme--documenter-dark .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11,html.theme--documenter-dark .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12,html.theme--documenter-dark .column.is-12-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12,html.theme--documenter-dark .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--documenter-dark .column.is-narrow-touch{flex:none;width:unset}html.theme--documenter-dark .column.is-full-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-touch{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-touch{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-touch{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-touch{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-touch{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--documenter-dark .column.is-0-touch{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-touch{margin-left:0%}html.theme--documenter-dark .column.is-1-touch{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-touch{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-touch{margin-left:25%}html.theme--documenter-dark .column.is-4-touch{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-touch{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-touch{margin-left:50%}html.theme--documenter-dark .column.is-7-touch{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-touch{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-touch{margin-left:75%}html.theme--documenter-dark .column.is-10-touch{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-touch{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--documenter-dark .column.is-narrow-desktop{flex:none;width:unset}html.theme--documenter-dark .column.is-full-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-desktop{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--documenter-dark .column.is-0-desktop{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-desktop{margin-left:0%}html.theme--documenter-dark .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-desktop{margin-left:25%}html.theme--documenter-dark .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-desktop{margin-left:50%}html.theme--documenter-dark .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-desktop{margin-left:75%}html.theme--documenter-dark .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--documenter-dark .column.is-narrow-widescreen{flex:none;width:unset}html.theme--documenter-dark .column.is-full-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--documenter-dark .column.is-0-widescreen{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-widescreen{margin-left:0%}html.theme--documenter-dark .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--documenter-dark .column.is-narrow-fullhd{flex:none;width:unset}html.theme--documenter-dark .column.is-full-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--documenter-dark .column.is-0-fullhd{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-fullhd{margin-left:0%}html.theme--documenter-dark .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-fullhd{margin-left:100%}}html.theme--documenter-dark .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .columns:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--documenter-dark .columns.is-centered{justify-content:center}html.theme--documenter-dark .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--documenter-dark .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--documenter-dark .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .columns.is-gapless:last-child{margin-bottom:0}html.theme--documenter-dark .columns.is-mobile{display:flex}html.theme--documenter-dark .columns.is-multiline{flex-wrap:wrap}html.theme--documenter-dark .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-desktop{display:flex}}html.theme--documenter-dark .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--documenter-dark .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--documenter-dark .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--documenter-dark .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--documenter-dark .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--documenter-dark .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--documenter-dark .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--documenter-dark .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--documenter-dark .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--documenter-dark .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--documenter-dark .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--documenter-dark .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--documenter-dark .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .tile.is-child{margin:0 !important}html.theme--documenter-dark .tile.is-parent{padding:.75rem}html.theme--documenter-dark .tile.is-vertical{flex-direction:column}html.theme--documenter-dark .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--documenter-dark .tile:not(.is-child){display:flex}html.theme--documenter-dark .tile.is-1{flex:none;width:8.33333337%}html.theme--documenter-dark .tile.is-2{flex:none;width:16.66666674%}html.theme--documenter-dark .tile.is-3{flex:none;width:25%}html.theme--documenter-dark .tile.is-4{flex:none;width:33.33333337%}html.theme--documenter-dark .tile.is-5{flex:none;width:41.66666674%}html.theme--documenter-dark .tile.is-6{flex:none;width:50%}html.theme--documenter-dark .tile.is-7{flex:none;width:58.33333337%}html.theme--documenter-dark .tile.is-8{flex:none;width:66.66666674%}html.theme--documenter-dark .tile.is-9{flex:none;width:75%}html.theme--documenter-dark .tile.is-10{flex:none;width:83.33333337%}html.theme--documenter-dark .tile.is-11{flex:none;width:91.66666674%}html.theme--documenter-dark .tile.is-12{flex:none;width:100%}}html.theme--documenter-dark .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--documenter-dark .hero .navbar{background:none}html.theme--documenter-dark .hero .tabs ul{border-bottom:none}html.theme--documenter-dark .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-white strong{color:inherit}html.theme--documenter-dark .hero.is-white .title{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--documenter-dark .hero.is-white .subtitle a:not(.button),html.theme--documenter-dark .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-white .navbar-menu{background-color:#fff}}html.theme--documenter-dark .hero.is-white .navbar-item,html.theme--documenter-dark .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--documenter-dark .hero.is-white a.navbar-item:hover,html.theme--documenter-dark .hero.is-white a.navbar-item.is-active,html.theme--documenter-dark .hero.is-white .navbar-link:hover,html.theme--documenter-dark .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--documenter-dark .hero.is-white .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--documenter-dark .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-black strong{color:inherit}html.theme--documenter-dark .hero.is-black .title{color:#fff}html.theme--documenter-dark .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-black .subtitle a:not(.button),html.theme--documenter-dark .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--documenter-dark .hero.is-black .navbar-item,html.theme--documenter-dark .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-black a.navbar-item:hover,html.theme--documenter-dark .hero.is-black a.navbar-item.is-active,html.theme--documenter-dark .hero.is-black .navbar-link:hover,html.theme--documenter-dark .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-black .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--documenter-dark .hero.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-light strong{color:inherit}html.theme--documenter-dark .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--documenter-dark .hero.is-light .subtitle a:not(.button),html.theme--documenter-dark .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-light .navbar-menu{background-color:#ecf0f1}}html.theme--documenter-dark .hero.is-light .navbar-item,html.theme--documenter-dark .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a.navbar-item:hover,html.theme--documenter-dark .hero.is-light a.navbar-item.is-active,html.theme--documenter-dark .hero.is-light .navbar-link:hover,html.theme--documenter-dark .hero.is-light .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--documenter-dark .hero.is-light .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-light .tabs li.is-active a{color:#ecf0f1 !important;opacity:1}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .hero.is-light.is-bold{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}}html.theme--documenter-dark .hero.is-dark,html.theme--documenter-dark .content kbd.hero{background-color:#282f2f;color:#fff}html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-dark strong,html.theme--documenter-dark .content kbd.hero strong{color:inherit}html.theme--documenter-dark .hero.is-dark .title,html.theme--documenter-dark .content kbd.hero .title{color:#fff}html.theme--documenter-dark .hero.is-dark .subtitle,html.theme--documenter-dark .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button),html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button),html.theme--documenter-dark .hero.is-dark .subtitle strong,html.theme--documenter-dark .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-dark .navbar-menu,html.theme--documenter-dark .content kbd.hero .navbar-menu{background-color:#282f2f}}html.theme--documenter-dark .hero.is-dark .navbar-item,html.theme--documenter-dark .content kbd.hero .navbar-item,html.theme--documenter-dark .hero.is-dark .navbar-link,html.theme--documenter-dark .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-dark a.navbar-item:hover,html.theme--documenter-dark .content kbd.hero a.navbar-item:hover,html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active,html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active,html.theme--documenter-dark .hero.is-dark .navbar-link:hover,html.theme--documenter-dark .content kbd.hero .navbar-link:hover,html.theme--documenter-dark .hero.is-dark .navbar-link.is-active,html.theme--documenter-dark .content kbd.hero .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .hero.is-dark .tabs a,html.theme--documenter-dark .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-dark .tabs a:hover,html.theme--documenter-dark .content kbd.hero .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs li.is-active a{color:#282f2f !important;opacity:1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#282f2f}html.theme--documenter-dark .hero.is-dark.is-bold,html.theme--documenter-dark .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu,html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}}html.theme--documenter-dark .hero.is-primary,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-primary strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--documenter-dark .hero.is-primary .title,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--documenter-dark .hero.is-primary .subtitle,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--documenter-dark .hero.is-primary .subtitle strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-primary .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#375a7f}}html.theme--documenter-dark .hero.is-primary .navbar-item,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--documenter-dark .hero.is-primary .navbar-link,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-primary a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--documenter-dark .hero.is-primary .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--documenter-dark .hero.is-primary .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .hero.is-primary .tabs a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-primary .tabs a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#375a7f !important;opacity:1}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#375a7f}html.theme--documenter-dark .hero.is-primary.is-bold,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}}html.theme--documenter-dark .hero.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-link strong{color:inherit}html.theme--documenter-dark .hero.is-link .title{color:#fff}html.theme--documenter-dark .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-link .subtitle a:not(.button),html.theme--documenter-dark .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-link .navbar-menu{background-color:#1abc9c}}html.theme--documenter-dark .hero.is-link .navbar-item,html.theme--documenter-dark .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-link a.navbar-item:hover,html.theme--documenter-dark .hero.is-link a.navbar-item.is-active,html.theme--documenter-dark .hero.is-link .navbar-link:hover,html.theme--documenter-dark .hero.is-link .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-link .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-link .tabs li.is-active a{color:#1abc9c !important;opacity:1}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1abc9c}html.theme--documenter-dark .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}}html.theme--documenter-dark .hero.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-info strong{color:inherit}html.theme--documenter-dark .hero.is-info .title{color:#fff}html.theme--documenter-dark .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-info .subtitle a:not(.button),html.theme--documenter-dark .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-info .navbar-menu{background-color:#024c7d}}html.theme--documenter-dark .hero.is-info .navbar-item,html.theme--documenter-dark .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-info a.navbar-item:hover,html.theme--documenter-dark .hero.is-info a.navbar-item.is-active,html.theme--documenter-dark .hero.is-info .navbar-link:hover,html.theme--documenter-dark .hero.is-info .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-info .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-info .tabs li.is-active a{color:#024c7d !important;opacity:1}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#024c7d}html.theme--documenter-dark .hero.is-info.is-bold{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}}html.theme--documenter-dark .hero.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-success strong{color:inherit}html.theme--documenter-dark .hero.is-success .title{color:#fff}html.theme--documenter-dark .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-success .subtitle a:not(.button),html.theme--documenter-dark .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-success .navbar-menu{background-color:#008438}}html.theme--documenter-dark .hero.is-success .navbar-item,html.theme--documenter-dark .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-success a.navbar-item:hover,html.theme--documenter-dark .hero.is-success a.navbar-item.is-active,html.theme--documenter-dark .hero.is-success .navbar-link:hover,html.theme--documenter-dark .hero.is-success .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-success .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-success .tabs li.is-active a{color:#008438 !important;opacity:1}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#008438}html.theme--documenter-dark .hero.is-success.is-bold{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}}html.theme--documenter-dark .hero.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-warning strong{color:inherit}html.theme--documenter-dark .hero.is-warning .title{color:#fff}html.theme--documenter-dark .hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button),html.theme--documenter-dark .hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-warning .navbar-menu{background-color:#ad8100}}html.theme--documenter-dark .hero.is-warning .navbar-item,html.theme--documenter-dark .hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-warning a.navbar-item:hover,html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active,html.theme--documenter-dark .hero.is-warning .navbar-link:hover,html.theme--documenter-dark .hero.is-warning .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .hero.is-warning .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-warning .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs li.is-active a{color:#ad8100 !important;opacity:1}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ad8100}html.theme--documenter-dark .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}}html.theme--documenter-dark .hero.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-danger strong{color:inherit}html.theme--documenter-dark .hero.is-danger .title{color:#fff}html.theme--documenter-dark .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button),html.theme--documenter-dark .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-danger .navbar-menu{background-color:#9e1b0d}}html.theme--documenter-dark .hero.is-danger .navbar-item,html.theme--documenter-dark .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-danger a.navbar-item:hover,html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active,html.theme--documenter-dark .hero.is-danger .navbar-link:hover,html.theme--documenter-dark .hero.is-danger .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-danger .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs li.is-active a{color:#9e1b0d !important;opacity:1}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#9e1b0d}html.theme--documenter-dark .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}}html.theme--documenter-dark .hero.is-small .hero-body,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--documenter-dark .hero.is-halfheight .hero-body,html.theme--documenter-dark .hero.is-fullheight .hero-body,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--documenter-dark .hero.is-halfheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .hero.is-halfheight{min-height:50vh}html.theme--documenter-dark .hero.is-fullheight{min-height:100vh}html.theme--documenter-dark .hero-video{overflow:hidden}html.theme--documenter-dark .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--documenter-dark .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-video{display:none}}html.theme--documenter-dark .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-buttons .button{display:flex}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-buttons{display:flex;justify-content:center}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--documenter-dark .hero-head,html.theme--documenter-dark .hero-foot{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-body{padding:3rem 3rem}}html.theme--documenter-dark .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--documenter-dark .section{padding:3rem 3rem}html.theme--documenter-dark .section.is-medium{padding:9rem 4.5rem}html.theme--documenter-dark .section.is-large{padding:18rem 6rem}}html.theme--documenter-dark .footer{background-color:#282f2f;padding:3rem 1.5rem 6rem}html.theme--documenter-dark hr{height:1px}html.theme--documenter-dark h6{text-transform:uppercase;letter-spacing:0.5px}html.theme--documenter-dark .hero{background-color:#343c3d}html.theme--documenter-dark a{transition:all 200ms ease}html.theme--documenter-dark .button{transition:all 200ms ease;border-width:1px;color:#fff}html.theme--documenter-dark .button.is-active,html.theme--documenter-dark .button.is-focused,html.theme--documenter-dark .button:active,html.theme--documenter-dark .button:focus{box-shadow:0 0 0 2px rgba(140,155,157,0.5)}html.theme--documenter-dark .button.is-white.is-hovered,html.theme--documenter-dark .button.is-white:hover{background-color:#fff}html.theme--documenter-dark .button.is-white.is-active,html.theme--documenter-dark .button.is-white.is-focused,html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white:focus{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.5)}html.theme--documenter-dark .button.is-black.is-hovered,html.theme--documenter-dark .button.is-black:hover{background-color:#1d1d1d}html.theme--documenter-dark .button.is-black.is-active,html.theme--documenter-dark .button.is-black.is-focused,html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black:focus{border-color:#0a0a0a;box-shadow:0 0 0 2px rgba(10,10,10,0.5)}html.theme--documenter-dark .button.is-light.is-hovered,html.theme--documenter-dark .button.is-light:hover{background-color:#fff}html.theme--documenter-dark .button.is-light.is-active,html.theme--documenter-dark .button.is-light.is-focused,html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light:focus{border-color:#ecf0f1;box-shadow:0 0 0 2px rgba(236,240,241,0.5)}html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered,html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover{background-color:#3a4344}html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused,html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus{border-color:#282f2f;box-shadow:0 0 0 2px rgba(40,47,47,0.5)}html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover{background-color:#436d9a}html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink,html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus{border-color:#375a7f;box-shadow:0 0 0 2px rgba(55,90,127,0.5)}html.theme--documenter-dark .button.is-link.is-hovered,html.theme--documenter-dark .button.is-link:hover{background-color:#1fdeb8}html.theme--documenter-dark .button.is-link.is-active,html.theme--documenter-dark .button.is-link.is-focused,html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link:focus{border-color:#1abc9c;box-shadow:0 0 0 2px rgba(26,188,156,0.5)}html.theme--documenter-dark .button.is-info.is-hovered,html.theme--documenter-dark .button.is-info:hover{background-color:#0363a3}html.theme--documenter-dark .button.is-info.is-active,html.theme--documenter-dark .button.is-info.is-focused,html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info:focus{border-color:#024c7d;box-shadow:0 0 0 2px rgba(2,76,125,0.5)}html.theme--documenter-dark .button.is-success.is-hovered,html.theme--documenter-dark .button.is-success:hover{background-color:#00aa48}html.theme--documenter-dark .button.is-success.is-active,html.theme--documenter-dark .button.is-success.is-focused,html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success:focus{border-color:#008438;box-shadow:0 0 0 2px rgba(0,132,56,0.5)}html.theme--documenter-dark .button.is-warning.is-hovered,html.theme--documenter-dark .button.is-warning:hover{background-color:#d39e00}html.theme--documenter-dark .button.is-warning.is-active,html.theme--documenter-dark .button.is-warning.is-focused,html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning:focus{border-color:#ad8100;box-shadow:0 0 0 2px rgba(173,129,0,0.5)}html.theme--documenter-dark .button.is-danger.is-hovered,html.theme--documenter-dark .button.is-danger:hover{background-color:#c12110}html.theme--documenter-dark .button.is-danger.is-active,html.theme--documenter-dark .button.is-danger.is-focused,html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger:focus{border-color:#9e1b0d;box-shadow:0 0 0 2px rgba(158,27,13,0.5)}html.theme--documenter-dark .label{color:#dbdee0}html.theme--documenter-dark .button,html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .select,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea{height:2.5em}html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .select:after,html.theme--documenter-dark .select select{border-width:1px}html.theme--documenter-dark .control.has-addons .button,html.theme--documenter-dark .control.has-addons .input,html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search>input,html.theme--documenter-dark .control.has-addons .select{margin-right:-1px}html.theme--documenter-dark .notification{background-color:#343c3d}html.theme--documenter-dark .card{box-shadow:none;border:1px solid #343c3d;background-color:#282f2f;border-radius:.4em}html.theme--documenter-dark .card .card-image img{border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-header{box-shadow:none;background-color:rgba(18,18,18,0.2);border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-footer{background-color:rgba(18,18,18,0.2)}html.theme--documenter-dark .card .card-footer,html.theme--documenter-dark .card .card-footer-item{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .notification.is-white a:not(.button){color:#0a0a0a;text-decoration:underline}html.theme--documenter-dark .notification.is-black a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-light a:not(.button){color:rgba(0,0,0,0.7);text-decoration:underline}html.theme--documenter-dark .notification.is-dark a:not(.button),html.theme--documenter-dark .content kbd.notification a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-primary a:not(.button),html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-link a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-info a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-success a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-warning a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-danger a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .tag,html.theme--documenter-dark .content kbd,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{border-radius:.4em}html.theme--documenter-dark .menu-list a{transition:all 300ms ease}html.theme--documenter-dark .modal-card-body{background-color:#282f2f}html.theme--documenter-dark .modal-card-foot,html.theme--documenter-dark .modal-card-head{border-color:#343c3d}html.theme--documenter-dark .message-header{font-weight:700;background-color:#343c3d;color:#fff}html.theme--documenter-dark .message-body{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .navbar{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent{background:none}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar .navbar-menu{background-color:#375a7f;border-radius:0 0 .4em .4em}}html.theme--documenter-dark .hero .navbar,html.theme--documenter-dark body>.navbar{border-radius:0}html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous{border-width:1px}html.theme--documenter-dark .panel-block,html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs{border-width:1px}html.theme--documenter-dark .panel-block:first-child,html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child{border-top-width:1px}html.theme--documenter-dark .panel-heading{font-weight:700}html.theme--documenter-dark .panel-tabs a{border-width:1px;margin-bottom:-1px}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#17a689}html.theme--documenter-dark .panel-block:hover{color:#1dd2af}html.theme--documenter-dark .panel-block:hover .panel-icon{color:#1dd2af}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#17a689}html.theme--documenter-dark .tabs a{border-bottom-width:1px;margin-bottom:-1px}html.theme--documenter-dark .tabs ul{border-bottom-width:1px}html.theme--documenter-dark .tabs.is-boxed a{border-width:1px}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#1f2424}html.theme--documenter-dark .tabs.is-toggle li a{border-width:1px;margin-bottom:0}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark h1 .docs-heading-anchor,html.theme--documenter-dark h1 .docs-heading-anchor:hover,html.theme--documenter-dark h1 .docs-heading-anchor:visited,html.theme--documenter-dark h2 .docs-heading-anchor,html.theme--documenter-dark h2 .docs-heading-anchor:hover,html.theme--documenter-dark h2 .docs-heading-anchor:visited,html.theme--documenter-dark h3 .docs-heading-anchor,html.theme--documenter-dark h3 .docs-heading-anchor:hover,html.theme--documenter-dark h3 .docs-heading-anchor:visited,html.theme--documenter-dark h4 .docs-heading-anchor,html.theme--documenter-dark h4 .docs-heading-anchor:hover,html.theme--documenter-dark h4 .docs-heading-anchor:visited,html.theme--documenter-dark h5 .docs-heading-anchor,html.theme--documenter-dark h5 .docs-heading-anchor:hover,html.theme--documenter-dark h5 .docs-heading-anchor:visited,html.theme--documenter-dark h6 .docs-heading-anchor,html.theme--documenter-dark h6 .docs-heading-anchor:hover,html.theme--documenter-dark h6 .docs-heading-anchor:visited{color:#f2f2f2}html.theme--documenter-dark h1 .docs-heading-anchor-permalink,html.theme--documenter-dark h2 .docs-heading-anchor-permalink,html.theme--documenter-dark h3 .docs-heading-anchor-permalink,html.theme--documenter-dark h4 .docs-heading-anchor-permalink,html.theme--documenter-dark h5 .docs-heading-anchor-permalink,html.theme--documenter-dark h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--documenter-dark .docs-light-only{display:none !important}html.theme--documenter-dark pre{position:relative;overflow:hidden}html.theme--documenter-dark pre code,html.theme--documenter-dark pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--documenter-dark pre code:first-of-type,html.theme--documenter-dark pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--documenter-dark pre code:last-of-type,html.theme--documenter-dark pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--documenter-dark pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#fff;cursor:pointer;text-align:center}html.theme--documenter-dark pre .copy-button:focus,html.theme--documenter-dark pre .copy-button:hover{opacity:1;background:rgba(255,255,255,0.1);color:#1abc9c}html.theme--documenter-dark pre .copy-button.success{color:#259a12;opacity:1}html.theme--documenter-dark pre .copy-button.error{color:#cb3c33;opacity:1}html.theme--documenter-dark pre:hover .copy-button{opacity:1}html.theme--documenter-dark .admonition{background-color:#282f2f;border-style:solid;border-width:1px;border-color:#5e6d6f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .admonition strong{color:currentColor}html.theme--documenter-dark .admonition.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--documenter-dark .admonition.is-medium{font-size:1.25rem}html.theme--documenter-dark .admonition.is-large{font-size:1.5rem}html.theme--documenter-dark .admonition.is-default{background-color:#282f2f;border-color:#5e6d6f}html.theme--documenter-dark .admonition.is-default>.admonition-header{background-color:#5e6d6f;color:#fff}html.theme--documenter-dark .admonition.is-default>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-info{background-color:#282f2f;border-color:#024c7d}html.theme--documenter-dark .admonition.is-info>.admonition-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .admonition.is-info>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-success{background-color:#282f2f;border-color:#008438}html.theme--documenter-dark .admonition.is-success>.admonition-header{background-color:#008438;color:#fff}html.theme--documenter-dark .admonition.is-success>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-warning{background-color:#282f2f;border-color:#ad8100}html.theme--documenter-dark .admonition.is-warning>.admonition-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .admonition.is-warning>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-danger{background-color:#282f2f;border-color:#9e1b0d}html.theme--documenter-dark .admonition.is-danger>.admonition-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .admonition.is-danger>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-compat{background-color:#282f2f;border-color:#137886}html.theme--documenter-dark .admonition.is-compat>.admonition-header{background-color:#137886;color:#fff}html.theme--documenter-dark .admonition.is-compat>.admonition-body{color:#fff}html.theme--documenter-dark .admonition-header{color:#fff;background-color:#5e6d6f;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--documenter-dark .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--documenter-dark details.admonition.is-details>.admonition-header{list-style:none}html.theme--documenter-dark details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--documenter-dark details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--documenter-dark .admonition-body{color:#fff;padding:0.5rem .75rem}html.theme--documenter-dark .admonition-body pre{background-color:#282f2f}html.theme--documenter-dark .admonition-body code{background-color:rgba(255,255,255,0.05)}html.theme--documenter-dark .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #5e6d6f;box-shadow:none;max-width:100%}html.theme--documenter-dark .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#282f2f;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5e6d6f;overflow:auto}html.theme--documenter-dark .docstring>header code{background-color:transparent}html.theme--documenter-dark .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--documenter-dark .docstring>header .docstring-binding{margin-right:0.3em}html.theme--documenter-dark .docstring>header .docstring-category{margin-left:0.3em}html.theme--documenter-dark .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>section:last-child{border-bottom:none}html.theme--documenter-dark .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--documenter-dark .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--documenter-dark .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--documenter-dark .documenter-example-output{background-color:#1f2424}html.theme--documenter-dark .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#282f2f;color:#fff;border-bottom:3px solid #9e1b0d;padding:10px 35px;text-align:center;font-size:15px}html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--documenter-dark .outdated-warning-overlay a{color:#1abc9c}html.theme--documenter-dark .outdated-warning-overlay a:hover{color:#1dd2af}html.theme--documenter-dark .content pre{border:1px solid #5e6d6f}html.theme--documenter-dark .content code{font-weight:inherit}html.theme--documenter-dark .content a code{color:#1abc9c}html.theme--documenter-dark .content h1 code,html.theme--documenter-dark .content h2 code,html.theme--documenter-dark .content h3 code,html.theme--documenter-dark .content h4 code,html.theme--documenter-dark .content h5 code,html.theme--documenter-dark .content h6 code{color:#f2f2f2}html.theme--documenter-dark .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--documenter-dark .content blockquote>ul:first-child,html.theme--documenter-dark .content blockquote>ol:first-child,html.theme--documenter-dark .content .admonition-body>ul:first-child,html.theme--documenter-dark .content .admonition-body>ol:first-child{margin-top:0}html.theme--documenter-dark pre,html.theme--documenter-dark code{font-variant-ligatures:no-contextual}html.theme--documenter-dark .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb a.is-disabled,html.theme--documenter-dark .breadcrumb a.is-disabled:hover{color:#f2f2f2}html.theme--documenter-dark .hljs{background:initial !important}html.theme--documenter-dark .katex .katex-mathml{top:0;right:0}html.theme--documenter-dark .katex-display,html.theme--documenter-dark mjx-container,html.theme--documenter-dark .MathJax_Display{margin:0.5em 0 !important}html.theme--documenter-dark html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--documenter-dark li.no-marker{list-style:none}html.theme--documenter-dark #documenter .docs-main>article{overflow-wrap:break-word}html.theme--documenter-dark #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main{width:100%}html.theme--documenter-dark #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-main>header,html.theme--documenter-dark #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar{background-color:#1f2424;border-bottom:1px solid #5e6d6f;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--documenter-dark #documenter .docs-main section.footnotes{border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--documenter-dark #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5e6d6f;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--documenter-dark #documenter .docs-sidebar{display:flex;flex-direction:column;color:#fff;background-color:#282f2f;border-right:1px solid #5e6d6f;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--documenter-dark #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar{left:0;top:0}}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a,html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover{color:#fff}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5e6d6f;display:none;padding:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5e6d6f;padding-bottom:1.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#fff;background:#282f2f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#fff;background-color:#32393a}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5e6d6f;border-bottom:1px solid #5e6d6f;background-color:#1f2424}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#1f2424;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#32393a;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--documenter-dark #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}html.theme--documenter-dark kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--documenter-dark .search-min-width-50{min-width:50%}html.theme--documenter-dark .search-min-height-100{min-height:100%}html.theme--documenter-dark .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--documenter-dark .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--documenter-dark .search-filter:hover,html.theme--documenter-dark .search-filter:focus{color:#333}html.theme--documenter-dark .search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}html.theme--documenter-dark .search-filter-selected:hover,html.theme--documenter-dark .search-filter-selected:focus{color:#f5f5f5}html.theme--documenter-dark .search-result-highlight{background-color:#ffdd57;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .search-result-title{width:85%;color:#f5f5f5}html.theme--documenter-dark .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem}html.theme--documenter-dark .gap-8{gap:2rem}html.theme--documenter-dark{background-color:#1f2424;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark .ansi span.sgr1{font-weight:bolder}html.theme--documenter-dark .ansi span.sgr2{font-weight:lighter}html.theme--documenter-dark .ansi span.sgr3{font-style:italic}html.theme--documenter-dark .ansi span.sgr4{text-decoration:underline}html.theme--documenter-dark .ansi span.sgr7{color:#1f2424;background-color:#fff}html.theme--documenter-dark .ansi span.sgr8{color:transparent}html.theme--documenter-dark .ansi span.sgr8 span{color:transparent}html.theme--documenter-dark .ansi span.sgr9{text-decoration:line-through}html.theme--documenter-dark .ansi span.sgr30{color:#242424}html.theme--documenter-dark .ansi span.sgr31{color:#f6705f}html.theme--documenter-dark .ansi span.sgr32{color:#4fb43a}html.theme--documenter-dark .ansi span.sgr33{color:#f4c72f}html.theme--documenter-dark .ansi span.sgr34{color:#7587f0}html.theme--documenter-dark .ansi span.sgr35{color:#bc89d3}html.theme--documenter-dark .ansi span.sgr36{color:#49b6ca}html.theme--documenter-dark .ansi span.sgr37{color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr40{background-color:#242424}html.theme--documenter-dark .ansi span.sgr41{background-color:#f6705f}html.theme--documenter-dark .ansi span.sgr42{background-color:#4fb43a}html.theme--documenter-dark .ansi span.sgr43{background-color:#f4c72f}html.theme--documenter-dark .ansi span.sgr44{background-color:#7587f0}html.theme--documenter-dark .ansi span.sgr45{background-color:#bc89d3}html.theme--documenter-dark .ansi span.sgr46{background-color:#49b6ca}html.theme--documenter-dark .ansi span.sgr47{background-color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr90{color:#92a0a2}html.theme--documenter-dark .ansi span.sgr91{color:#ff8674}html.theme--documenter-dark .ansi span.sgr92{color:#79d462}html.theme--documenter-dark .ansi span.sgr93{color:#ffe76b}html.theme--documenter-dark .ansi span.sgr94{color:#8a98ff}html.theme--documenter-dark .ansi span.sgr95{color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr96{color:#6bc8db}html.theme--documenter-dark .ansi span.sgr97{color:#ecf0f1}html.theme--documenter-dark .ansi span.sgr100{background-color:#92a0a2}html.theme--documenter-dark .ansi span.sgr101{background-color:#ff8674}html.theme--documenter-dark .ansi span.sgr102{background-color:#79d462}html.theme--documenter-dark .ansi span.sgr103{background-color:#ffe76b}html.theme--documenter-dark .ansi span.sgr104{background-color:#8a98ff}html.theme--documenter-dark .ansi span.sgr105{background-color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr106{background-color:#6bc8db}html.theme--documenter-dark .ansi span.sgr107{background-color:#ecf0f1}html.theme--documenter-dark code.language-julia-repl>span.hljs-meta{color:#4fb43a;font-weight:bolder}html.theme--documenter-dark .hljs{background:#2b2b2b;color:#f8f8f2}html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-quote{color:#d4d0ab}html.theme--documenter-dark .hljs-variable,html.theme--documenter-dark .hljs-template-variable,html.theme--documenter-dark .hljs-tag,html.theme--documenter-dark .hljs-name,html.theme--documenter-dark .hljs-selector-id,html.theme--documenter-dark .hljs-selector-class,html.theme--documenter-dark .hljs-regexp,html.theme--documenter-dark .hljs-deletion{color:#ffa07a}html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-link{color:#f5ab35}html.theme--documenter-dark .hljs-attribute{color:#ffd700}html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-addition{color:#abe338}html.theme--documenter-dark .hljs-title,html.theme--documenter-dark .hljs-section{color:#00e0e0}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{color:#dcc6e0}html.theme--documenter-dark .hljs-emphasis{font-style:italic}html.theme--documenter-dark .hljs-strong{font-weight:bold}@media screen and (-ms-high-contrast: active){html.theme--documenter-dark .hljs-addition,html.theme--documenter-dark .hljs-attribute,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-link,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-quote{color:highlight}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{font-weight:bold}}html.theme--documenter-dark .hljs-subst{color:#f8f8f2}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333 !important;background-color:#f1f5f9 !important}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:whitesmoke;background-color:#33415580;border-radius:0.6rem}html.theme--documenter-dark .search-result-title{color:whitesmoke}html.theme--documenter-dark .search-result-highlight{background-color:greenyellow;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem} diff --git a/previews/PR2418/assets/themes/documenter-light.css b/previews/PR2418/assets/themes/documenter-light.css new file mode 100644 index 0000000000..2f168c77b4 --- /dev/null +++ b/previews/PR2418/assets/themes/documenter-light.css @@ -0,0 +1,9 @@ +.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.file-cta,.file-name,.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input,.button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus,.pagination-ellipsis:focus,.file-cta:focus,.file-name:focus,.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.button:focus,.is-focused.pagination-previous,.is-focused.pagination-next,.is-focused.pagination-link,.is-focused.pagination-ellipsis,.is-focused.file-cta,.is-focused.file-name,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-focused.button,.pagination-previous:active,.pagination-next:active,.pagination-link:active,.pagination-ellipsis:active,.file-cta:active,.file-name:active,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.button:active,.is-active.pagination-previous,.is-active.pagination-next,.is-active.pagination-link,.is-active.pagination-ellipsis,.is-active.file-cta,.is-active.file-name,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.is-active.button{outline:none}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled],.pagination-ellipsis[disabled],.file-cta[disabled],.file-name[disabled],.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],.button[disabled],fieldset[disabled] .pagination-previous,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] .button{cursor:not-allowed}.tabs,.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.breadcrumb,.file,.button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}.admonition:not(:last-child),.tabs:not(:last-child),.pagination:not(:last-child),.message:not(:last-child),.level:not(:last-child),.breadcrumb:not(:last-child),.block:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.progress:not(:last-child),.notification:not(:last-child),.content:not(:last-child),.box:not(:last-child){margin-bottom:1.5rem}.modal-close,.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}.modal-close::before,.delete::before,.modal-close::after,.delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.modal-close::before,.delete::before{height:2px;width:50%}.modal-close::after,.delete::after{height:50%;width:2px}.modal-close:hover,.delete:hover,.modal-close:focus,.delete:focus{background-color:rgba(10,10,10,0.3)}.modal-close:active,.delete:active{background-color:rgba(10,10,10,0.4)}.is-small.modal-close,#documenter .docs-sidebar form.docs-search>input.modal-close,.is-small.delete,#documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.modal-close,.is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.modal-close,.is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.control.is-loading::after,.select.is-loading::after,.loader,.button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.modal-background,.modal,.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363636 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c1c !important}.has-background-dark{background-color:#363636 !important}.has-text-primary{color:#4eb5de !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#27a1d2 !important}.has-background-primary{background-color:#4eb5de !important}.has-text-primary-light{color:#eef8fc !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#c3e6f4 !important}.has-background-primary-light{background-color:#eef8fc !important}.has-text-primary-dark{color:#1a6d8e !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#228eb9 !important}.has-background-primary-dark{background-color:#1a6d8e !important}.has-text-link{color:#2e63b8 !important}a.has-text-link:hover,a.has-text-link:focus{color:#244d8f !important}.has-background-link{background-color:#2e63b8 !important}.has-text-link-light{color:#eff3fb !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c6d6f1 !important}.has-background-link-light{background-color:#eff3fb !important}.has-text-link-dark{color:#3169c4 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#5485d4 !important}.has-background-link-dark{background-color:#3169c4 !important}.has-text-info{color:#209cee !important}a.has-text-info:hover,a.has-text-info:focus{color:#1081cb !important}.has-background-info{background-color:#209cee !important}.has-text-info-light{color:#ecf7fe !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#bde2fa !important}.has-background-info-light{background-color:#ecf7fe !important}.has-text-info-dark{color:#0e72b4 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#1190e3 !important}.has-background-info-dark{background-color:#0e72b4 !important}.has-text-success{color:#22c35b !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a9847 !important}.has-background-success{background-color:#22c35b !important}.has-text-success-light{color:#eefcf3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#c2f4d4 !important}.has-background-success-light{background-color:#eefcf3 !important}.has-text-success-dark{color:#198f43 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#21bb57 !important}.has-background-success-dark{background-color:#198f43 !important}.has-text-warning{color:#ffdd57 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#ffd324 !important}.has-background-warning{background-color:#ffdd57 !important}.has-text-warning-light{color:#fffbeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fff1b8 !important}.has-background-warning-light{background-color:#fffbeb !important}.has-text-warning-dark{color:#947600 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#c79f00 !important}.has-background-warning-dark{background-color:#947600 !important}.has-text-danger{color:#da0b00 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a70800 !important}.has-background-danger{background-color:#da0b00 !important}.has-text-danger-light{color:#ffeceb !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#ffbbb8 !important}.has-background-danger-light{background-color:#ffeceb !important}.has-text-danger-dark{color:#f50c00 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#ff3429 !important}.has-background-danger-dark{background-color:#f50c00 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363636 !important}.has-background-grey-darker{background-color:#363636 !important}.has-text-grey-dark{color:#4a4a4a !important}.has-background-grey-dark{background-color:#4a4a4a !important}.has-text-grey{color:#6b6b6b !important}.has-background-grey{background-color:#6b6b6b !important}.has-text-grey-light{color:#b5b5b5 !important}.has-background-grey-light{background-color:#b5b5b5 !important}.has-text-grey-lighter{color:#dbdbdb !important}.has-background-grey-lighter{background-color:#dbdbdb !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,.docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}body{color:#222;font-size:1em;font-weight:400;line-height:1.5}a{color:#2e63b8;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:rgba(0,0,0,0.05);color:#000;font-size:.875em;font-weight:normal;padding:.1em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#222;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#222;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#222}@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:#bbb;color:#222;display:block;padding:1.25rem}a.box:hover,a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #2e63b8}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #2e63b8}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#222;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-small,.button #documenter .docs-sidebar form.docs-search>input.icon,#documenter .docs-sidebar .button form.docs-search>input.icon,.button .icon.is-medium,.button .icon.is-large{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}.button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}.button:hover,.button.is-hovered{border-color:#b5b5b5;color:#363636}.button:focus,.button.is-focused{border-color:#3c5dcd;color:#363636}.button:focus:not(:active),.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button:active,.button.is-active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#222;text-decoration:underline}.button.is-text:hover,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text.is-focused{background-color:#f5f5f5;color:#222}.button.is-text:active,.button.is-text.is-active{background-color:#e8e8e8;color:#222}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#2e63b8;text-decoration:none}.button.is-ghost:hover,.button.is-ghost.is-hovered{color:#2e63b8;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white:hover,.button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white:focus,.button.is-white.is-focused{border-color:transparent;color:#0a0a0a}.button.is-white:focus:not(:active),.button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.button.is-white:active,.button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover,.button.is-white.is-inverted.is-hovered{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:hover,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-outlined.is-loading:hover::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:hover,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading:hover::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black:hover,.button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}.button.is-black:focus,.button.is-black.is-focused{border-color:transparent;color:#fff}.button.is-black:focus:not(:active),.button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.button.is-black:active,.button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover,.button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:hover,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-outlined.is-loading:hover::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:hover,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading:hover::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:hover,.button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus,.button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus:not(:active),.button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.button.is-light:active,.button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted:hover,.button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:hover,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-outlined.is-loading:hover::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-light.is-inverted.is-outlined:hover,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading:hover::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-dark,.content kbd.button{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark:hover,.content kbd.button:hover,.button.is-dark.is-hovered,.content kbd.button.is-hovered{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark:focus,.content kbd.button:focus,.button.is-dark.is-focused,.content kbd.button.is-focused{border-color:transparent;color:#fff}.button.is-dark:focus:not(:active),.content kbd.button:focus:not(:active),.button.is-dark.is-focused:not(:active),.content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.button.is-dark:active,.content kbd.button:active,.button.is-dark.is-active,.content kbd.button.is-active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],.content kbd.button[disabled],fieldset[disabled] .button.is-dark,fieldset[disabled] .content kbd.button,.content fieldset[disabled] kbd.button{background-color:#363636;border-color:#363636;box-shadow:none}.button.is-dark.is-inverted,.content kbd.button.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted:hover,.content kbd.button.is-inverted:hover,.button.is-dark.is-inverted.is-hovered,.content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],.content kbd.button.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted,fieldset[disabled] .content kbd.button.is-inverted,.content fieldset[disabled] kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after,.content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined,.content kbd.button.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:hover,.content kbd.button.is-outlined:hover,.button.is-dark.is-outlined.is-hovered,.content kbd.button.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.content kbd.button.is-outlined:focus,.button.is-dark.is-outlined.is-focused,.content kbd.button.is-outlined.is-focused{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after,.content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-outlined.is-loading:hover::after,.content kbd.button.is-outlined.is-loading:hover::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.content kbd.button.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading.is-focused::after,.content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined[disabled],.content kbd.button.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined,fieldset[disabled] .content kbd.button.is-outlined,.content fieldset[disabled] kbd.button.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined,.content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined:hover,.content kbd.button.is-inverted.is-outlined:hover,.button.is-dark.is-inverted.is-outlined.is-hovered,.content kbd.button.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.content kbd.button.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined.is-focused,.content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading:hover::after,.content kbd.button.is-inverted.is-outlined.is-loading:hover::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.content kbd.button.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-inverted.is-outlined[disabled],.content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined,fieldset[disabled] .content kbd.button.is-inverted.is-outlined,.content fieldset[disabled] kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary,.docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;color:#fff}.button.is-primary:hover,.docstring>section>a.button.docs-sourcelink:hover,.button.is-primary.is-hovered,.docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#43b1dc;border-color:transparent;color:#fff}.button.is-primary:focus,.docstring>section>a.button.docs-sourcelink:focus,.button.is-primary.is-focused,.docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}.button.is-primary:focus:not(:active),.docstring>section>a.button.docs-sourcelink:focus:not(:active),.button.is-primary.is-focused:not(:active),.docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.button.is-primary:active,.docstring>section>a.button.docs-sourcelink:active,.button.is-primary.is-active,.docstring>section>a.button.is-active.docs-sourcelink{background-color:#39acda;border-color:transparent;color:#fff}.button.is-primary[disabled],.docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary,fieldset[disabled] .docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;box-shadow:none}.button.is-primary.is-inverted,.docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted:hover,.docstring>section>a.button.is-inverted.docs-sourcelink:hover,.button.is-primary.is-inverted.is-hovered,.docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],.docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted,fieldset[disabled] .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#4eb5de}.button.is-primary.is-loading::after,.docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined,.docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;color:#4eb5de}.button.is-primary.is-outlined:hover,.docstring>section>a.button.is-outlined.docs-sourcelink:hover,.button.is-primary.is-outlined.is-hovered,.docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-outlined:focus,.docstring>section>a.button.is-outlined.docs-sourcelink:focus,.button.is-primary.is-outlined.is-focused,.docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.button.is-primary.is-outlined.is-loading::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined[disabled],.docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-outlined,fieldset[disabled] .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;box-shadow:none;color:#4eb5de}.button.is-primary.is-inverted.is-outlined,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,.button.is-primary.is-inverted.is-outlined.is-hovered,.docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-inverted.is-outlined:focus,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,.button.is-primary.is-inverted.is-outlined.is-focused,.docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-inverted.is-outlined[disabled],.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined,fieldset[disabled] .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light,.docstring>section>a.button.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.button.is-primary.is-light:hover,.docstring>section>a.button.is-light.docs-sourcelink:hover,.button.is-primary.is-light.is-hovered,.docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e3f3fa;border-color:transparent;color:#1a6d8e}.button.is-primary.is-light:active,.docstring>section>a.button.is-light.docs-sourcelink:active,.button.is-primary.is-light.is-active,.docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d8eff8;border-color:transparent;color:#1a6d8e}.button.is-link{background-color:#2e63b8;border-color:transparent;color:#fff}.button.is-link:hover,.button.is-link.is-hovered{background-color:#2b5eae;border-color:transparent;color:#fff}.button.is-link:focus,.button.is-link.is-focused{border-color:transparent;color:#fff}.button.is-link:focus:not(:active),.button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button.is-link:active,.button.is-link.is-active{background-color:#2958a4;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#2e63b8;border-color:#2e63b8;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted:hover,.button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#2e63b8}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;color:#2e63b8}.button.is-link.is-outlined:hover,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined.is-focused{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-outlined.is-loading:hover::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;box-shadow:none;color:#2e63b8}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:hover,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted.is-outlined.is-loading:hover::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff3fb;color:#3169c4}.button.is-link.is-light:hover,.button.is-link.is-light.is-hovered{background-color:#e4ecf8;border-color:transparent;color:#3169c4}.button.is-link.is-light:active,.button.is-link.is-light.is-active{background-color:#dae5f6;border-color:transparent;color:#3169c4}.button.is-info{background-color:#209cee;border-color:transparent;color:#fff}.button.is-info:hover,.button.is-info.is-hovered{background-color:#1497ed;border-color:transparent;color:#fff}.button.is-info:focus,.button.is-info.is-focused{border-color:transparent;color:#fff}.button.is-info:focus:not(:active),.button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.button.is-info:active,.button.is-info.is-active{background-color:#1190e3;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#209cee;border-color:#209cee;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#209cee}.button.is-info.is-inverted:hover,.button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#209cee}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined{background-color:transparent;border-color:#209cee;color:#209cee}.button.is-info.is-outlined:hover,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined.is-focused{background-color:#209cee;border-color:#209cee;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-outlined.is-loading:hover::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#209cee;box-shadow:none;color:#209cee}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#209cee}.button.is-info.is-inverted.is-outlined.is-loading:hover::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.button.is-info.is-light:hover,.button.is-info.is-light.is-hovered{background-color:#e0f1fd;border-color:transparent;color:#0e72b4}.button.is-info.is-light:active,.button.is-info.is-light.is-active{background-color:#d4ecfc;border-color:transparent;color:#0e72b4}.button.is-success{background-color:#22c35b;border-color:transparent;color:#fff}.button.is-success:hover,.button.is-success.is-hovered{background-color:#20b856;border-color:transparent;color:#fff}.button.is-success:focus,.button.is-success.is-focused{border-color:transparent;color:#fff}.button.is-success:focus:not(:active),.button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.button.is-success:active,.button.is-success.is-active{background-color:#1ead51;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#22c35b;border-color:#22c35b;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#22c35b}.button.is-success.is-inverted:hover,.button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#22c35b}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;color:#22c35b}.button.is-success.is-outlined:hover,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined.is-focused{background-color:#22c35b;border-color:#22c35b;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-outlined.is-loading:hover::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;box-shadow:none;color:#22c35b}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#22c35b}.button.is-success.is-inverted.is-outlined.is-loading:hover::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#eefcf3;color:#198f43}.button.is-success.is-light:hover,.button.is-success.is-light.is-hovered{background-color:#e3faeb;border-color:transparent;color:#198f43}.button.is-success.is-light:active,.button.is-success.is-light.is-active{background-color:#d8f8e3;border-color:transparent;color:#198f43}.button.is-warning{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:hover,.button.is-warning.is-hovered{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus,.button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus:not(:active),.button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.button.is-warning:active,.button.is-warning.is-active{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffdd57;border-color:#ffdd57;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted:hover,.button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ffdd57}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;color:#ffdd57}.button.is-warning.is-outlined:hover,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined.is-focused{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-outlined.is-loading:hover::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;box-shadow:none;color:#ffdd57}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted.is-outlined:hover,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted.is-outlined.is-loading:hover::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-warning.is-light{background-color:#fffbeb;color:#947600}.button.is-warning.is-light:hover,.button.is-warning.is-light.is-hovered{background-color:#fff8de;border-color:transparent;color:#947600}.button.is-warning.is-light:active,.button.is-warning.is-light.is-active{background-color:#fff6d1;border-color:transparent;color:#947600}.button.is-danger{background-color:#da0b00;border-color:transparent;color:#fff}.button.is-danger:hover,.button.is-danger.is-hovered{background-color:#cd0a00;border-color:transparent;color:#fff}.button.is-danger:focus,.button.is-danger.is-focused{border-color:transparent;color:#fff}.button.is-danger:focus:not(:active),.button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.button.is-danger:active,.button.is-danger.is-active{background-color:#c10a00;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#da0b00;border-color:#da0b00;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted:hover,.button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#da0b00}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;color:#da0b00}.button.is-danger.is-outlined:hover,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined.is-focused{background-color:#da0b00;border-color:#da0b00;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-outlined.is-loading:hover::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;box-shadow:none;color:#da0b00}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted.is-outlined.is-loading:hover::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.button.is-danger.is-light:hover,.button.is-danger.is-light.is-hovered{background-color:#ffe0de;border-color:transparent;color:#f50c00}.button.is-danger.is-light:active,.button.is-danger.is-light.is-active{background-color:#ffd3d1;border-color:transparent;color:#f50c00}.button.is-small,#documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}.button.is-small:not(.is-rounded),#documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent !important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#6b6b6b;box-shadow:none;pointer-events:none}.button.is-rounded,#documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:0.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}.buttons:last-child{margin-bottom:-0.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button:hover,.buttons.has-addons .button.is-hovered{z-index:2}.buttons.has-addons .button:focus,.buttons.has-addons .button.is-focused,.buttons.has-addons .button:active,.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-selected{z-index:3}.buttons.has-addons .button:focus:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-selected:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.65625rem}.button.is-responsive.is-medium{font-size:.75rem}.button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.75rem}.button.is-responsive.is-medium{font-size:1rem}.button.is-responsive.is-large{font-size:1.25rem}}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){.container{max-width:992px}}@media screen and (max-width: 1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:0.25em}.content p:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content ul:not(:last-child),.content blockquote:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:0.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:0.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:0.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:0.8em}.content h5{font-size:1.125em;margin-bottom:0.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}.content ol.is-lower-roman:not([type]){list-style-type:lower-roman}.content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}.content ol.is-upper-roman:not([type]){list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}.content sup,.content sub{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.content table th{color:#222}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#222}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#222}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small,#documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small,#documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-right:.25em}.icon-text .icon:not(:first-child){margin-left:.25em}div.icon-text{display:flex}.image,#documenter .docs-sidebar .docs-logo>img{display:block;position:relative}.image img,#documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}.image img.is-rounded,#documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}.image.is-fullwidth,#documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}.image.is-square,#documenter .docs-sidebar .docs-logo>img.is-square,.image.is-1by1,#documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}.image.is-5by4,#documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}.image.is-4by3,#documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}.image.is-3by2,#documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}.image.is-5by3,#documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}.image.is-16by9,#documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}.image.is-2by1,#documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}.image.is-3by1,#documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}.image.is-4by5,#documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}.image.is-3by4,#documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}.image.is-2by3,#documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}.image.is-3by5,#documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}.image.is-9by16,#documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}.image.is-1by2,#documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}.image.is-1by3,#documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}.image.is-16x16,#documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}.image.is-24x24,#documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}.image.is-32x32,#documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}.image.is-48x48,#documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}.image.is-64x64,#documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}.image.is-96x96,#documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}.image.is-128x128,#documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:transparent}.notification>.delete{right:.5rem;position:absolute;top:0.5rem}.notification .title,.notification .subtitle,.notification .content{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.notification.is-dark,.content kbd.notification{background-color:#363636;color:#fff}.notification.is-primary,.docstring>section>a.notification.docs-sourcelink{background-color:#4eb5de;color:#fff}.notification.is-primary.is-light,.docstring>section>a.notification.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.notification.is-link{background-color:#2e63b8;color:#fff}.notification.is-link.is-light{background-color:#eff3fb;color:#3169c4}.notification.is-info{background-color:#209cee;color:#fff}.notification.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.notification.is-success{background-color:#22c35b;color:#fff}.notification.is-success.is-light{background-color:#eefcf3;color:#198f43}.notification.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.notification.is-warning.is-light{background-color:#fffbeb;color:#947600}.notification.is-danger{background-color:#da0b00;color:#fff}.notification.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#222}.progress::-moz-progress-bar{background-color:#222}.progress::-ms-fill{background-color:#222;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #ededed 30%)}.progress.is-dark::-webkit-progress-value,.content kbd.progress::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar,.content kbd.progress::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill,.content kbd.progress::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate,.content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363636 30%, #ededed 30%)}.progress.is-primary::-webkit-progress-value,.docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#4eb5de}.progress.is-primary::-moz-progress-bar,.docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#4eb5de}.progress.is-primary::-ms-fill,.docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#4eb5de}.progress.is-primary:indeterminate,.docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #4eb5de 30%, #ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#2e63b8}.progress.is-link::-moz-progress-bar{background-color:#2e63b8}.progress.is-link::-ms-fill{background-color:#2e63b8}.progress.is-link:indeterminate{background-image:linear-gradient(to right, #2e63b8 30%, #ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#209cee}.progress.is-info::-moz-progress-bar{background-color:#209cee}.progress.is-info::-ms-fill{background-color:#209cee}.progress.is-info:indeterminate{background-image:linear-gradient(to right, #209cee 30%, #ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#22c35b}.progress.is-success::-moz-progress-bar{background-color:#22c35b}.progress.is-success::-ms-fill{background-color:#22c35b}.progress.is-success:indeterminate{background-image:linear-gradient(to right, #22c35b 30%, #ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffdd57}.progress.is-warning::-moz-progress-bar{background-color:#ffdd57}.progress.is-warning::-ms-fill{background-color:#ffdd57}.progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ffdd57 30%, #ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#da0b00}.progress.is-danger::-moz-progress-bar{background-color:#da0b00}.progress.is-danger::-ms-fill{background-color:#da0b00}.progress.is-danger:indeterminate{background-image:linear-gradient(to right, #da0b00 30%, #ededed 30%)}.progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right, #222 30%, #ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small,#documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#222}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.table td.is-link,.table th.is-link{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.table td.is-info,.table th.is-info{background-color:#209cee;border-color:#209cee;color:#fff}.table td.is-success,.table th.is-success{background-color:#22c35b;border-color:#22c35b;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.table td.is-danger,.table th.is-danger{background-color:#da0b00;border-color:#da0b00;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#4eb5de;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#222}.table th:not([align]){text-align:left}.table tr.is-selected{background-color:#4eb5de;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:rgba(0,0,0,0)}.table thead td,.table thead th{border-width:0 0 2px;color:#222}.table tfoot{background-color:rgba(0,0,0,0)}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#222}.table tbody{background-color:rgba(0,0,0,0)}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:0.25em 0.5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag,.tags .content kbd,.content .tags kbd,.tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}.tags .tag:not(:last-child),.tags .content kbd:not(:last-child),.content .tags kbd:not(:last-child),.tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-0.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large),.tags.are-medium .content kbd:not(.is-normal):not(.is-large),.content .tags.are-medium kbd:not(.is-normal):not(.is-large),.tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium),.tags.are-large .content kbd:not(.is-normal):not(.is-medium),.content .tags.are-large kbd:not(.is-normal):not(.is-medium),.tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag,.tags.is-centered .content kbd,.content .tags.is-centered kbd,.tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child),.tags.is-right .content kbd:not(:first-child),.content .tags.is-right kbd:not(:first-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}.tags.is-right .tag:not(:last-child),.tags.is-right .content kbd:not(:last-child),.content .tags.is-right kbd:not(:last-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}.tags.has-addons .tag,.tags.has-addons .content kbd,.content .tags.has-addons kbd,.tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}.tags.has-addons .tag:not(:first-child),.tags.has-addons .content kbd:not(:first-child),.content .tags.has-addons kbd:not(:first-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.tags.has-addons .tag:not(:last-child),.tags.has-addons .content kbd:not(:last-child),.content .tags.has-addons kbd:not(:last-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.tag:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#222;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.tag:not(body) .delete,.content kbd:not(body) .delete,.docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}.tag.is-white:not(body),.content kbd.is-white:not(body),.docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}.tag.is-black:not(body),.content kbd.is-black:not(body),.docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}.tag.is-light:not(body),.content kbd.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.tag.is-dark:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink.is-dark:not(body),.content .docstring>section>kbd:not(body){background-color:#363636;color:#fff}.tag.is-primary:not(body),.content kbd.is-primary:not(body),.docstring>section>a.docs-sourcelink:not(body){background-color:#4eb5de;color:#fff}.tag.is-primary.is-light:not(body),.content kbd.is-primary.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#eef8fc;color:#1a6d8e}.tag.is-link:not(body),.content kbd.is-link:not(body),.docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#2e63b8;color:#fff}.tag.is-link.is-light:not(body),.content kbd.is-link.is-light:not(body),.docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#eff3fb;color:#3169c4}.tag.is-info:not(body),.content kbd.is-info:not(body),.docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#209cee;color:#fff}.tag.is-info.is-light:not(body),.content kbd.is-info.is-light:not(body),.docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ecf7fe;color:#0e72b4}.tag.is-success:not(body),.content kbd.is-success:not(body),.docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#22c35b;color:#fff}.tag.is-success.is-light:not(body),.content kbd.is-success.is-light:not(body),.docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#eefcf3;color:#198f43}.tag.is-warning:not(body),.content kbd.is-warning:not(body),.docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ffdd57;color:rgba(0,0,0,0.7)}.tag.is-warning.is-light:not(body),.content kbd.is-warning.is-light:not(body),.docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffbeb;color:#947600}.tag.is-danger:not(body),.content kbd.is-danger:not(body),.docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#da0b00;color:#fff}.tag.is-danger.is-light:not(body),.content kbd.is-danger.is-light:not(body),.docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#ffeceb;color:#f50c00}.tag.is-normal:not(body),.content kbd.is-normal:not(body),.docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}.tag.is-medium:not(body),.content kbd.is-medium:not(body),.docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}.tag.is-large:not(body),.content kbd.is-large:not(body),.docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child),.content kbd:not(body) .icon:first-child:not(:last-child),.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child),.content kbd:not(body) .icon:last-child:not(:first-child),.docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child,.content kbd:not(body) .icon:first-child:last-child,.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag.is-delete:not(body),.content kbd.is-delete:not(body),.docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before,.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}.tag.is-delete:not(body):hover,.content kbd.is-delete:not(body):hover,.docstring>section>a.docs-sourcelink.is-delete:not(body):hover,.tag.is-delete:not(body):focus,.content kbd.is-delete:not(body):focus,.docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#e8e8e8}.tag.is-delete:not(body):active,.content kbd.is-delete:not(body):active,.docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#dbdbdb}.tag.is-rounded:not(body),#documenter .docs-sidebar form.docs-search>input:not(body),.content kbd.is-rounded:not(body),#documenter .docs-sidebar .content form.docs-search>input:not(body),.docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}a.tag:hover,.docstring>section>a.docs-sourcelink:hover{text-decoration:underline}.title,.subtitle{word-break:break-word}.title em,.title span,.subtitle em,.subtitle span{font-weight:inherit}.title sub,.subtitle sub{font-size:.75em}.title sup,.subtitle sup{font-size:.75em}.title .tag,.title .content kbd,.content .title kbd,.title .docstring>section>a.docs-sourcelink,.subtitle .tag,.subtitle .content kbd,.content .subtitle kbd,.subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}.title{color:#222;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#222;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#222;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#222}.select select::-moz-placeholder,.textarea::-moz-placeholder,.input::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#707070}.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder,.input::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#707070}.select select:-moz-placeholder,.textarea:-moz-placeholder,.input:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#707070}.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder,.input:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#707070}.select select:hover,.textarea:hover,.input:hover,#documenter .docs-sidebar form.docs-search>input:hover,.select select.is-hovered,.is-hovered.textarea,.is-hovered.input,#documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#b5b5b5}.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{border-color:#2e63b8;box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#6b6b6b}.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,.input[disabled]::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-webkit-input-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,.input[disabled]:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-ms-input-placeholder{color:rgba(107,107,107,0.3)}.textarea,.input,#documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}.textarea[readonly],.input[readonly],#documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}.is-white.textarea,.is-white.input,#documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}.is-white.textarea:focus,.is-white.input:focus,#documenter .docs-sidebar form.docs-search>input.is-white:focus,.is-white.is-focused.textarea,.is-white.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-white.textarea:active,.is-white.input:active,#documenter .docs-sidebar form.docs-search>input.is-white:active,.is-white.is-active.textarea,.is-white.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.is-black.textarea,.is-black.input,#documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}.is-black.textarea:focus,.is-black.input:focus,#documenter .docs-sidebar form.docs-search>input.is-black:focus,.is-black.is-focused.textarea,.is-black.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-black.textarea:active,.is-black.input:active,#documenter .docs-sidebar form.docs-search>input.is-black:active,.is-black.is-active.textarea,.is-black.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.is-light.textarea,.is-light.input,#documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}.is-light.textarea:focus,.is-light.input:focus,#documenter .docs-sidebar form.docs-search>input.is-light:focus,.is-light.is-focused.textarea,.is-light.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-light.textarea:active,.is-light.input:active,#documenter .docs-sidebar form.docs-search>input.is-light:active,.is-light.is-active.textarea,.is-light.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.is-dark.textarea,.content kbd.textarea,.is-dark.input,#documenter .docs-sidebar form.docs-search>input.is-dark,.content kbd.input{border-color:#363636}.is-dark.textarea:focus,.content kbd.textarea:focus,.is-dark.input:focus,#documenter .docs-sidebar form.docs-search>input.is-dark:focus,.content kbd.input:focus,.is-dark.is-focused.textarea,.content kbd.is-focused.textarea,.is-dark.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.content kbd.is-focused.input,#documenter .docs-sidebar .content form.docs-search>input.is-focused,.is-dark.textarea:active,.content kbd.textarea:active,.is-dark.input:active,#documenter .docs-sidebar form.docs-search>input.is-dark:active,.content kbd.input:active,.is-dark.is-active.textarea,.content kbd.is-active.textarea,.is-dark.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.content kbd.is-active.input,#documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.is-primary.textarea,.docstring>section>a.textarea.docs-sourcelink,.is-primary.input,#documenter .docs-sidebar form.docs-search>input.is-primary,.docstring>section>a.input.docs-sourcelink{border-color:#4eb5de}.is-primary.textarea:focus,.docstring>section>a.textarea.docs-sourcelink:focus,.is-primary.input:focus,#documenter .docs-sidebar form.docs-search>input.is-primary:focus,.docstring>section>a.input.docs-sourcelink:focus,.is-primary.is-focused.textarea,.docstring>section>a.is-focused.textarea.docs-sourcelink,.is-primary.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.docstring>section>a.is-focused.input.docs-sourcelink,.is-primary.textarea:active,.docstring>section>a.textarea.docs-sourcelink:active,.is-primary.input:active,#documenter .docs-sidebar form.docs-search>input.is-primary:active,.docstring>section>a.input.docs-sourcelink:active,.is-primary.is-active.textarea,.docstring>section>a.is-active.textarea.docs-sourcelink,.is-primary.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.is-link.textarea,.is-link.input,#documenter .docs-sidebar form.docs-search>input.is-link{border-color:#2e63b8}.is-link.textarea:focus,.is-link.input:focus,#documenter .docs-sidebar form.docs-search>input.is-link:focus,.is-link.is-focused.textarea,.is-link.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-link.textarea:active,.is-link.input:active,#documenter .docs-sidebar form.docs-search>input.is-link:active,.is-link.is-active.textarea,.is-link.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.is-info.textarea,.is-info.input,#documenter .docs-sidebar form.docs-search>input.is-info{border-color:#209cee}.is-info.textarea:focus,.is-info.input:focus,#documenter .docs-sidebar form.docs-search>input.is-info:focus,.is-info.is-focused.textarea,.is-info.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-info.textarea:active,.is-info.input:active,#documenter .docs-sidebar form.docs-search>input.is-info:active,.is-info.is-active.textarea,.is-info.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.is-success.textarea,.is-success.input,#documenter .docs-sidebar form.docs-search>input.is-success{border-color:#22c35b}.is-success.textarea:focus,.is-success.input:focus,#documenter .docs-sidebar form.docs-search>input.is-success:focus,.is-success.is-focused.textarea,.is-success.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-success.textarea:active,.is-success.input:active,#documenter .docs-sidebar form.docs-search>input.is-success:active,.is-success.is-active.textarea,.is-success.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.is-warning.textarea,.is-warning.input,#documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ffdd57}.is-warning.textarea:focus,.is-warning.input:focus,#documenter .docs-sidebar form.docs-search>input.is-warning:focus,.is-warning.is-focused.textarea,.is-warning.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-warning.textarea:active,.is-warning.input:active,#documenter .docs-sidebar form.docs-search>input.is-warning:active,.is-warning.is-active.textarea,.is-warning.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.is-danger.textarea,.is-danger.input,#documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#da0b00}.is-danger.textarea:focus,.is-danger.input:focus,#documenter .docs-sidebar form.docs-search>input.is-danger:focus,.is-danger.is-focused.textarea,.is-danger.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-danger.textarea:active,.is-danger.input:active,#documenter .docs-sidebar form.docs-search>input.is-danger:active,.is-danger.is-active.textarea,.is-danger.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.is-small.textarea,.is-small.input,#documenter .docs-sidebar form.docs-search>input{border-radius:2px;font-size:.75rem}.is-medium.textarea,.is-medium.input,#documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}.is-large.textarea,.is-large.input,#documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}.is-fullwidth.textarea,.is-fullwidth.input,#documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}.is-inline.textarea,.is-inline.input,#documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}.input.is-rounded,#documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}.input.is-static,#documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.radio,.checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.radio input,.checkbox input{cursor:pointer}.radio:hover,.checkbox:hover{color:#222}.radio[disabled],.checkbox[disabled],fieldset[disabled] .radio,fieldset[disabled] .checkbox,.radio input[disabled],.checkbox input[disabled]{color:#6b6b6b;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#2e63b8;right:1.125em;z-index:4}.select.is-rounded select,#documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:0.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#222}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select:hover,.select.is-white select.is-hovered{border-color:#f2f2f2}.select.is-white select:focus,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select:hover,.select.is-black select.is-hovered{border-color:#000}.select.is-black select:focus,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select:hover,.select.is-light select.is-hovered{border-color:#e8e8e8}.select.is-light select:focus,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.select.is-dark:not(:hover)::after,.content kbd.select:not(:hover)::after{border-color:#363636}.select.is-dark select,.content kbd.select select{border-color:#363636}.select.is-dark select:hover,.content kbd.select select:hover,.select.is-dark select.is-hovered,.content kbd.select select.is-hovered{border-color:#292929}.select.is-dark select:focus,.content kbd.select select:focus,.select.is-dark select.is-focused,.content kbd.select select.is-focused,.select.is-dark select:active,.content kbd.select select:active,.select.is-dark select.is-active,.content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.select.is-primary:not(:hover)::after,.docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#4eb5de}.select.is-primary select,.docstring>section>a.select.docs-sourcelink select{border-color:#4eb5de}.select.is-primary select:hover,.docstring>section>a.select.docs-sourcelink select:hover,.select.is-primary select.is-hovered,.docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#39acda}.select.is-primary select:focus,.docstring>section>a.select.docs-sourcelink select:focus,.select.is-primary select.is-focused,.docstring>section>a.select.docs-sourcelink select.is-focused,.select.is-primary select:active,.docstring>section>a.select.docs-sourcelink select:active,.select.is-primary select.is-active,.docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.select.is-link:not(:hover)::after{border-color:#2e63b8}.select.is-link select{border-color:#2e63b8}.select.is-link select:hover,.select.is-link select.is-hovered{border-color:#2958a4}.select.is-link select:focus,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select.is-info:not(:hover)::after{border-color:#209cee}.select.is-info select{border-color:#209cee}.select.is-info select:hover,.select.is-info select.is-hovered{border-color:#1190e3}.select.is-info select:focus,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.select.is-success:not(:hover)::after{border-color:#22c35b}.select.is-success select{border-color:#22c35b}.select.is-success select:hover,.select.is-success select.is-hovered{border-color:#1ead51}.select.is-success select:focus,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.select.is-warning:not(:hover)::after{border-color:#ffdd57}.select.is-warning select{border-color:#ffdd57}.select.is-warning select:hover,.select.is-warning select.is-hovered{border-color:#ffd83e}.select.is-warning select:focus,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.select.is-danger:not(:hover)::after{border-color:#da0b00}.select.is-danger select{border-color:#da0b00}.select.is-danger select:hover,.select.is-danger select.is-hovered{border-color:#c10a00}.select.is-danger select:focus,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.select.is-small,#documenter .docs-sidebar form.docs-search>input.select{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#6b6b6b !important;opacity:0.5}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}.select.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white:hover .file-cta,.file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white:focus .file-cta,.file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}.file.is-white:active .file-cta,.file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black:hover .file-cta,.file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black:focus .file-cta,.file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}.file.is-black:active .file-cta,.file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:hover .file-cta,.file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:focus .file-cta,.file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}.file.is-light:active .file-cta,.file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-dark .file-cta,.content kbd.file .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark:hover .file-cta,.content kbd.file:hover .file-cta,.file.is-dark.is-hovered .file-cta,.content kbd.file.is-hovered .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark:focus .file-cta,.content kbd.file:focus .file-cta,.file.is-dark.is-focused .file-cta,.content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,54,54,0.25);color:#fff}.file.is-dark:active .file-cta,.content kbd.file:active .file-cta,.file.is-dark.is-active .file-cta,.content kbd.file.is-active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta,.docstring>section>a.file.docs-sourcelink .file-cta{background-color:#4eb5de;border-color:transparent;color:#fff}.file.is-primary:hover .file-cta,.docstring>section>a.file.docs-sourcelink:hover .file-cta,.file.is-primary.is-hovered .file-cta,.docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#43b1dc;border-color:transparent;color:#fff}.file.is-primary:focus .file-cta,.docstring>section>a.file.docs-sourcelink:focus .file-cta,.file.is-primary.is-focused .file-cta,.docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(78,181,222,0.25);color:#fff}.file.is-primary:active .file-cta,.docstring>section>a.file.docs-sourcelink:active .file-cta,.file.is-primary.is-active .file-cta,.docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#39acda;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#2e63b8;border-color:transparent;color:#fff}.file.is-link:hover .file-cta,.file.is-link.is-hovered .file-cta{background-color:#2b5eae;border-color:transparent;color:#fff}.file.is-link:focus .file-cta,.file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(46,99,184,0.25);color:#fff}.file.is-link:active .file-cta,.file.is-link.is-active .file-cta{background-color:#2958a4;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#209cee;border-color:transparent;color:#fff}.file.is-info:hover .file-cta,.file.is-info.is-hovered .file-cta{background-color:#1497ed;border-color:transparent;color:#fff}.file.is-info:focus .file-cta,.file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(32,156,238,0.25);color:#fff}.file.is-info:active .file-cta,.file.is-info.is-active .file-cta{background-color:#1190e3;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#22c35b;border-color:transparent;color:#fff}.file.is-success:hover .file-cta,.file.is-success.is-hovered .file-cta{background-color:#20b856;border-color:transparent;color:#fff}.file.is-success:focus .file-cta,.file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(34,195,91,0.25);color:#fff}.file.is-success:active .file-cta,.file.is-success.is-active .file-cta{background-color:#1ead51;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:hover .file-cta,.file.is-warning.is-hovered .file-cta{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:focus .file-cta,.file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,221,87,0.25);color:rgba(0,0,0,0.7)}.file.is-warning:active .file-cta,.file.is-warning.is-active .file-cta{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-danger .file-cta{background-color:#da0b00;border-color:transparent;color:#fff}.file.is-danger:hover .file-cta,.file.is-danger.is-hovered .file-cta{background-color:#cd0a00;border-color:transparent;color:#fff}.file.is-danger:focus .file-cta,.file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(218,11,0,0.25);color:#fff}.file.is-danger:active .file-cta,.file.is-danger.is-active .file-cta{background-color:#c10a00;border-color:transparent;color:#fff}.file.is-small,#documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa,#documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#222}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#222}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#222}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#222;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:0.5em}.label.is-small,#documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:0.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark,.content kbd.help{color:#363636}.help.is-primary,.docstring>section>a.help.docs-sourcelink{color:#4eb5de}.help.is-link{color:#2e63b8}.help.is-info{color:#209cee}.help.is-success{color:#22c35b}.help.is-warning{color:#ffdd57}.help.is-danger{color:#da0b00}.field:not(:last-child){margin-bottom:0.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .button.is-hovered:not([disabled]),.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,.field.has-addons .control .input.is-hovered:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),.field.has-addons .control .select select:not([disabled]):hover,.field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .button.is-focused:not([disabled]),.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button.is-active:not([disabled]),.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,.field.has-addons .control .input.is-focused:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,.field.has-addons .control .input.is-active:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),.field.has-addons .control .select select:not([disabled]):focus,.field.has-addons .control .select select.is-focused:not([disabled]),.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select.is-active:not([disabled]){z-index:3}.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .button.is-focused:not([disabled]):hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button.is-active:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,.field.has-addons .control .input.is-focused:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,.field.has-addons .control .input.is-active:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):focus:hover,.field.has-addons .control .select select.is-focused:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width: 768px){.field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small,#documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}.field-label.is-normal{padding-top:0.375em}.field-label.is-medium{font-size:1.25rem;padding-top:0.375em}.field-label.is-large{font-size:1.5rem;padding-top:0.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#222}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}.control.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#2e63b8;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#222;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ul,.breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small,#documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:#bbb;color:#222;max-width:100%;position:relative}.card-footer:first-child,.card-content:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-footer:last-child,.card-content:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}.card-header-title{align-items:center;color:#222;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:rgba(0,0,0,0);padding:1.5rem}.card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:#bbb;padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#222;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#2e63b8;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .title,.level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,0.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,0.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small,#documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#222;display:block;padding:0.5em 0.75em}.menu-list a:hover{background-color:#f5f5f5;color:#222}.menu-list a.is-active{background-color:#2e63b8;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#6b6b6b;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small,#documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark,.content kbd.message{background-color:#fafafa}.message.is-dark .message-header,.content kbd.message .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body,.content kbd.message .message-body{border-color:#363636}.message.is-primary,.docstring>section>a.message.docs-sourcelink{background-color:#eef8fc}.message.is-primary .message-header,.docstring>section>a.message.docs-sourcelink .message-header{background-color:#4eb5de;color:#fff}.message.is-primary .message-body,.docstring>section>a.message.docs-sourcelink .message-body{border-color:#4eb5de;color:#1a6d8e}.message.is-link{background-color:#eff3fb}.message.is-link .message-header{background-color:#2e63b8;color:#fff}.message.is-link .message-body{border-color:#2e63b8;color:#3169c4}.message.is-info{background-color:#ecf7fe}.message.is-info .message-header{background-color:#209cee;color:#fff}.message.is-info .message-body{border-color:#209cee;color:#0e72b4}.message.is-success{background-color:#eefcf3}.message.is-success .message-header{background-color:#22c35b;color:#fff}.message.is-success .message-body{border-color:#22c35b;color:#198f43}.message.is-warning{background-color:#fffbeb}.message.is-warning .message-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.message.is-warning .message-body{border-color:#ffdd57;color:#947600}.message.is-danger{background-color:#ffeceb}.message.is-danger .message-header{background-color:#da0b00;color:#fff}.message.is-danger .message-body{border-color:#da0b00;color:#f50c00}.message-header{align-items:center;background-color:#222;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#222;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:rgba(0,0,0,0)}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,0.86)}.modal-content,.modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){.modal-content,.modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-head,.modal-card-foot{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#222;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand>.navbar-item,.navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){.navbar.is-white .navbar-start>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-start .navbar-link::after,.navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand>.navbar-item,.navbar.is-black .navbar-brand .navbar-link{color:#fff}.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-black .navbar-start>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-end .navbar-link{color:#fff}.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-start .navbar-link::after,.navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>.navbar-item,.navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-light .navbar-start>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start .navbar-link::after,.navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}.navbar.is-dark,.content kbd.navbar{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand>.navbar-item,.content kbd.navbar .navbar-brand>.navbar-item,.navbar.is-dark .navbar-brand .navbar-link,.content kbd.navbar .navbar-brand .navbar-link{color:#fff}.navbar.is-dark .navbar-brand>a.navbar-item:focus,.content kbd.navbar .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover,.content kbd.navbar .navbar-brand>a.navbar-item:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.content kbd.navbar .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.content kbd.navbar .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.content kbd.navbar .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand .navbar-link.is-active,.content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after,.content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger,.content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-dark .navbar-start>.navbar-item,.content kbd.navbar .navbar-start>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.content kbd.navbar .navbar-start .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.content kbd.navbar .navbar-end>.navbar-item,.navbar.is-dark .navbar-end .navbar-link,.content kbd.navbar .navbar-end .navbar-link{color:#fff}.navbar.is-dark .navbar-start>a.navbar-item:focus,.content kbd.navbar .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover,.content kbd.navbar .navbar-start>a.navbar-item:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.content kbd.navbar .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.content kbd.navbar .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.content kbd.navbar .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.content kbd.navbar .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.content kbd.navbar .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.content kbd.navbar .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.content kbd.navbar .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.content kbd.navbar .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.content kbd.navbar .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end .navbar-link.is-active,.content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-start .navbar-link::after,.content kbd.navbar .navbar-start .navbar-link::after,.navbar.is-dark .navbar-end .navbar-link::after,.content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active,.content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary,.docstring>section>a.navbar.docs-sourcelink{background-color:#4eb5de;color:#fff}.navbar.is-primary .navbar-brand>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,.navbar.is-primary .navbar-brand .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}.navbar.is-primary .navbar-brand>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger,.docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-primary .navbar-start>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,.navbar.is-primary .navbar-end .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}.navbar.is-primary .navbar-start>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-start .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,.navbar.is-primary .navbar-end .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#4eb5de;color:#fff}}.navbar.is-link{background-color:#2e63b8;color:#fff}.navbar.is-link .navbar-brand>.navbar-item,.navbar.is-link .navbar-brand .navbar-link{color:#fff}.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-link .navbar-start>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-end .navbar-link{color:#fff}.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-start .navbar-link::after,.navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#2e63b8;color:#fff}}.navbar.is-info{background-color:#209cee;color:#fff}.navbar.is-info .navbar-brand>.navbar-item,.navbar.is-info .navbar-brand .navbar-link{color:#fff}.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-info .navbar-start>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-end .navbar-link{color:#fff}.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-start .navbar-link::after,.navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#209cee;color:#fff}}.navbar.is-success{background-color:#22c35b;color:#fff}.navbar.is-success .navbar-brand>.navbar-item,.navbar.is-success .navbar-brand .navbar-link{color:#fff}.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-success .navbar-start>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-end .navbar-link{color:#fff}.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-start .navbar-link::after,.navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#22c35b;color:#fff}}.navbar.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>.navbar-item,.navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-warning .navbar-start>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start .navbar-link::after,.navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffdd57;color:rgba(0,0,0,0.7)}}.navbar.is-danger{background-color:#da0b00;color:#fff}.navbar.is-danger .navbar-brand>.navbar-item,.navbar.is-danger .navbar-brand .navbar-link{color:#fff}.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-danger .navbar-start>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-end .navbar-link{color:#fff}.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-start .navbar-link::after,.navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#da0b00;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top,body.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom,body.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#222;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,0.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#222;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}a.navbar-item,.navbar-link{cursor:pointer}a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover,a.navbar-item.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,.navbar-link.is-active{background-color:#fafafa;color:#2e63b8}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(0.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8}.navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8;border-bottom-style:solid;border-bottom-width:3px;color:#2e63b8;padding-bottom:calc(0.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#2e63b8;margin-top:-0.375em;right:1.125em}.navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch,body.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch,body.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width: 1056px){.navbar,.navbar-menu,.navbar-start,.navbar-end{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-start,.navbar.is-spaced .navbar-end{align-items:center}.navbar.is-spaced a.navbar-item,.navbar.is-spaced .navbar-link{border-radius:4px}.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar.is-spaced .navbar-dropdown,.navbar-dropdown.is-boxed{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.navbar>.container .navbar-brand,.container>.navbar .navbar-brand{margin-left:-.75rem}.navbar>.container .navbar-menu,.container>.navbar .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop,body.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop,body.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}html.has-spaced-navbar-fixed-top,body.has-spaced-navbar-fixed-top{padding-top:5.25rem}html.has-spaced-navbar-fixed-bottom,body.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}a.navbar-item.is-active,.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:focus):not(:hover),.navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link,.navbar-item.has-dropdown.is-active .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small,#documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-previous,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,.pagination.is-rounded .pagination-next,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-previous,.pagination-next,.pagination-link{border-color:#dbdbdb;color:#222;min-width:2.5em}.pagination-previous:hover,.pagination-next:hover,.pagination-link:hover{border-color:#b5b5b5;color:#363636}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus{border-color:#3c5dcd}.pagination-previous:active,.pagination-next:active,.pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}.pagination-previous[disabled],.pagination-previous.is-disabled,.pagination-next[disabled],.pagination-next.is-disabled,.pagination-link[disabled],.pagination-link.is-disabled{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#6b6b6b;opacity:0.5}.pagination-previous,.pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width: 768px){.pagination{flex-wrap:wrap}.pagination-previous,.pagination-next{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:#bbb;font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading,.content kbd.panel .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active,.content kbd.panel .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon,.content kbd.panel .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading,.docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#4eb5de;color:#fff}.panel.is-primary .panel-tabs a.is-active,.docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#4eb5de}.panel.is-primary .panel-block.is-active .panel-icon,.docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#4eb5de}.panel.is-link .panel-heading{background-color:#2e63b8;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#2e63b8}.panel.is-link .panel-block.is-active .panel-icon{color:#2e63b8}.panel.is-info .panel-heading{background-color:#209cee;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#209cee}.panel.is-info .panel-block.is-active .panel-icon{color:#209cee}.panel.is-success .panel-heading{background-color:#22c35b;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#22c35b}.panel.is-success .panel-block.is-active .panel-icon{color:#22c35b}.panel.is-warning .panel-heading{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ffdd57}.panel.is-warning .panel-block.is-active .panel-icon{color:#ffdd57}.panel.is-danger .panel-heading{background-color:#da0b00;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#da0b00}.panel.is-danger .panel-block.is-active .panel-icon{color:#da0b00}.panel-tabs:not(:last-child),.panel-block:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#222;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:0.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#222}.panel-list a:hover{color:#2e63b8}.panel-block{align-items:center;color:#222;display:flex;justify-content:flex-start;padding:0.5em 0.75em}.panel-block input[type="checkbox"]{margin-right:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#2e63b8;color:#363636}.panel-block.is-active .panel-icon{color:#2e63b8}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#6b6b6b;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#222;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#222;color:#222}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#2e63b8;color:#2e63b8}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:0.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:rgba(0,0,0,0) !important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li:last-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li.is-active a{background-color:#2e63b8;border-color:#2e63b8;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-small,#documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0%}.columns.is-mobile>.column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>.column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>.column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>.column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>.column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0%}.column.is-1-mobile{flex:none;width:8.33333337%}.column.is-offset-1-mobile{margin-left:8.33333337%}.column.is-2-mobile{flex:none;width:16.66666674%}.column.is-offset-2-mobile{margin-left:16.66666674%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.33333337%}.column.is-offset-4-mobile{margin-left:33.33333337%}.column.is-5-mobile{flex:none;width:41.66666674%}.column.is-offset-5-mobile{margin-left:41.66666674%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.33333337%}.column.is-offset-7-mobile{margin-left:58.33333337%}.column.is-8-mobile{flex:none;width:66.66666674%}.column.is-offset-8-mobile{margin-left:66.66666674%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.33333337%}.column.is-offset-10-mobile{margin-left:83.33333337%}.column.is-11-mobile{flex:none;width:91.66666674%}.column.is-offset-11-mobile{margin-left:91.66666674%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0%}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333337%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333337%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66666674%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66666674%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333337%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333337%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66666674%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66666674%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333337%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333337%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66666674%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66666674%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333337%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333337%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66666674%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66666674%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0%}.column.is-1-touch{flex:none;width:8.33333337%}.column.is-offset-1-touch{margin-left:8.33333337%}.column.is-2-touch{flex:none;width:16.66666674%}.column.is-offset-2-touch{margin-left:16.66666674%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.33333337%}.column.is-offset-4-touch{margin-left:33.33333337%}.column.is-5-touch{flex:none;width:41.66666674%}.column.is-offset-5-touch{margin-left:41.66666674%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.33333337%}.column.is-offset-7-touch{margin-left:58.33333337%}.column.is-8-touch{flex:none;width:66.66666674%}.column.is-offset-8-touch{margin-left:66.66666674%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.33333337%}.column.is-offset-10-touch{margin-left:83.33333337%}.column.is-11-touch{flex:none;width:91.66666674%}.column.is-offset-11-touch{margin-left:91.66666674%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0%}.column.is-1-desktop{flex:none;width:8.33333337%}.column.is-offset-1-desktop{margin-left:8.33333337%}.column.is-2-desktop{flex:none;width:16.66666674%}.column.is-offset-2-desktop{margin-left:16.66666674%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.33333337%}.column.is-offset-4-desktop{margin-left:33.33333337%}.column.is-5-desktop{flex:none;width:41.66666674%}.column.is-offset-5-desktop{margin-left:41.66666674%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.33333337%}.column.is-offset-7-desktop{margin-left:58.33333337%}.column.is-8-desktop{flex:none;width:66.66666674%}.column.is-offset-8-desktop{margin-left:66.66666674%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.33333337%}.column.is-offset-10-desktop{margin-left:83.33333337%}.column.is-11-desktop{flex:none;width:91.66666674%}.column.is-offset-11-desktop{margin-left:91.66666674%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0%}.column.is-1-widescreen{flex:none;width:8.33333337%}.column.is-offset-1-widescreen{margin-left:8.33333337%}.column.is-2-widescreen{flex:none;width:16.66666674%}.column.is-offset-2-widescreen{margin-left:16.66666674%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.33333337%}.column.is-offset-4-widescreen{margin-left:33.33333337%}.column.is-5-widescreen{flex:none;width:41.66666674%}.column.is-offset-5-widescreen{margin-left:41.66666674%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.33333337%}.column.is-offset-7-widescreen{margin-left:58.33333337%}.column.is-8-widescreen{flex:none;width:66.66666674%}.column.is-offset-8-widescreen{margin-left:66.66666674%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.33333337%}.column.is-offset-10-widescreen{margin-left:83.33333337%}.column.is-11-widescreen{flex:none;width:91.66666674%}.column.is-offset-11-widescreen{margin-left:91.66666674%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0%}.column.is-1-fullhd{flex:none;width:8.33333337%}.column.is-offset-1-fullhd{margin-left:8.33333337%}.column.is-2-fullhd{flex:none;width:16.66666674%}.column.is-offset-2-fullhd{margin-left:16.66666674%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.33333337%}.column.is-offset-4-fullhd{margin-left:33.33333337%}.column.is-5-fullhd{flex:none;width:41.66666674%}.column.is-offset-5-fullhd{margin-left:41.66666674%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.33333337%}.column.is-offset-7-fullhd{margin-left:58.33333337%}.column.is-8-fullhd{flex:none;width:66.66666674%}.column.is-offset-8-fullhd{margin-left:66.66666674%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.33333337%}.column.is-offset-10-fullhd{margin-left:83.33333337%}.column.is-11-fullhd{flex:none;width:91.66666674%}.column.is-offset-11-fullhd{margin-left:91.66666674%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0 !important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){.columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-0-fullhd{--columnGap: 0rem}}.columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){.columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-1-fullhd{--columnGap: .25rem}}.columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){.columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-2-fullhd{--columnGap: .5rem}}.columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){.columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-3-fullhd{--columnGap: .75rem}}.columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){.columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-4-fullhd{--columnGap: 1rem}}.columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){.columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}.columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){.columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}.columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){.columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}.columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){.columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-8-fullhd{--columnGap: 2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0 !important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333337%}.tile.is-2{flex:none;width:16.66666674%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333337%}.tile.is-5{flex:none;width:41.66666674%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333337%}.tile.is-8{flex:none;width:66.66666674%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333337%}.tile.is-11{flex:none;width:91.66666674%}.tile.is-12{flex:none;width:100%}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:none}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,0.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}.hero.is-white a.navbar-item:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white .navbar-link:hover,.hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,0.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-black a.navbar-item:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black .navbar-link:hover,.hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:0.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,0.7)}.hero.is-light .subtitle{color:rgba(0,0,0,0.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-light a.navbar-item:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light .navbar-link:hover,.hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}.hero.is-dark,.content kbd.hero{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong,.content kbd.hero strong{color:inherit}.hero.is-dark .title,.content kbd.hero .title{color:#fff}.hero.is-dark .subtitle,.content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}.hero.is-dark .subtitle a:not(.button),.content kbd.hero .subtitle a:not(.button),.hero.is-dark .subtitle strong,.content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-dark .navbar-menu,.content kbd.hero .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.content kbd.hero .navbar-item,.hero.is-dark .navbar-link,.content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-dark a.navbar-item:hover,.content kbd.hero a.navbar-item:hover,.hero.is-dark a.navbar-item.is-active,.content kbd.hero a.navbar-item.is-active,.hero.is-dark .navbar-link:hover,.content kbd.hero .navbar-link:hover,.hero.is-dark .navbar-link.is-active,.content kbd.hero .navbar-link.is-active{background-color:#292929;color:#fff}.hero.is-dark .tabs a,.content kbd.hero .tabs a{color:#fff;opacity:0.9}.hero.is-dark .tabs a:hover,.content kbd.hero .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a,.content kbd.hero .tabs li.is-active a{color:#363636 !important;opacity:1}.hero.is-dark .tabs.is-boxed a,.content kbd.hero .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a,.content kbd.hero .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.content kbd.hero .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover,.content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.content kbd.hero .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.content kbd.hero .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold,.content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}@media screen and (max-width: 768px){.hero.is-dark.is-bold .navbar-menu,.content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}}.hero.is-primary,.docstring>section>a.hero.docs-sourcelink{background-color:#4eb5de;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong,.docstring>section>a.hero.docs-sourcelink strong{color:inherit}.hero.is-primary .title,.docstring>section>a.hero.docs-sourcelink .title{color:#fff}.hero.is-primary .subtitle,.docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}.hero.is-primary .subtitle a:not(.button),.docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),.hero.is-primary .subtitle strong,.docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-primary .navbar-menu,.docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#4eb5de}}.hero.is-primary .navbar-item,.docstring>section>a.hero.docs-sourcelink .navbar-item,.hero.is-primary .navbar-link,.docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-primary a.navbar-item:hover,.docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,.hero.is-primary a.navbar-item.is-active,.docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,.hero.is-primary .navbar-link:hover,.docstring>section>a.hero.docs-sourcelink .navbar-link:hover,.hero.is-primary .navbar-link.is-active,.docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#39acda;color:#fff}.hero.is-primary .tabs a,.docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}.hero.is-primary .tabs a:hover,.docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#4eb5de !important;opacity:1}.hero.is-primary .tabs.is-boxed a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#4eb5de}.hero.is-primary.is-bold,.docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}@media screen and (max-width: 768px){.hero.is-primary.is-bold .navbar-menu,.docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}}.hero.is-link{background-color:#2e63b8;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,0.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-link .navbar-menu{background-color:#2e63b8}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-link a.navbar-item:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link .navbar-link:hover,.hero.is-link .navbar-link.is-active{background-color:#2958a4;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:0.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#2e63b8 !important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#2e63b8}.hero.is-link.is-bold{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}@media screen and (max-width: 768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}}.hero.is-info{background-color:#209cee;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,0.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-info .navbar-menu{background-color:#209cee}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-info a.navbar-item:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info .navbar-link:hover,.hero.is-info .navbar-link.is-active{background-color:#1190e3;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#209cee !important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#209cee}.hero.is-info.is-bold{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}@media screen and (max-width: 768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}}.hero.is-success{background-color:#22c35b;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,0.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-success .navbar-menu{background-color:#22c35b}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-success a.navbar-item:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success .navbar-link:hover,.hero.is-success .navbar-link.is-active{background-color:#1ead51;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#22c35b !important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#22c35b}.hero.is-success.is-bold{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}@media screen and (max-width: 768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}}.hero.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,0.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-warning .navbar-menu{background-color:#ffdd57}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-warning a.navbar-item:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#ffdd57 !important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ffdd57}.hero.is-warning.is-bold{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}@media screen and (max-width: 768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}}.hero.is-danger{background-color:#da0b00;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-danger .navbar-menu{background-color:#da0b00}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-danger a.navbar-item:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger .navbar-link.is-active{background-color:#c10a00;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#da0b00 !important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#da0b00}.hero.is-danger.is-bold{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}@media screen and (max-width: 768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}}.hero.is-small .hero-body,#documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-halfheight .hero-body,.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}.hero.is-halfheight .hero-body>.container,.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}.hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-head,.hero-foot{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem}h1 .docs-heading-anchor,h1 .docs-heading-anchor:hover,h1 .docs-heading-anchor:visited,h2 .docs-heading-anchor,h2 .docs-heading-anchor:hover,h2 .docs-heading-anchor:visited,h3 .docs-heading-anchor,h3 .docs-heading-anchor:hover,h3 .docs-heading-anchor:visited,h4 .docs-heading-anchor,h4 .docs-heading-anchor:hover,h4 .docs-heading-anchor:visited,h5 .docs-heading-anchor,h5 .docs-heading-anchor:hover,h5 .docs-heading-anchor:visited,h6 .docs-heading-anchor,h6 .docs-heading-anchor:hover,h6 .docs-heading-anchor:visited{color:#222}h1 .docs-heading-anchor-permalink,h2 .docs-heading-anchor-permalink,h3 .docs-heading-anchor-permalink,h4 .docs-heading-anchor-permalink,h5 .docs-heading-anchor-permalink,h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}h1 .docs-heading-anchor-permalink::before,h2 .docs-heading-anchor-permalink::before,h3 .docs-heading-anchor-permalink::before,h4 .docs-heading-anchor-permalink::before,h5 .docs-heading-anchor-permalink::before,h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}h1:hover .docs-heading-anchor-permalink,h2:hover .docs-heading-anchor-permalink,h3:hover .docs-heading-anchor-permalink,h4:hover .docs-heading-anchor-permalink,h5:hover .docs-heading-anchor-permalink,h6:hover .docs-heading-anchor-permalink{visibility:visible}.docs-dark-only{display:none !important}pre{position:relative;overflow:hidden}pre code,pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}pre code:first-of-type,pre code.hljs:first-of-type{padding-top:0.5rem !important}pre code:last-of-type,pre code.hljs:last-of-type{padding-bottom:0.5rem !important}pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#222;cursor:pointer;text-align:center}pre .copy-button:focus,pre .copy-button:hover{opacity:1;background:rgba(34,34,34,0.1);color:#2e63b8}pre .copy-button.success{color:#259a12;opacity:1}pre .copy-button.error{color:#cb3c33;opacity:1}pre:hover .copy-button{opacity:1}.admonition{background-color:#b5b5b5;border-style:solid;border-width:1px;border-color:#363636;border-radius:4px;font-size:1rem}.admonition strong{color:currentColor}.admonition.is-small,#documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}.admonition.is-medium{font-size:1.25rem}.admonition.is-large{font-size:1.5rem}.admonition.is-default{background-color:#b5b5b5;border-color:#363636}.admonition.is-default>.admonition-header{background-color:#363636;color:#fff}.admonition.is-default>.admonition-body{color:#fff}.admonition.is-info{background-color:#def0fc;border-color:#209cee}.admonition.is-info>.admonition-header{background-color:#209cee;color:#fff}.admonition.is-info>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-success{background-color:#bdf4d1;border-color:#22c35b}.admonition.is-success>.admonition-header{background-color:#22c35b;color:#fff}.admonition.is-success>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-warning{background-color:#fff3c5;border-color:#ffdd57}.admonition.is-warning>.admonition-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.admonition.is-warning>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-danger{background-color:#ffaba7;border-color:#da0b00}.admonition.is-danger>.admonition-header{background-color:#da0b00;color:#fff}.admonition.is-danger>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-compat{background-color:#bdeff5;border-color:#1db5c9}.admonition.is-compat>.admonition-header{background-color:#1db5c9;color:#fff}.admonition.is-compat>.admonition-body{color:rgba(0,0,0,0.7)}.admonition-header{color:#fff;background-color:#363636;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}details.admonition.is-details>.admonition-header{list-style:none}details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}.admonition-body{color:#222;padding:0.5rem .75rem}.admonition-body pre{background-color:#f5f5f5}.admonition-body code{background-color:rgba(0,0,0,0.05)}.docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #dbdbdb;box-shadow:2px 2px 3px rgba(10,10,10,0.1);max-width:100%}.docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#f5f5f5;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #dbdbdb;overflow:auto}.docstring>header code{background-color:transparent}.docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}.docstring>header .docstring-binding{margin-right:0.3em}.docstring>header .docstring-category{margin-left:0.3em}.docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #dbdbdb}.docstring>section:last-child{border-bottom:none}.docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}.docstring>section>a.docs-sourcelink:focus{opacity:1 !important}.docstring:hover>section>a.docs-sourcelink{opacity:0.2}.docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}.docstring>section:hover a.docs-sourcelink{opacity:1}.documenter-example-output{background-color:#fff}.outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#ffaba7;color:rgba(0,0,0,0.7);border-bottom:3px solid #da0b00;padding:10px 35px;text-align:center;font-size:15px}.outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}.outdated-warning-overlay a{color:#2e63b8}.outdated-warning-overlay a:hover{color:#363636}.content pre{border:1px solid #dbdbdb}.content code{font-weight:inherit}.content a code{color:#2e63b8}.content h1 code,.content h2 code,.content h3 code,.content h4 code,.content h5 code,.content h6 code{color:#222}.content table{display:block;width:initial;max-width:100%;overflow-x:auto}.content blockquote>ul:first-child,.content blockquote>ol:first-child,.content .admonition-body>ul:first-child,.content .admonition-body>ol:first-child{margin-top:0}pre,code{font-variant-ligatures:no-contextual}.breadcrumb a.is-disabled{cursor:default;pointer-events:none}.breadcrumb a.is-disabled,.breadcrumb a.is-disabled:hover{color:#222}.hljs{background:initial !important}.katex .katex-mathml{top:0;right:0}.katex-display,mjx-container,.MathJax_Display{margin:0.5em 0 !important}html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}li.no-marker{list-style:none}#documenter .docs-main>article{overflow-wrap:break-word}#documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){#documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){#documenter .docs-main{width:100%}#documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}#documenter .docs-main>header,#documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}#documenter .docs-main header.docs-navbar{background-color:#fff;border-bottom:1px solid #dbdbdb;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}#documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}#documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}#documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}#documenter .docs-main header.docs-navbar .docs-right .docs-icon,#documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}#documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}#documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}#documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #bbb;transition-duration:0.7s;-webkit-transition-duration:0.7s}#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}#documenter .docs-main section.footnotes{border-top:1px solid #dbdbdb}#documenter .docs-main section.footnotes li .tag:first-child,#documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,#documenter .docs-main section.footnotes li .content kbd:first-child,.content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}#documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #dbdbdb;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){#documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}#documenter .docs-main .docs-footer .docs-footer-nextpage,#documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}#documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}#documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}#documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}#documenter .docs-sidebar{display:flex;flex-direction:column;color:#0a0a0a;background-color:#f5f5f5;border-right:1px solid #dbdbdb;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}#documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #bbb}@media screen and (min-width: 1056px){#documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){#documenter .docs-sidebar{left:0;top:0}}#documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}#documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}#documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}#documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}#documenter .docs-sidebar .docs-package-name a,#documenter .docs-sidebar .docs-package-name a:hover{color:#0a0a0a}#documenter .docs-sidebar .docs-version-selector{border-top:1px solid #dbdbdb;display:none;padding:0.5rem}#documenter .docs-sidebar .docs-version-selector.visible{display:flex}#documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #dbdbdb;padding-bottom:1.5rem}#documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}#documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}#documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}#documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}#documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}#documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}#documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}#documenter .docs-sidebar ul.docs-menu .tocitem,#documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#0a0a0a;background:#f5f5f5}#documenter .docs-sidebar ul.docs-menu a.tocitem:hover,#documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#0a0a0a;background-color:#ebebeb}#documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #dbdbdb;border-bottom:1px solid #dbdbdb;background-color:#fff}#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#fff;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#ebebeb;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}#documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}#documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}#documenter .docs-sidebar form.docs-search>input{width:14.4rem}#documenter .docs-sidebar #documenter-search-query{color:#707070;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){#documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#ccc}}@media screen and (max-width: 1055px){#documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#ccc}}kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(0,0,0,0.6);box-shadow:0 2px 0 1px rgba(0,0,0,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}.search-min-width-50{min-width:50%}.search-min-height-100{min-height:100%}.search-modal-card-body{max-height:calc(100vh - 15rem)}.search-result-link{border-radius:0.7em;transition:all 300ms}.search-result-link:hover,.search-result-link:focus{background-color:rgba(0,128,128,0.1)}.search-result-link .property-search-result-badge,.search-result-link .search-filter{transition:all 300ms}.property-search-result-badge,.search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}.search-result-link:hover .property-search-result-badge,.search-result-link:hover .search-filter,.search-result-link:focus .property-search-result-badge,.search-result-link:focus .search-filter{color:#f1f5f9;background-color:#333}.search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}.search-filter:hover,.search-filter:focus{color:#333}.search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}.search-filter-selected:hover,.search-filter-selected:focus{color:#f5f5f5}.search-result-highlight{background-color:#ffdd57;color:black}.search-divider{border-bottom:1px solid #dbdbdb}.search-result-title{width:85%;color:#333}.search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}#search-modal .modal-card-body::-webkit-scrollbar,#search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}#search-modal .modal-card-body::-webkit-scrollbar-thumb,#search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}#search-modal .modal-card-body::-webkit-scrollbar-track,#search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}.w-100{width:100%}.gap-2{gap:0.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.ansi span.sgr1{font-weight:bolder}.ansi span.sgr2{font-weight:lighter}.ansi span.sgr3{font-style:italic}.ansi span.sgr4{text-decoration:underline}.ansi span.sgr7{color:#fff;background-color:#222}.ansi span.sgr8{color:transparent}.ansi span.sgr8 span{color:transparent}.ansi span.sgr9{text-decoration:line-through}.ansi span.sgr30{color:#242424}.ansi span.sgr31{color:#a7201f}.ansi span.sgr32{color:#066f00}.ansi span.sgr33{color:#856b00}.ansi span.sgr34{color:#2149b0}.ansi span.sgr35{color:#7d4498}.ansi span.sgr36{color:#007989}.ansi span.sgr37{color:gray}.ansi span.sgr40{background-color:#242424}.ansi span.sgr41{background-color:#a7201f}.ansi span.sgr42{background-color:#066f00}.ansi span.sgr43{background-color:#856b00}.ansi span.sgr44{background-color:#2149b0}.ansi span.sgr45{background-color:#7d4498}.ansi span.sgr46{background-color:#007989}.ansi span.sgr47{background-color:gray}.ansi span.sgr90{color:#616161}.ansi span.sgr91{color:#cb3c33}.ansi span.sgr92{color:#0e8300}.ansi span.sgr93{color:#a98800}.ansi span.sgr94{color:#3c5dcd}.ansi span.sgr95{color:#9256af}.ansi span.sgr96{color:#008fa3}.ansi span.sgr97{color:#f5f5f5}.ansi span.sgr100{background-color:#616161}.ansi span.sgr101{background-color:#cb3c33}.ansi span.sgr102{background-color:#0e8300}.ansi span.sgr103{background-color:#a98800}.ansi span.sgr104{background-color:#3c5dcd}.ansi span.sgr105{background-color:#9256af}.ansi span.sgr106{background-color:#008fa3}.ansi span.sgr107{background-color:#f5f5f5}code.language-julia-repl>span.hljs-meta{color:#066f00;font-weight:bolder}/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#F3F3F3;color:#444}.hljs-comment{color:#697070}.hljs-tag,.hljs-punctuation{color:#444a}.hljs-tag .hljs-name,.hljs-tag .hljs-attr{color:#444}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta .hljs-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-operator,.hljs-selector-pseudo{color:#ab5656}.hljs-literal{color:#695}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}.gap-4{gap:1rem} diff --git a/previews/PR2418/assets/themeswap.js b/previews/PR2418/assets/themeswap.js new file mode 100644 index 0000000000..9f5eebe6aa --- /dev/null +++ b/previews/PR2418/assets/themeswap.js @@ -0,0 +1,84 @@ +// Small function to quickly swap out themes. Gets put into the tag.. +function set_theme_from_local_storage() { + // Initialize the theme to null, which means default + var theme = null; + // If the browser supports the localstorage and is not disabled then try to get the + // documenter theme + if (window.localStorage != null) { + // Get the user-picked theme from localStorage. May be `null`, which means the default + // theme. + theme = window.localStorage.getItem("documenter-theme"); + } + // Check if the users preference is for dark color scheme + var darkPreference = + window.matchMedia("(prefers-color-scheme: dark)").matches === true; + // Initialize a few variables for the loop: + // + // - active: will contain the index of the theme that should be active. Note that there + // is no guarantee that localStorage contains sane values. If `active` stays `null` + // we either could not find the theme or it is the default (primary) theme anyway. + // Either way, we then need to stick to the primary theme. + // + // - disabled: style sheets that should be disabled (i.e. all the theme style sheets + // that are not the currently active theme) + var active = null; + var disabled = []; + var primaryLightTheme = null; + var primaryDarkTheme = null; + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // To distinguish the default (primary) theme, it needs to have the data-theme-primary + // attribute set. + if (ss.ownerNode.getAttribute("data-theme-primary") !== null) { + primaryLightTheme = themename; + } + // Check if the theme is primary dark theme so that we could store its name in darkTheme + if (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null) { + primaryDarkTheme = themename; + } + // If we find a matching theme (and it's not the default), we'll set active to non-null + if (themename === theme) active = i; + // Store the style sheets of inactive themes so that we could disable them + if (themename !== theme) disabled.push(ss); + } + var activeTheme = null; + if (active !== null) { + // If we did find an active theme, we'll (1) add the theme--$(theme) class to + document.getElementsByTagName("html")[0].className = "theme--" + theme; + activeTheme = theme; + } else { + // If we did _not_ find an active theme, then we need to fall back to the primary theme + // which can either be dark or light, depending on the user's OS preference. + var activeTheme = darkPreference ? primaryDarkTheme : primaryLightTheme; + // In case it somehow happens that the relevant primary theme was not found in the + // preceding loop, we abort without doing anything. + if (activeTheme === null) { + console.error("Unable to determine primary theme."); + return; + } + // When switching to the primary light theme, then we must not have a class name + // for the tag. That's only for non-primary or the primary dark theme. + if (darkPreference) { + document.getElementsByTagName("html")[0].className = + "theme--" + activeTheme; + } else { + document.getElementsByTagName("html")[0].className = ""; + } + } + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // we'll disable all the stylesheets, except for the active one + ss.disabled = !(themename == activeTheme); + } +} +set_theme_from_local_storage(); diff --git a/previews/PR2418/assets/warner.js b/previews/PR2418/assets/warner.js new file mode 100644 index 0000000000..3f6f5d0083 --- /dev/null +++ b/previews/PR2418/assets/warner.js @@ -0,0 +1,52 @@ +function maybeAddWarning() { + // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE + // in siteinfo.js. + // If either of these are undefined something went horribly wrong, so we abort. + if ( + window.DOCUMENTER_NEWEST === undefined || + window.DOCUMENTER_CURRENT_VERSION === undefined || + window.DOCUMENTER_STABLE === undefined + ) { + return; + } + + // Current version is not a version number, so we can't tell if it's the newest version. Abort. + if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { + return; + } + + // Current version is newest version, so no need to add a warning. + if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { + return; + } + + // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. + if (document.body.querySelector('meta[name="robots"]') === null) { + const meta = document.createElement("meta"); + meta.name = "robots"; + meta.content = "noindex"; + + document.getElementsByTagName("head")[0].appendChild(meta); + } + + const div = document.createElement("div"); + div.classList.add("outdated-warning-overlay"); + const closer = document.createElement("button"); + closer.classList.add("outdated-warning-closer", "delete"); + closer.addEventListener("click", function () { + document.body.removeChild(div); + }); + const href = window.documenterBaseURL + "/../" + window.DOCUMENTER_STABLE; + div.innerHTML = + 'This documentation is not for the latest stable release, but for either the development version or an older release.
Click here to go to the documentation for the latest stable release.'; + div.appendChild(closer); + document.body.appendChild(div); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", maybeAddWarning); +} else { + maybeAddWarning(); +} diff --git a/previews/PR2418/background/duality/index.html b/previews/PR2418/background/duality/index.html new file mode 100644 index 0000000000..dc2ec43f02 --- /dev/null +++ b/previews/PR2418/background/duality/index.html @@ -0,0 +1,80 @@ + +Duality · MathOptInterface

Duality

Conic duality is the starting point for MOI's duality conventions. When all functions are affine (or coordinate projections), and all constraint sets are closed convex cones, the model may be called a conic optimization problem.

For a minimization problem in geometric conic form, the primal is:

\[\begin{align} +& \min_{x \in \mathbb{R}^n} & a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m +\end{align}\]

and the dual is a maximization problem in standard conic form:

\[\begin{align} +& \max_{y_1, \ldots, y_m} & -\sum_{i=1}^m b_i^T y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 - \sum_{i=1}^m A_i^T y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m +\end{align}\]

where each $\mathcal{C}_i$ is a closed convex cone and $\mathcal{C}_i^*$ is its dual cone.

For a maximization problem in geometric conic form, the primal is:

\[\begin{align} +& \max_{x \in \mathbb{R}^n} & a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m +\end{align}\]

and the dual is a minimization problem in standard conic form:

\[\begin{align} +& \min_{y_1, \ldots, y_m} & \sum_{i=1}^m b_i^T y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 + \sum_{i=1}^m A_i^T y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m +\end{align}\]

A linear inequality constraint $a^T x + b \ge c$ is equivalent to $a^T x + b - c \in \mathbb{R}_+$, and $a^T x + b \le c$ is equivalent to $a^T x + b - c \in \mathbb{R}_-$. Variable-wise constraints are affine constraints with the appropriate identity mapping in place of $A_i$.

For the special case of minimization LPs, the MOI primal form can be stated as:

\[\begin{align} +& \min_{x \in \mathbb{R}^n} & a_0^T x &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1 x & \ge b_1\\ +&& A_2 x & \le b_2\\ +&& A_3 x & = b_3 +\end{align}\]

By applying the stated transformations to conic form, taking the dual, and transforming back into linear inequality form, one obtains the following dual:

\[\begin{align} +& \max_{y_1,y_2,y_3} & b_1^Ty_1 + b_2^Ty_2 + b_3^Ty_3 &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 & = a_0\\ +&& y_1 &\ge 0\\ +&& y_2 &\le 0 +\end{align}\]

For maximization LPs, the MOI primal form can be stated as:

\[\begin{align} +& \max_{x \in \mathbb{R}^n} & a_0^T x &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1 x & \ge b_1\\ +&& A_2 x & \le b_2\\ +&& A_3 x & = b_3 +\end{align}\]

and similarly, the dual is:

\[\begin{align} +& \min_{y_1,y_2,y_3} & -b_1^Ty_1 - b_2^Ty_2 - b_3^Ty_3 &+ b_0 +\\ +& \;\;\text{s.t.} +&A_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 & = -a_0\\ +&& y_1 &\ge 0\\ +&& y_2 &\le 0 +\end{align}\]

Warning

For the LP case, the signs of the feasible dual variables depend only on the sense of the corresponding primal inequality and not on the objective sense.

Duality and scalar product

The scalar product is different from the canonical one for the sets PositiveSemidefiniteConeTriangle, LogDetConeTriangle, RootDetConeTriangle.

If the set $C_i$ of the section Duality is one of these three cones, then the rows of the matrix $A_i$ corresponding to off-diagonal entries are twice the value of the coefficients field in the VectorAffineFunction for the corresponding rows. See PositiveSemidefiniteConeTriangle for details.

Dual for problems with quadratic functions

Quadratic Programs (QPs)

For quadratic programs with only affine conic constraints,

\[\begin{align*} +& \min_{x \in \mathbb{R}^n} & \frac{1}{2}x^TQ_0x + a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m. +\end{align*}\]

with cones $\mathcal{C}_i \subseteq \mathbb{R}^{m_i}$ for $i = 1, \ldots, m$, consider the Lagrangian function

\[L(x, y) = \frac{1}{2}x^TQ_0x + a_0^T x + b_0 - \sum_{i = 1}^m y_i^T (A_i x + b_i).\]

Let $z(y)$ denote $\sum_{i = 1}^m A_i^T y_i - a_0$, the Lagrangian can be rewritten as

\[L(x, y) = \frac{1}{2}{x}^TQ_0x - z(y)^T x + b_0 - \sum_{i = 1}^m y_i^T b_i.\]

The condition $\nabla_x L(x, y) = 0$ gives

\[0 = \nabla_x L(x, y) = Q_0x + a_0 - \sum_{i = 1}^m y_i^T b_i\]

which gives $Q_0x = z(y)$. This allows to obtain that

\[\min_{x \in \mathbb{R}^n} L(x, y) = -\frac{1}{2}x^TQ_0x + b_0 - \sum_{i = 1}^m y_i^T b_i\]

so the dual problem is

\[\max_{y_i \in \mathcal{C}_i^*} \min_{x \in \mathbb{R}^n} -\frac{1}{2}x^TQ_0x + b_0 - \sum_{i = 1}^m y_i^T b_i.\]

If $Q_0$ is invertible, we have $x = Q_0^{-1}z(y)$ hence

\[\min_{x \in \mathbb{R}^n} L(x, y) = -\frac{1}{2}z(y)^TQ_0^{-1}z(y) + b_0 - \sum_{i = 1}^m y_i^T b_i\]

so the dual problem is

\[\max_{y_i \in \mathcal{C}_i^*} -\frac{1}{2}z(y)^TQ_0^{-1}z(y) + b_0 - \sum_{i = 1}^m y_i^T b_i.\]

Quadratically Constrained Quadratic Programs (QCQPs)

Given a problem with both quadratic function and quadratic objectives:

\[\begin{align*} +& \min_{x \in \mathbb{R}^n} & \frac{1}{2}x^TQ_0x + a_0^T x + b_0 +\\ +& \;\;\text{s.t.} & \frac{1}{2}x^TQ_ix + a_i^T x + b_i & \in \mathcal{C}_i & i = 1 \ldots m. +\end{align*}\]

with cones $\mathcal{C}_i \subseteq \mathbb{R}$ for $i = 1 \ldots m$, consider the Lagrangian function

\[L(x, y) = \frac{1}{2}x^TQ_0x + a_0^T x + b_0 - \sum_{i = 1}^m y_i (\frac{1}{2}x^TQ_ix + a_i^T x + b_i)\]

A pair of primal-dual variables $(x^\star, y^\star)$ is optimal if

  • $x^\star$ is a minimizer of

    \[\min_{x \in \mathbb{R}^n} L(x, y^\star).\]

    That is,

    \[0 = \nabla_x L(x, y^\star) = Q_0x + a_0 - \sum_{i = 1}^m y_i^\star (Q_ix + a_i).\]

  • and $y^\star$ is a maximizer of

    \[\max_{y_i \in \mathcal{C}_i^*} L(x^\star, y).\]

    That is, for all $i = 1, \ldots, m$, $\frac{1}{2}x^TQ_ix + a_i^T x + b_i$ is either zero or in the normal cone of $\mathcal{C}_i^*$ at $y^\star$. For instance, if $\mathcal{C}_i$ is $\{ z \in \mathbb{R} : z \le 0 \}$, this means that if $\frac{1}{2}x^TQ_ix + a_i^T x + b_i$ is nonzero at $x^\star$ then $y_i^\star = 0$. This is the classical complementary slackness condition.

If $\mathcal{C}_i$ is a vector set, the discussion remains valid with $y_i(\frac{1}{2}x^TQ_ix + a_i^T x + b_i)$ replaced with the scalar product between $y_i$ and the vector of scalar-valued quadratic functions.

Dual for square semidefinite matrices

The set PositiveSemidefiniteConeTriangle is a self-dual. That is, querying ConstraintDual of a PositiveSemidefiniteConeTriangle constraint returns a vector that is itself a member of PositiveSemidefiniteConeTriangle.

However, the dual of PositiveSemidefiniteConeSquare is not so straight forward. This section explains the duality convention we use, and how it is derived.

Info

If you have a PositiveSemidefiniteConeSquare constraint, the result matrix $A$ from ConstraintDual is not positive semidefinite. However, $A + A^\top$ is positive semidefinite.

Let $\mathcal{S}_+$ be the cone of symmetric semidefinite matrices in the $\frac{n(n+1)}{2}$ dimensional space of symmetric $\mathbb{R}^{n \times n}$ matrices. That is, $\mathcal{S}_+$ is the set PositiveSemidefiniteConeTriangle. It is well known that $\mathcal{S}_+$ is a self-dual proper cone.

Let $\mathcal{P}_+$ be the cone of symmetric semidefinite matrices in the $n^2$ dimensional space of $\mathbb{R}^{n \times n}$ matrices. That is $\mathcal{P}_+$ is the set PositiveSemidefiniteConeSquare.

In addition, let $\mathcal{D}_+$ be the cone of matrices $A$ such that $A+A^\top \in \mathcal{P}_+$.

$\mathcal{P}_+$ is not proper because it is not solid (it is not $n^2$ dimensional), so it is not necessarily true that $\mathcal{P}_+^{**} = \mathcal{P}_+$.

However, this is the case, because we will show that $\mathcal{P}_+^{*} = \mathcal{D}_+$ and $\mathcal{D}_+^{*} = \mathcal{P}_+$.

First, let us see why $\mathcal{P}_+^{*} = \mathcal{D}_+$.

If $B$ is symmetric, then

\[\langle A,B \rangle = \langle A^\top, B^\top \rangle = \langle A^\top, B\rangle\]

so

\[2\langle A, B \rangle = \langle A, B \rangle + \langle A^\top, B \rangle = \langle A + A^\top , B \rangle.\]

Therefore, $\langle A,B\rangle \ge 0$ for all $B \in \mathcal{P}_+$ if and only if $\langle A+A^\top,B\rangle \ge 0$ for all $B \in \mathcal{P}_+$. Since $A+A^\top$ is symmetric, and we know that $\mathcal{S}_+$ is self-dual, we have shown that $\mathcal{P}_+^{*}$ is the set of matrices $A$ such that $A+A^\top \in \mathcal{P}_+$.

Second, let us see why $\mathcal{D}_+^{*} = \mathcal{P}_+$.

Since $A \in \mathcal{D}_+$ implies that $A^\top \in \mathcal{D}_+$, $B \in \mathcal{D}_+^{*}$ means that $\langle A+A^\top,B\rangle \ge 0$ for all $A \in \mathcal{D}_+$, and hence $B \in \\mathcal{P}_+$.

To see why it should be symmetric, simply notice that if $B_{i,j} < B_{j,i}$, then $\langle A,B\rangle$ can be made arbitrarily small by setting $A_{i,j} = A_{i,j} + s$ and $A_{j,i} = A_{j,i} - s$, with $s$ arbitrarily large, and $A$ stays in $\mathcal{D}_+$ because $A+A^\top$ does not change.

Typically, the primal/dual pair for semidefinite programs is presented as:

\[\begin{align} + \min & \langle C, X \rangle \\ +\text{s.t.} \;\; & \langle A_k, X\rangle = b_k \forall k \\ + & X \in \mathcal{S}_+ +\end{align}\]

with the dual

\[\begin{align} + \max & \sum_k b_k y_k \\ +\text{s.t.} \;\; & C - \sum A_k y_k \in \mathcal{S}_+ +\end{align}\]

If we allow $A_k$ to be non-symmetric, we should instead use:

\[\begin{align} + \min & \langle C, X \rangle \\ +\text{s.t.} \;\; & \langle A_k, X\rangle = b_k \forall k \\ + & X \in \mathcal{D}_+ +\end{align}\]

with the dual

\[\begin{align} + \max & \sum b_k y_k \\ +\text{s.t.} \;\; & C - \sum A_k y_k \in \mathcal{P}_+ +\end{align}\]

This is implemented as:

\[\begin{align} + \min & \langle C, Z \rangle + \langle C - C^\top, S \rangle \\ +\text{s.t.} \;\; & \langle A_k, Z \rangle + \langle A_k - A_k^\top, S \rangle = b_k \forall k \\ + & Z \in \mathcal{S}_+ +\end{align}\]

with the dual

\[\begin{align} + \max & \sum b_k y_k \\ +\text{s.t.} \;\; & C+C^\top - \sum (A_k+A_k^\top) y_k \in \mathcal{S}_+ \\ + & C-C^\top - \sum(A_k-A_k^\top) y_k = 0 +\end{align}\]

and we recover $Z = X + X^\top$.

diff --git a/previews/PR2418/background/infeasibility_certificates/index.html b/previews/PR2418/background/infeasibility_certificates/index.html new file mode 100644 index 0000000000..5e5b5f72a2 --- /dev/null +++ b/previews/PR2418/background/infeasibility_certificates/index.html @@ -0,0 +1,28 @@ + +Infeasibility certificates · MathOptInterface

Infeasibility certificates

When given a conic problem that is infeasible or unbounded, some solvers can produce a certificate of infeasibility. This page explains what a certificate of infeasibility is, and the related conventions that MathOptInterface adopts.

Conic duality

MathOptInterface uses conic duality to define infeasibility certificates. A full explanation is given in the section Duality, but here is a brief overview.

Minimization problems

For a minimization problem in geometric conic form, the primal is:

\[\begin{align} +& \min_{x \in \mathbb{R}^n} & a_0^\top x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m, +\end{align}\]

and the dual is a maximization problem in standard conic form:

\[\begin{align} +& \max_{y_1, \ldots, y_m} & -\sum_{i=1}^m b_i^\top y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 - \sum_{i=1}^m A_i^\top y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m, +\end{align}\]

where each $\mathcal{C}_i$ is a closed convex cone and $\mathcal{C}_i^*$ is its dual cone.

Maximization problems

For a maximization problem in geometric conic form, the primal is:

\[\begin{align} +& \max_{x \in \mathbb{R}^n} & a_0^\top x + b_0 +\\ +& \;\;\text{s.t.} & A_i x + b_i & \in \mathcal{C}_i & i = 1 \ldots m, +\end{align}\]

and the dual is a minimization problem in standard conic form:

\[\begin{align} +& \min_{y_1, \ldots, y_m} & \sum_{i=1}^m b_i^\top y_i + b_0 +\\ +& \;\;\text{s.t.} & a_0 + \sum_{i=1}^m A_i^\top y_i & = 0 +\\ +& & y_i & \in \mathcal{C}_i^* & i = 1 \ldots m. +\end{align}\]

Unbounded problems

A problem is unbounded if and only if:

  1. there exists a feasible primal solution
  2. the dual is infeasible.

A feasible primal solution—if one exists—can be obtained by setting ObjectiveSense to FEASIBILITY_SENSE before optimizing. Therefore, most solvers stop after they prove the dual is infeasible via a certificate of dual infeasibility, but before they have found a feasible primal solution. This is also the reason that MathOptInterface defines the DUAL_INFEASIBLE status instead of UNBOUNDED.

A certificate of dual infeasibility is an improving ray of the primal problem. That is, there exists some vector $d$ such that for all $\eta > 0$:

\[A_i (x + \eta d) + b_i \in \mathcal{C}_i,\ \ i = 1 \ldots m,\]

and (for minimization problems):

\[a_0^\top (x + \eta d) + b_0 < a_0^\top x + b_0,\]

for any feasible point $x$. The latter simplifies to $a_0^\top d < 0$. For maximization problems, the inequality is reversed, so that $a_0^\top d > 0$.

If the solver has found a certificate of dual infeasibility:

Note

The choice of whether to scale the ray $d$ to have magnitude 1 is left to the solver.

Infeasible problems

A certificate of primal infeasibility is an improving ray of the dual problem. However, because infeasibility is independent of the objective function, we first homogenize the primal problem by removing its objective.

For a minimization problem, a dual improving ray is some vector $d$ such that for all $\eta > 0$:

\[\begin{align} +-\sum_{i=1}^m A_i^\top (y_i + \eta d_i) & = 0 \\ +(y_i + \eta d_i) & \in \mathcal{C}_i^* & i = 1 \ldots m, +\end{align}\]

and:

\[-\sum_{i=1}^m b_i^\top (y_i + \eta d_i) > -\sum_{i=1}^m b_i^\top y_i,\]

for any feasible dual solution $y$. The latter simplifies to $-\sum_{i=1}^m b_i^\top d_i > 0$. For a maximization problem, the inequality is $\sum_{i=1}^m b_i^\top d_i < 0$. (Note that these are the same inequality, modulo a - sign.)

If the solver has found a certificate of primal infeasibility:

Note

The choice of whether to scale the ray $d$ to have magnitude 1 is left to the solver.

Infeasibility certificates of variable bounds

Many linear solvers (for example, Gurobi) do not provide explicit access to the primal infeasibility certificate of a variable bound. However, given a set of linear constraints:

\[\begin{align} +l_A \le A x \le u_A \\ +l_x \le x \le u_x, +\end{align}\]

the primal certificate of the variable bounds can be computed using the primal certificate associated with the affine constraints, $d$. (Note that $d$ will have one element for each row of the $A$ matrix, and that some or all of the elements in the vectors $l_A$ and $u_A$ may be $\pm \infty$. If both $l_A$ and $u_A$ are finite for some row, the corresponding element in `d must be 0.)

Given $d$, compute $\bar{d} = d^\top A$. If the bound is finite, a certificate for the lower variable bound of $x_i$ is $\max\{\bar{d}_i, 0\}$, and a certificate for the upper variable bound is $\min\{\bar{d}_i, 0\}$.

diff --git a/previews/PR2418/background/motivation/index.html b/previews/PR2418/background/motivation/index.html new file mode 100644 index 0000000000..42666dc67d --- /dev/null +++ b/previews/PR2418/background/motivation/index.html @@ -0,0 +1,2 @@ + +Motivation · MathOptInterface

Motivation

MathOptInterface (MOI) is a replacement for MathProgBase, the first-generation abstraction layer for mathematical optimization previously used by JuMP and Convex.jl.

To address a number of limitations of MathProgBase, MOI is designed to:

  • Be simple and extensible
    • unifying linear, quadratic, and conic optimization,
    • seamlessly facilitating extensions to essentially arbitrary constraints and functions (for example, indicator constraints, complementarity constraints, and piecewise-linear functions)
  • Be fast
    • by allowing access to a solver's in-memory representation of a problem without writing intermediate files (when possible)
    • by using multiple dispatch and avoiding requiring containers of non-concrete types
  • Allow a solver to return multiple results (for example, a pool of solutions)
  • Allow a solver to return extra arbitrary information via attributes (for example, variable- and constraint-wise membership in an irreducible inconsistent subset for infeasibility analysis)
  • Provide a greatly expanded set of status codes explaining what happened during the optimization procedure
  • Enable a solver to more precisely specify which problem classes it supports
  • Enable both primal and dual warm starts
  • Enable adding and removing both variables and constraints by indices that are not required to be consecutive
  • Enable any modification that the solver supports to an existing model
  • Avoid requiring the solver wrapper to store an additional copy of the problem data
diff --git a/previews/PR2418/background/naming_conventions/index.html b/previews/PR2418/background/naming_conventions/index.html new file mode 100644 index 0000000000..cb90485c93 --- /dev/null +++ b/previews/PR2418/background/naming_conventions/index.html @@ -0,0 +1,2 @@ + +Naming conventions · MathOptInterface

Naming conventions

MOI follows several conventions for naming functions and structures. These should also be followed by packages extending MOI.

Sets

Sets encode the structure of constraints. Their names should follow the following conventions:

  • Abstract types in the set hierarchy should begin with Abstract and end in Set, for example, AbstractScalarSet, AbstractVectorSet.
  • Vector-valued conic sets should end with Cone, for example, NormInfinityCone, SecondOrderCone.
  • Vector-valued Cartesian products should be plural and not end in Cone, for example, Nonnegatives, not NonnegativeCone.
  • Matrix-valued conic sets should provide two representations: ConeSquare and ConeTriangle, for example, RootDetConeTriangle and RootDetConeSquare. See Matrix cones for more details.
  • Scalar sets should be singular, not plural, for example, Integer, not Integers.
  • As much as possible, the names should follow established conventions in the domain where this set is used: for instance, convex sets should have names close to those of CVX, and constraint-programming sets should follow MiniZinc's constraints.
diff --git a/previews/PR2418/changelog/index.html b/previews/PR2418/changelog/index.html new file mode 100644 index 0000000000..bd3a6caf67 --- /dev/null +++ b/previews/PR2418/changelog/index.html @@ -0,0 +1,30 @@ + +Release notes · MathOptInterface

Release notes

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

v1.25.2 (January 29, 2024)

Fixed

Other

  • Clarified ordering of nonlinear tape in documentation (#2401)
  • Updated vale.sh (#2403) (#2404)
  • Tidied `src/Utilities/results.jl (#2411)

v1.25.1 (January 11, 2024)

Fixed

Other

  • Removed a duplicated test (#2395)

v1.25.0 (January 5, 2024)

Added

  • Added the AutomaticDifferentiationBackend attribute (#2386)

Fixed

v1.24.0 (January 2, 2024)

Added

  • Added get_fallback for ConstraintDual of variable bounds (#2373)

Fixed

  • Fixed RSOCtoPSDBridge for dimension 2 (#2359)
  • Fixed getting ConstraintFunction in conversion bridge (#2360)
  • Fixed map_indices (#2367)
  • Fixed SlackBridgePrimalDualStart for non-slack bridges (#2365)
  • Fixed test_attribute_TimeLimitSec (#2370)
  • Fixed order of model attributes during copy_to (#2372)
  • Fixed ConstraintIndex conflicts between variable and constraint bridges (#2362)
  • Fixed corner-case deletion in bridges (#2377)
  • Fixed ListOfVariablesWithAttributeSet for variable bridges (#2380)
  • Fixed SlackBridge if scalar constant is not zero (#2382)
  • Fixed setting multiple bounds on a bridged variable (#2383)

Other

  • Minor documentation improvements (#2355), (#2374)
  • Improved side_dimension_for_vectorized_dimension (#2356)
  • Added DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)
  • Refactored SDPAModel into a separate test file and test more widely (#2364), (#2357)

v1.23.0 (November 29, 2023)

Added

Fixed

  • Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)
  • Fixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)

v1.22.0 (November 6, 2023)

Added

Fixed

Other

  • Fixed typo in docstring of ScalarAffineFunction (#2326)
  • Added Gurobi to solver-tests.yml (#2332)
  • Improved the error message when a bridge does not support an attribute (#2329)
  • Improved documentation for implementing a bridge (#2334)
  • Updated [compat] bounds in Project.toml (#2344)

v1.21.0 (October 25, 2023)

Added

Fixed

  • Fixed test_attribute_TimeLimitSec (#2256)
  • Fixed conversion cost in objective bridges (#2309)

Other

  • Fixed flakey link checking in documentation (#2297)
  • Minor documentation fixes (#2304) (#2313)
  • Fixed [compat] section of Project.toml (#2310)
  • Added MultiObjectiveAlgorithms to solver-tests.yml (#2312)

v1.20.1 (September 24, 2023)

Fixed

Other

  • Added MathOptSetDistances to solver-tests.yml (#2265)
  • Updated Documenter (#2266)
  • Fixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)
  • Various style improvements
    • Replaced using Package with import Package where possible (#2274)
    • Removed Utilities.EMPTYSTRING (#2283)
    • Removed unnecessary const acronyms in Utilities (#2280) (#2281)
    • Removed invalid and unused method (#2286)
  • Refactored src/Utilities/model.jl (#2287)

v1.20.0 (September 7, 2023)

Added

Other

  • Updated dependencies (#2258)
  • Improved performance of ScalarNonlinearFunction utilities (#2259)
  • Fixed docstrings (#2261)

v1.19.0 (August 15, 2023)

Added

Fixed

Other

  • Added extensions to solver-tests.yml (#2229)
  • Refactored test/Benchmarks (#2234)
  • Fixed warnings in tests (#2241) (#2243)
  • Small refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)
  • Fixed various typos (#2251) (#2255)
  • Partitioned how we run the tests on GitHub actions (#2252) (#2253)

v1.18.0 (June 23, 2023)

Added

Fixed

  • Fixed a missing @require in MOI.Test (#2195) (#2196)
  • Fixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)
  • Fixed splatting nonlinear expression with univariate operator (#2221)

Other

  • Removed unused argument names (#2199)
  • Reduced memory requirement for tests (#2204)
  • Refactored Utilities.promote_operation (#2206)
  • Improved code style in Utilities/mutable_arithmetics.jl (#2209)
  • Refactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)

v1.17.1 (June 6, 2023)

Fixed

Other

  • Added documentation for enum instances (#2186)
  • Updated chatroom links in documentation (#2188)
  • Changed the documentation to build on Julia v1.9 (#2191)

v1.17.0 (June 1, 2023)

Added

Fixed

  • Fixed support for external sets in Utilities.loadfromstring! (#2177)
  • Fixed promote_operation for ScalarNonlinearFunction (#2179)
  • Fixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)

v1.16.0 (May 16, 2023)

Added

Fixed

  • Fixed support for Julia v1.9 to work around a bug in the upstream Julia compiler (#2161) (#2163)
  • Fixed a correctness bug in Bridges.Constraint.HermitianToSymmetricPSDBridge (#2171)
  • Fixed convert(::VariableIndex, ::ScalarAffineFunction) when the function has terms with 0coefficients (#2173)

Other

  • Fixed solver-tests.yml (#2157)
  • Updated documentation links to developer chatroom (#2160)
  • Added various tests for bridges (#2156)
  • Added checklists to the developer documentation (#2167) (#2168)

v1.15.1 (April 25, 2023)

Fixed

  • Fixed deleting a variable in a bridged objective (#2150)

v1.15.0 (April 19, 2023)

Added

Fixed

Other

  • Add a test for variables in one-sided open Interval sets (#2133)
  • Minor style fixes in the source code (#2148)

v1.14.1 (April 6, 2023)

Fixed

Other

  • Added a warning when an ambiguous string is passed to exclude in Test.runtests (#2136)

v1.14.0 (April 4, 2023)

Added

Fixed

  • Fixed ResultCount when parsing .sol files in FileFormats.NL (#2130)

v1.13.2 (March 21, 2023)

Fixed

Other

  • Fixed typos in the documentation (#2114)
  • Functions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)

v1.13.1 (March 3, 2023)

Other

  • Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)
  • Improved the docstrings in src/functions.jl (#2108)

v1.13.0 (February 28, 2023)

Added

Fixed

Other

  • Added tests for vector-valued objective functions in FileFormats.MOF (#2093)
  • Used and documented preference for import MathOptInterface as MOI (#2096)
  • Fix and test links in the documentation with linkcheck = true (#2098)
  • Improved docstrings of sets in src/sets.jl (#2099)
  • Skip checking flakey links in documentation with linkcheck_ignore (#2103)

v1.12.0 (February 10, 2023)

Added

Fixed

  • Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)

Other

v1.11.5 (January 24, 2023)

Fixed

  • Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)

Other

  • Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)

v1.11.4 (January 12, 2023)

Fixed

  • Fixed a bug reading .lp files with an Integer section (#2078)

v1.11.3 (January 12, 2023)

Fixed

  • Fixed a performance bug when deleting a vector of constraints (#2072)
  • Fixed a bug reading .lp files with terms like x -1 y (#2076)

Other

  • Documented the two-argument method of optimize! (#2074)

v1.11.2 (January 2, 2023)

Fixed

  • Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)
  • Fixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)

v1.11.1 (December 22, 2022)

Fixed

  • Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)

v1.11.0 (December 2, 2022)

Added

Other

  • Tidied these release notes (#2055)

v1.10.0 (November 22, 2022)

Added

Fixed

  • Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)
  • Fixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)
  • Fixed reading of free variables in FileFormats.LP (#2044)
  • Fixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)
  • Fixed situations in which x^y returns a complex value in Nonlinear (#2050)

Other

  • Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)
  • Removed specialized iterators for keys and values in Utilities.CleverDicts (#2051)

v1.9.0 (October 29, 2022)

Added

  • Added default fallback for getting ListOfConstraintIndices and NumberOfConstraints when the constraint type is unsupported by the model (#2021)
  • Added support for min and max in nonlinear expressions (#2023)
  • Added support for Indicator{EqualTo{T}} constraints in FileFormats.MPS (#2022)
  • Added default fallback for write_to_file and read_from_file (#2029)

Fixed

  • Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)
  • Fixed reading free rows in FileFormats.MPS files (#2009)
  • Fixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)
  • Fixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)
  • Fixed the requirements check in Test.test_constraint_get_ConstraintIndex (#2024)

v1.8.2 (September 20, 2022)

Documentation

  • Added vale as a documentation linter (#2002)
  • Improved styling of code blocks in the PDF (#1999) (#2000)
  • Fixed a number of typos in the documentation (#2001) (#2003)

v1.8.1 (September 12, 2022)

Fixed

  • Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)

v1.8.0 (September 1, 2022)

Added

Fixed

  • Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)
  • Allow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)

v1.7.0 (August 16, 2022)

Added

Fixed

  • Fixed some missing promotion rules

Other

  • Improved the performance of Jacobian products in Nonlinear
  • Removed an un-needed copy in Utilities.modify_function
  • Various clean-ups in Bridges/bridge_optimizer.jl

v1.6.1 (July 23, 2022)

Fixed

  • Added support for ExponentialCone in MatrixOfConstraints
  • Fix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint

v1.6.0 (July 2, 2022)

Added

  • Added Bridges.needs_final_touch and Bridges.final_touch
  • Added new bridges from constraint programming sets to mixed-integer linear programs:
    • AllDifferentToCountDistinctBridge
    • CountAtLeastToCountBelongsBridge
    • CountBelongsToMILPBridge
    • CountDistinctToMILPBridge
    • CountGreaterThanToMILPBridge
    • CircuitToMILPBridge

Fixed

  • Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear
  • Fix BinPackingToMILPBridge to respect variable bounds
  • Fix SemiToBinaryBridge to throw error if other bounds are set

v1.5.0 (June 27, 2022)

Added

  • Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error
  • Added Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue
  • Added new bridges:
    • RootDetConeSquare to RootDetConeTriangle
    • LogDetConeSquare to LogDetConeTriangle
    • BinPacking to a mixed-integer linear program
    • Table to a mixed-integer linear program
  • Added Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer

Fixed

  • Fixed ZeroOne tests with lower and upper bounds
  • Fixed error in FileFormats.LP when reading a malformed file
  • Fixed reading of nonlinear programs in FileFormats.MOF
  • Fixed bug in ConstraintDual when using SquareBridge

Other

  • Improved documentation of nonlinear API
  • Documented duality convention for PositiveSemidefiniteConeSquare sets
  • Fixed typo in Bridges.Constraint.QuadToSOCBridge docstring

v1.4.0 (June 9, 2022)

Added

  • Added a number of sets for constraint programming:
    • AllDifferent
    • BinPacking
    • Circuit
    • CountAtLeast
    • CountBelongs
    • CountDistinct
    • CountGreaterThan
    • Cumulative
    • Path
    • Table
  • Added support for user-defined hessians in Nonlinear
  • Added Bridges.runtests to simplify the testing of bridge implementations

Fixed

  • Fixed a bug in FileFormats.NL when writing univariate *

Other

  • Began a large refactoring of the Bridges submodule, with greatly improved documentation.

v1.3.0 (May 27, 2022)

Added

  • Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.
  • Add FileFormats.NL.SolFileResults(::IO, ::Model)
  • Add FileFormats.NL.read!(::IO, ::Model)
  • Add MOI.modify that accepts a vector of modifications

Fixed

  • Fixed a bug in Test which attempted to include non-.jl files
  • Fixed a bug in FileFormats for models with open interval constraints

Other

  • Fixed a performance issue in Utilities.DoubleDict
  • Various minor improvements to the documentation

v1.2.0 (April 25, 2022)

Added

  • Add support for the FORMAT_REW/.rew file format in FileFormats.

Fixed

  • Fix bug handling of default variable bounds in FileFormats.LP
  • Fix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.

v1.1.2 (March 31, 2022)

Fixed

  • Fix a range of bugs in FileFormats.LP
  • Fix reading of problem dimensions in FileFormats.SDPA

v1.1.1 (March 23, 2022)

Fixed

  • Fix bug in test_model_UpperBoundAlreadySet
  • Fix bug in test_infeasible_ tests
  • Fix bug in test_objective_ObjectiveFunction_blank
  • Relax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.

New tests

  • Add test_conic_empty_matrix that checks conic solvers support problems with no variables.

v1.1.0 (March 2, 2022)

Added

  • Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.

v1.0.2 (March 1, 2022)

Fixed

  • Fixed a bug in the test_model_ScalarFunctionConstantNotZero test
  • Fixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute
  • Identified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.

v1.0.1 (February 25, 2022)

Fixed

  • Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer
  • Fixed a bug in which shift_constant did not promote mixed types of coefficients
  • Fixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed
  • Fixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function
  • Fixed a bug when modifying scalar constants of a function containing a bridged variable
  • Fixed a bug in which final_touch was not always called with a CachingOptimizer

v1.0.0 (February 17, 2022)

Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.

Breaking

  • Julia 1.6 is now the minimum supported version
  • All deprecations have been removed

Troubleshooting problems when updating

If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)

To find the deprecated features you are using, start Julia with --depwarn=yes:

$ julia --depwarn=yes

Then install MathOptInterface v0.10.9:

julia> using Pkg
+julia> pkg"add MathOptInterface@0.10"

And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.

v0.10.9 (February 16, 2022)

Added

  • Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers
  • Added MOI.default_cache for specifying the model used in CachingOptimizer

Fixed

  • Fixed LaTeX printing of MOI.Interval sets

Other

  • Added Aqua.jl as a CI check, and fixed suggested issues
  • The constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.

v0.10.8 (February 3, 2022)

Added

  • Added a Base.read! for FileFormats.LP.

Fixed

  • Fixed a bug in MutableSparseMatrix
  • Fixed a bug when calling operate!(vcat, ...) with Number arguments
  • Removed unintended export of deprecated symbols
  • Fixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.

v0.10.7 (January 5, 2022)

Added

  • Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.

Fixed

  • Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.
  • Fixed an error message in FileFormats.CBF
  • Fixed comparison in test_linear_integration_Interval
  • Fixed errors for ConstraintPrimal in a CachingOptimizer
  • Fixed printing of models with non-Float64 coefficients.

Other

  • Various improvements to reduce time-to-first-solve latency
  • Improved error message when an optimizer does not support compute_conflict!

v0.10.6 (November 30, 2021)

Added

  • Added new documentation and tests for infeasibility certificates
  • Added a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v"0.10.5" to run tests added in v0.10.5 and earlier.
  • MOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).
  • Added infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE
  • CachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.

Fixed

  • Fixed a StackOverflow bug in copy_to
  • Fixed error thrown when nonconvex quadratic constraints cannot be bridged
  • Fixed a bug in copy_to for FileFormats.NL.Model
  • Fixed a bug in FileFormats.NL when printing large integers
  • Remove a common test failure for LowerBoundAlreadySet tests
  • Utilities.num_rows is now exported
  • Remove parts of failing test_model_copy_to_xxx tests due to bridges

v0.10.5 (November 7, 2021)

Fixed

  • Fixed getter in UniversalFallback
  • Fixed test_solve_conflict_zeroone_ii

Other

  • Make normalize_and_add_constraint more flexible
  • Update paper BibTeX

v0.10.4 (October 26, 2021)

Added

  • Add SolverVersion attribute
  • Add new tests:
    • test_solve_conflict_zeroone_ii
    • test_nonlinear_objective
  • Utilities.VariablesContainer now supports ConstraintFunction and ConstraintSet
  • The documentation is now available as a PDF

Other

  • Update to MutableArithmetics 0.3
  • Various improvements to the documentation

v0.10.3 (September 18, 2021)

Fixed

  • Fixed bug which prevented callbacks from working through a CachingOptimizer
  • Fixed bug in Test submodule

v0.10.2 (September 16, 2021)

  • Updated MathOptFormat to v1.0
  • Updated JSONSchema to v1.0
  • Added Utilities.set_with_dimension
  • Added two-argument optimize!(::AbstractOptimizer, ::ModelLike)
  • The experimental feature copy_to_and_optimize! has been removed
  • Det bridges now support getting ConstraintFunction and ConstraintSet
  • Various minor bug fixes identified by improved testing

v0.10.1 (September 8, 2021)

  • Various fixes to MOI.Test

v0.10.0 (September 6, 2021)

MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.

Breaking in MOI

  • SingleVariable has been removed; use VariableIndex instead
  • SingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError
  • SettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed
  • VariableIndex constraints should not support ConstraintName
  • VariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead
  • ListOfConstraints has been renamed to ListOfConstraintTypesPresent
  • ListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}
  • SolveTime has been renamed to SolveTimeSec
  • IndicatorSet has been renamed to Indicator
  • RawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument
  • The .N field in result attributes has been renamed to .result_index
  • The .variable_index field in ScalarAffineTerm has been renamed to .variable
  • The .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1
  • The .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2
  • The order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.
  • The index_value function has been removed. Use .value instead.
  • isapprox has been removed for SOS1 and SOS2.
  • The dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.
  • copy_to no longer takes keyword arguments:
    • copy_names: now copy names if they are supported by the destination solver
    • filter_constraints: use Utilities.ModelFilter instead
    • warn_attributes: never warn about optimizer attributes

Breaking in Bridges

  • Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge
  • Constraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge
  • Bridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.
  • Bridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges
  • The signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).

Breaking in FileFormats

  • FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.

Breaking in Utilities

  • The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.
  • Utilities.supports_default_copy has been renamed to supports_incremental_interface
  • Utilities.automatic_copy_to has been renamed to Utilities.default_copy_to
  • The allocate-load API has been removed
  • CachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.
  • The field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.
  • The size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.
  • The size argument to Utilities.IndexMap(::Integer) has been removed.
  • Utilities.DoubleDicts have been significantly refactored. Consult the source code for details.
  • Utilities.test_models_equal has been moved to MOI.Test

Breaking in Test

  • MOI.Test has been renamed to MOI.DeprecatedTest
  • An entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.

Other changes:

  • attribute_value_type has been added
  • copy_to_and_optimize! has been added
  • VariableBasisStatus has been added
  • print(model) now prints a human-readable description of the model
  • Various improvements to the FileFormats submodule
    • FileFormats.CBF was refactored and received bugfixes
    • Support for MathOptFormat v0.6 was added in FileFormats.MOF
    • FileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.
    • FileFormats.NL has been added to support nonlinear files
  • Improved type inference throughout to reduce latency

Updating

A helpful script when updating is:

for (root, dirs, files) in walkdir(".")
+    for file in files
+        if !endswith(file, ".jl")
+            continue
+        end
+        path = joinpath(root, file)
+        s = read(path, String)
+        for pair in [
+            ".variable_index" => ".variable",
+            "RawParameter" => "RawOptimizerAttribute",
+            "ListOfConstraints" => "ListOfConstraintTypesPresent",
+            "TestConfig" => "Config",
+            "attr.N" => "attr.result_index",
+            "SolveTime" => "SolveTimeSec",
+            "DataType" => "Type",
+            "Utilities.supports_default_copy_to" =>
+                "supports_incremental_interface",
+            "SingleVariableConstraintNameError" =>
+                "VariableIndexConstraintNameError",
+            "SettingSingleVariableFunctionNotAllowed" =>
+                "SettingVariableIndexFunctionNotAllowed",
+            "automatic_copy_to" => "default_copy_to",
+        ]
+            s = replace(s, pair)
+        end
+        write(path, s)
+    end
+end

v0.9.22 (May 22, 2021)

This release contains backports from the ongoing development of the v0.10 release.

  • Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.
  • Improved performance of Utilities.is_canonical.
  • Fixed Utilities.pass_nonvariable_constraints with bridged variables.
  • Fixed performance regression of Utilities.Model.
  • Fixed ordering of objective setting in parser.

v0.9.21 (April 23, 2021)

  • Added supports_shift_constant.
  • Improve performance of bridging quadratic constraints.
  • Add precompilation statements.
  • Large improvements to the documentation.
  • Fix a variety of inference issues, benefiting precompilation and reducing initial latency.
  • RawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.
  • Utilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.

v0.9.20 (February 20, 2021)

  • Improved performance of Utilities.ScalarFunctionIterator
  • Added support for compute_conflict to MOI layers
  • Added test with zero off-diagonal quadratic term in objective
  • Fixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints
  • Fixed modification of un-set objective
  • Fixed function modification with duplicate terms
  • Made unit tests abort without failing if the problem class is not supported
  • Formatted code with JuliaFormatter
  • Clarified BasisStatusCode's docstring

v0.9.19 (December 1, 2020)

  • Added CallbackNodeStatus attribute
  • Added bridge from GreaterThan or LessThan to Interval
  • Added tests for infeasibility certificates and double optimize
  • Fixed support for Julia v1.6
  • Re-organized MOI docs and added documentation for adding a test

v0.9.18 (November 3, 2020)

  • Various improvements for working with complex numbers
  • Added GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint

v0.9.17 (September 21, 2020)

  • Fixed CleverDict with variable of negative index value
  • Implement supports_add_constrained_variable for MockOptimizer

v0.9.16 (September 17, 2020)

  • Various fixes:
    • 32-bit support
    • CleverDict with abstract value type
    • Checks in test suite

v0.9.15 (September 14, 2020)

  • Bridges improvements:
    • (R)SOCtoNonConvexQuad bridge
    • ZeroOne bridge
    • Use supports_add_constrained_variable in LazyBridgeOptimizer
    • Exposed VariableBridgeCost and ConstraintBridgeCost attributes
    • Prioritize constraining variables on creation according to these costs
    • Refactor bridge debugging
  • Large performance improvements across all submodules
  • Lots of documentation improvements
  • FileFormats improvements:
    • Update MathOptFormat to v0.5
    • Fix supported objectives in FileFormats
  • Testing improvements:
    • Add name option for basic_constraint_test
  • Bug fixes and missing methods
    • Add length for iterators
    • Fix bug with duplicate terms
    • Fix order of LinearOfConstraintIndices

v0.9.14 (May 30, 2020)

  • Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).
  • Bump JSONSchema dependency from v0.2 to v0.3 (#1090).
  • Documentation improvements:
    • Fix typos (#1054, #1060, #1061, #1064, #1069, #1070).
    • Remove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).
  • Utilities improvements:
    • Fix is_canonical for quadratic functions (#1081, #1089).
    • Implement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).
    • Add support for custom objective functions for UniversalFallback (#1086).
    • Deterministic ordering of constraints in UniversalFallback (#1088).
  • Testing improvements:
    • Add NormOneCone/NormInfinityCone tests (#1045).
  • Bridges improvements:
    • Add bridges from Semiinteger and Semicontinuous (#1059).
    • Implement getting ConstraintSet for Variable.FlipSignBridge (#1066).
    • Fix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).
    • Fix NormOne/NormInf bridges with nonzero constants (#1045).
    • Fix StackOverflow in debug (#1063).
  • FileFormats improvements:
    • [SDPA] Implement the extension for integer variables (#1079).
    • [SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).
    • [SDPA] No scaling of off-diagonal coefficient (#1076).
    • [SDPA] Add missing negation of constant (#1075).

v0.9.13 (March 24, 2020)

  • Added tests for Semicontinuous and Semiinteger variables (#1033).
  • Added tests for using ExprGraphs from NLP evaluators (#1043).
  • Update version compatibilities of dependencies (#1034, #1051, #1052).
  • Fixed typos in documentation (#1044).

v0.9.12 (February 28, 2020)

  • Fixed writing NLPBlock in MathOptFormat (#1037).
  • Fixed MockOptimizer for result attributes with non-one result index (#1039).
  • Updated test template with instantiate (#1032).

v0.9.11 (February 21, 2020)

  • Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).
  • Described dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).
  • Fixed typos in documentation (#1022, #1024).
  • Fixed warning of unsupported attribute (#1027).
  • Added more rootdet/logdet conic tests (#1026).
  • Implemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).

v0.9.10 (January 31, 2020)

  • Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).
  • Added RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).
  • Added NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).
  • Added supports_constrained_variable(s) (#1004).
  • Added dual_set_type (#1002).
  • Added tests for vector specialized version of delete (#989, #1011).
  • Added PSD3 test (#1007).
  • Clarified dual solution of Tests.pow1v and Tests.pow1f (#1013).
  • Added support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).
  • Fixed Utilities.vectorize for empty vector (#1003).
  • Fixed free variables in LP writer (#1006).

v0.9.9 (December 29, 2019)

  • Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).
  • Improved performance of deletion of vector of variables in MOI.Utilities.Model (#983).
  • Updated to MutableArithmetics v0.2 (#981).
  • Added MutableArithmetics.promote_operation allocation tests (#975).
  • Fixed inference issue on Julia v1.1 (#982).

v0.9.8 (December 19, 2019)

  • Implemented MutableArithmetics API (#924).
  • Fixed callbacks with CachingOptimizer (#959).
  • Fixed MOI.dimension for MOI.Complements (#948).
  • Added fallback for add_variables (#972).
  • Added is_diagonal_vectorized_index utility (#965).
  • Improved linear constraints display in manual (#963, #964).
  • Bridges improvements:
    • Added IndicatorSet to SOS1 bridge (#877).
    • Added support for starting values for Variable.VectorizeBridge (#944).
    • Fixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).
    • Fixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).
    • Fixed choice between variable or constraint bridges for constrained variables (#973).
    • Improve performance of bridge shortest path (#945, #946, #956).
    • Added docstring for test_delete_bridge (#954).
    • Added Variable bridge tests (#952).

v0.9.7 (October 30, 2019)

  • Implemented _result_index_field for NLPBlockDual (#934).
  • Fixed copy of model with starting values for vector constraints (#941).
  • Bridges improvements:
    • Improved performance of add_bridge and added has_bridge (#935).
    • Added AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).
    • Added support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).

v0.9.6 (October 25, 2019)

  • Added complementarity constraints (#913).
  • Allowed ModelLike objects as value of attributes (#928).
  • Testing improvements:
    • Added dual_objective_value option to MOI.Test.TestConfig (#922).
    • Added InvalidIndex tests in basic_constraint_tests (#921).
    • Added tests for the constant term in indicator constraint (#929).
  • Bridges improvements:
    • Added support for starting values for Functionize bridges (#923).
    • Added variable indices context to variable bridges (#920).
    • Fixed a typo in printing o debug_supports (#927).

v0.9.5 (October 9, 2019)

  • Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).
  • Added tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).
  • Use 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).
  • Bridges improvements:
    • Added debug utilities for unsupported variable/constraint/objective (#861).
    • Fixed deletion of variables in bridged VectorOfVariables constraints (#909).
    • Fixed result_index with objective bridges (#911).

v0.9.4 (October 2, 2019)

  • Added solver-independent MIP callbacks (#782).
  • Implements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).
  • Added tests for result count of solution attributes (#901, #904).
  • Added NumberOfThreads attribute (#892).
  • Added Utilities.get_bounds to get the bounds on a variable (#890).
  • Added a note on duplicate coefficients in documentation (#581).
  • Added result index in ConstraintBasisStatus (#898).
  • Added extension dictionary to Utilities.Model (#884, #895).
  • Fixed deletion of constrained variables for CachingOptimizer (#905).
  • Implemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).
  • Bridges improvements:
    • Added Variable.RSOCtoSOCBridge (#907).
    • Implemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).

v0.9.3 (September 20, 2019)

  • Fixed ambiguity detected in Julia v1.3 (#891, #893).
  • Fixed missing sets from ListOfSupportedConstraints (#880).
  • Fixed copy of VectorOfVariables constraints with duplicate indices (#886).
  • Added extension dictionary to MOIU.Model (#884).
  • Implemented MOI.get for function and set for GeoMeanBridge (#888).
  • Updated documentation for SingleVariable indices and bridges (#885).
  • Testing improvements:
    • Added more comprehensive tests for names (#882).
    • Added tests for SingleVariable duals (#883).
    • Added tests for DualExponentialCone and DualPowerCone (#873).
  • Improvements for arbitrary coefficient type:
    • Fixed == for sets with mutable fields (#887).
    • Removed some Float64 assumptions in bridges (#878).
    • Automatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).

v0.9.2 (September 5, 2019)

  • Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).
  • Generalized contlinear tests for arbitrary coefficient type (#855).
  • Fixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).
  • Fixed Allocate-Load copy for single variable constraints (#856).
  • Bridges improvements:
    • Add objective bridges (#789).
    • Fixed Variable.RSOCtoPSDBridge for dimension 2 (#869).
    • Added Variable.SOCtoRSOCBridge (#865).
    • Added Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).
    • Fixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).

v0.9.1 (August 22, 2019)

  • Fix support for Julia v1.2 (#834).
  • L1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).
  • Added tests to MOI.Test.nametest (#833).
  • Fix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).
  • Implements operate for operators * and / between vector function and constant (#837).
  • Implements show for MOI.Utilities.IndexMap (#847).
  • Fix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).
  • Fix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).

v0.9.0 (August 13, 2019)

  • Support for Julia v0.6 and v0.7 was dropped (#714, #717).
  • A MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).
  • add_constrained_variable and add_constrained_variables were added (#759).
  • Support for indicator constraints was added (#709, #712).
  • DualObjectiveValue attribute was added (#473).
  • RawParameter attribute was added (#733).
  • A dual_set function was added (#804).
  • A Benchmarks submodule was added to facilitate solver benchmarking (#769).
  • A submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).
  • The field of ObjectiveValue was renamed to result_index (#729).
  • The _constant and Utilities.getconstant function were renamed to constant
  • REDUCTION_CERTIFICATE result status was added (#734).
  • Abstract matrix sets were added (#731).
  • Testing improvements:
    • The testing guideline was updated (#728).
    • Quadratic tests were added (#697).
    • Unit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).
    • A rotated second-order cone test was added (#759).
    • A power cone test was added (#768).
    • Tests for ZeroOne variables with variable bounds were added (#772).
    • An unbounded test was added (#773).
    • Existing tests had a few updates (#702, #703, #763).
  • Documentation improvements:
    • Added a section on CachingOptimizer (#777).
    • Added a section on UniversalFallback, Model and @model (#762).
    • Transition the knapsack example to a doctest with MockOptimizer (#786).
  • Utilities improvements:
    • A CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).
    • The Utilities.constant function was renamed to Utilities.constant_vector (#740).
    • Implement optimizer attributes for CachingOptimizer (#745).
    • Rename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).
    • operate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).
    • Fix a type piracy of operate (#784).
    • The load_constraint fallback signature was fixed (#760).
    • The set_dot function was extended to work with sparse arrays (#805).
  • Bridges improvements:
    • The bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).
    • Bridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).
    • Fix constraint attributes for bridges (#699).
    • Constraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).
    • Variable bridges were added in (#759).
    • Various improvements (#746, #747).

v0.8.4 (March 13, 2019)

  • Performance improvement in default_copy_to and bridge optimizer (#696).
  • Add Silent and implement setting optimizer attributes in caching and mock optimizers (#695).
  • Add Functionize bridges (SingleVariable and VectorOfVariables) (#659).
  • Minor typo fixes (#694).

v0.8.3 (March 6, 2019)

  • Use zero constant in scalar constraint function of MOI.Test.copytest (#691).
  • Fix variable deletion with SingleVariable objective function (#690).
  • Fix LazyBridgeOptimizer with bridges that add no constraints (#689).
  • Error message improvements (#673, #685, #686, #688).
  • Documentation improvements (#682, #683, #687).
  • Basis status:
    • Remove VariableBasisStatus (#679).
    • Test ConstraintBasisStatus and implement it in bridges (#678).
  • Fix inference of NumberOfVariables and NumberOfConstraints (#677).
  • Implement division between a quadratic function and a number (#675).

v0.8.2 (February 7, 2019)

  • Add RawStatusString attribute (#629).
  • Do not set names to the optimizer but only to the cache in CachingOptimizer (#638).
  • Make scalar MOI functions act as scalars in broadcast (#646).
  • Add function utilities:
    • Implement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).
    • Add a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).
  • Improve support for starting values:
    • Show a warning in copy when starting values are not supported instead of throwing an error (#630).
    • Fix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).
    • Add a test in contlineartest with partially set VariablePrimalStart.
  • Bridges improvements:
    • Fix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.
    • Add Slack bridges (#610, #650).
    • Add FlipSign bridges (#658).
  • Add tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).
  • Use tolerance to compare VariablePrimal in rotatedsoc1 test (#632).
  • Use a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).

v0.8.1 (January 7, 2019)

  • Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).
  • Rename fullbridgeoptimizer into full_bridge_optimizer (#621).
  • Allow custom constraint types with full_bridge_optimizer (#617).
  • Add Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).

v0.8.0 (December 18, 2018)

  • Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.
  • Rename CachingOptimizer methods for style compliance.
  • Add an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.

v0.7.0 (December 13, 2018)

  • Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.
  • Check supports_default_copy_to in tests (#594).
  • Key pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.
  • Add perspective dimension to log-det cone (#593).

v0.6.4 (November 27, 2018)

  • Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).
  • Add a solver naming guideline (#578).
  • Make FeasibilitySense the default ObjectiveSense (#579).
  • Fix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).
  • Document solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).

v0.6.3 (November 16, 2018)

  • Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)
  • Attributes may now be partially set (some values could be nothing). (#563)
  • Performance improvements in Utilities.Model (#549, #567, #568)
  • Fix bug in QuadtoSOC (#558).
  • New supports_default_copy_to method that optimizers should implement to control caching behavior.
  • Documentation improvements.

v0.6.2 (October 26, 2018)

  • Improve hygiene of @model macro (#544).
  • Fix bug in copy tests (#543).
  • Fix bug in UniversalFallback attribute getter (#540).
  • Allow all correct solutions for solve_blank_obj unit test (#537).
  • Add errors for Allocate-Load and bad constraints (#534).
  • [performance] Add specialized implementation of hash for VariableIndex (#533).
  • [performance] Construct the name to object dictionaries lazily in model (#535).
  • Add the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).

v0.6.1 (September 22, 2018)

  • Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).
  • Add warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).
  • Modify MOIT.copytest to not add multiples constraints on the same variable (#521).
  • Add missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).

v0.6.0 (August 30, 2018)

  • The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.
  • Rename functions according to the JuMP style guide:
    • copy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;
    • set! -> set;
    • addvariable[s]! -> add_variable[s];
    • supportsconstraint -> supports_constraint;
    • addconstraint[s]! -> add_constraint[s];
    • isvalid -> is_valid;
    • isempty -> is_empty;
    • Base.delete! -> delete;
    • modify! -> modify;
    • transform! -> transform;
    • initialize! -> initialize;
    • write -> write_to_file; and
    • read! -> read_from_file.
  • Remove free! (use Base.finalize instead).
  • Add the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.
  • Add result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.
  • Add tests for ObjectiveBound.
  • Add test for empty rows in vector linear constraint.
  • Rework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)
  • canget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).

v0.5.0 (August 5, 2018)

  • Fix names with CachingOptimizer.
  • Cleanup thanks to @mohamed82008.
  • Added a universal fallback for constraints.
  • Fast utilities for function canonicalization thanks to @rdeits.
  • Renamed dimension field to side_dimension in the context of matrix-like sets.
  • New and improved tests for cases like duplicate terms and ObjectiveBound.
  • Removed cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.
  • The API for copy! is updated to remove the CopyResult type.
  • Updates for the new JuMP style guide.

v0.4.1 (June 28, 2018)

  • Fixes vector function modification on 32 bits.
  • Fixes Bellman-Ford algorithm for bridges.
  • Added an NLP test with FeasibilitySense.
  • Update modification documentation.

v0.4.0 (June 23, 2018)

  • Helper constructors for VectorAffineTerm and VectorQuadraticTerm.
  • Added modify_lhs to TestConfig.
  • Additional unit tests for optimizers.
  • Added a type parameter to CachingOptimizer for the optimizer field.
  • New API for problem modification (#388)
  • Tests pass without deprecation warnings on Julia 0.7.
  • Small fixes and documentation updates.

v0.3.0 (May 25, 2018)

  • Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.
  • Improvements to MockOptimizer.
  • Significant changes to Bridges.
  • New and improved unit tests.
  • Fixes for Julia 0.7.

v0.2.0 (April 24, 2018)

  • Improvements to and better coverage of Tests.
  • Documentation fixes.
  • SolverName attribute.
  • Changes to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).
  • Addition of NLP tests.
  • Introduction of UniversalFallback.
  • copynames keyword argument to MOI.copy!.
  • Add Bridges submodule.

v0.1.0 (February 28, 2018)

  • Initial public release.
  • The framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.
diff --git a/previews/PR2418/developer/checklists/index.html b/previews/PR2418/developer/checklists/index.html new file mode 100644 index 0000000000..9ea1a562d6 --- /dev/null +++ b/previews/PR2418/developer/checklists/index.html @@ -0,0 +1,112 @@ + +Checklists · MathOptInterface

Checklists

The purpose of this page is to collate a series of checklists for commonly performed changes to the source code of MathOptInterface.

In each case, copy the checklist into the description of the pull request.

Making a release

Use this checklist when making a release of the MathOptInterface repository.

## Basic
+
+ - [ ] `version` field of `Project.toml` has been updated
+       - If a breaking change, increment the MAJOR field and reset others to 0
+       - If adding new features, increment the MINOR field and reset PATCH to 0
+       - If adding bug fixes or documentation changes, increment the PATCH field
+
+## Documentation
+
+ - [ ] Add a new entry to `docs/src/changelog.md`, following existing style
+
+## Tests
+
+ - [ ] The `solver-tests.yml` GitHub action does not have unexpected failures.
+       To run the action, go to:
+       https://github.com/jump-dev/MathOptInterface.jl/actions/workflows/solver-tests.yml
+       and click "Run workflow"

Adding a new set

Use this checklist when adding a new set to the MathOptInterface repository.

## Basic
+
+ - [ ] Add a new `AbstractScalarSet` or `AbstractVectorSet` to `src/sets.jl`
+ - [ ] If `isbitstype(S) == false`, implement `Base.copy(set::S)`
+ - [ ] If `isbitstype(S) == false`, implement `Base.:(==)(x::S, y::S)`
+ - [ ] If an `AbstractVectorSet`, implement `dimension(set::S)`, unless the
+       dimension is given by `set.dimension`.
+
+## Utilities
+
+ - [ ] If an `AbstractVectorSet`, implement `Utilities.set_dot`,
+       unless the dot product between two vectors in the set is equivalent to
+       `LinearAlgebra.dot`
+ - [ ] If an `AbstractVectorSet`, implement `Utilities.set_with_dimension` in
+       `src/Utilities/matrix_of_constraints.jl`
+ - [ ] Add the set to the `@model` macro at the bottom of `src/Utilities.model.jl`
+
+## Documentation
+
+ - [ ] Add a docstring, which gives the mathematical definition of the set,
+       along with an `## Example` block containing a `jldoctest`
+ - [ ] Add the docstring to `docs/src/reference/standard_form.md`
+ - [ ] Add the set to the relevant table in `docs/src/manual/standard_form.md`
+
+## Tests
+
+ - [ ] Define a new `_set(::Type{S})` method in `src/Test/test_basic_constraint.jl`
+       and add the name of the set to the list at the bottom of that files
+ - [ ] If the set has any checks in its constructor, add tests to `test/sets.jl`
+
+## MathOptFormat
+
+ - [ ] Open an issue at `https://github.com/jump-dev/MathOptFormat` to add
+       support for the new set {{ replace with link to the issue }}
+
+## Optional
+
+ - [ ] Implement `dual_set(::S)` and `dual_set_type(::Type{S})`
+ - [ ] Add new tests to the `Test` submodule exercising your new set
+ - [ ] Add new bridges to convert your set into more commonly used sets

Adding a new bridge

Use this checklist when adding a new bridge to the MathOptInterface repository.

The steps are mostly the same, but locations depend on whether the bridge is a Constraint, Objective, or Variable bridge. In each case below, replace XXX with the appropriate type of bridge.

## Basic
+
+ - [ ] Create a new file in `src/Bridges/XXX/bridges`
+ - [ ] Define the bridge, following existing examples. The name of the bridge
+       struct must end in `Bridge`
+ - [ ] Check if your bridge can be a subtype of [`MOI.Bridges.Constraint.SetMapBridge`](@ref)
+ - [ ] Define a new `const` that is a `SingleBridgeOptimizer` wrapping the
+       new bridge. The name of the const must be the name of the bridge, less
+       the `Bridge` suffix
+ - [ ] `include` the file in `src/Bridges/XXX/bridges/XXX.jl`
+ - [ ] If the bridge should be enabled by default, add the bridge to
+       `add_all_bridges` at the bottom of `src/Bridges/XXX/XXX.jl`
+
+## Tests
+
+ - [ ] Create a new file in the appropriate subdirectory of `tests/Bridges/XXX`
+ - [ ] Use `MOI.Bridges.runtests` to test various inputs and outputs of the
+       bridge
+ - [ ] If, after opening the pull request to add the bridge, some lines are not
+       covered by the tests, add additional bridge-specific tests to cover the
+       untested lines.
+
+## Documentation
+
+ - [ ] Add a docstring which uses the same template as existing bridges.
+ - [ ] Add the docstring to `docs/src/submodules/Bridges/list_of_bridges.md`
+
+## Final touch
+
+If the bridge depends on run-time values of other variables and constraints in
+the model:
+
+ - [ ] Implement `MOI.Utilities.needs_final_touch(::Bridge)`
+ - [ ] Implement `MOI.Utilities.final_touch(::Bridge, ::MOI.ModelLike)`
+ - [ ] Ensure that `final_touch` can be called multiple times in a row

Updating MathOptFormat

Use this checklist when updating the version of MathOptFormat.

## Basic
+
+ - [ ] The file at `src/FileFormats/MOF/mof.schema.json` is updated
+ - [ ] The constant `_SUPPORTED_VERSIONS` is updated in
+       `src/FileFormats/MOF/MOF.jl`
+
+## New sets
+
+ - [ ] New sets are added to the `@model` in `src/FileFormats/MOF/MOF.jl`
+ - [ ] New sets are added to the `@enum` in `src/FileFormats/MOF/read.jl`
+ - [ ] `set_to_moi` is defined for each set in `src/FileFormats/MOF/read.jl`
+ - [ ] `head_name` is defined for each set in `src/FileFormats/MOF/write.jl`
+ - [ ] A new unit test calling `_test_model_equality` is aded to
+       `test/FileFormats/MOF/MOF.jl`
+
+## Tests
+
+ - [ ] The version field in `test/FileFormats/MOF/nlp.mof.json` is updated
+
+## Documentation
+
+ - [ ] The version fields are updated in `docs/src/submodules/FileFormats/overview.md`
diff --git a/previews/PR2418/index.html b/previews/PR2418/index.html new file mode 100644 index 0000000000..412930da9e --- /dev/null +++ b/previews/PR2418/index.html @@ -0,0 +1,9 @@ + +Introduction · MathOptInterface

Introduction

Welcome to the documentation for MathOptInterface.

Note

This documentation is also available in PDF format: MathOptInterface.pdf.

What is MathOptInterface?

MathOptInterface.jl (MOI) is an abstraction layer designed to provide a unified interface to mathematical optimization solvers so that users do not need to understand multiple solver-specific APIs.

Tip

This documentation is aimed at developers writing software interfaces to solvers and modeling languages using the MathOptInterface API. If you are a user interested in solving optimization problems, we encourage you instead to use MOI through a higher-level modeling interface like JuMP or Convex.jl.

How the documentation is structured

Having a high-level overview of how this documentation is structured will help you know where to look for certain things.

  • The Tutorials section contains articles on how to use and implement the MathOptInteraface API. Look here if you want to write a model in MOI, or write an interface to a new solver.
  • The Manual contains short code-snippets that explain how to use the MOI API. Look here for more details on particular areas of MOI.
  • The Background section contains articles on the theory behind MathOptInterface. Look here if you want to understand why, rather than how.
  • The API Reference contains a complete list of functions and types that comprise the MOI API. Look here is you want to know how to use (or implement) a particular function.
  • The Submodules section contains stand-alone documentation for each of the submodules within MOI. These submodules are not required to interface a solver with MOI, but they make the job much easier.

Citing MathOptInterface

If you find MathOptInterface useful in your work, we kindly request that you cite the following paper:

@article{legat2021mathoptinterface,
+    title={{MathOptInterface}: a data structure for mathematical optimization problems},
+    author={Legat, Beno{\^\i}t and Dowson, Oscar and Garcia, Joaquim Dias and Lubin, Miles},
+    journal={INFORMS Journal on Computing},
+    year={2021},
+    doi={10.1287/ijoc.2021.1067},
+    publisher={INFORMS}
+}

A preprint of this paper is freely available.

diff --git a/previews/PR2418/manual/constraints/index.html b/previews/PR2418/manual/constraints/index.html new file mode 100644 index 0000000000..71aef98167 --- /dev/null +++ b/previews/PR2418/manual/constraints/index.html @@ -0,0 +1,22 @@ + +Constraints · MathOptInterface

Constraints

Add a constraint

Use add_constraint to add a single constraint.

julia> c = MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(2))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)

add_constraint returns a ConstraintIndex type, which is used to refer to the added constraint in other calls.

Check if a ConstraintIndex is valid using is_valid.

julia> MOI.is_valid(model, c)
+true

Use add_constraints to add a number of constraints of the same type.

julia> c = MOI.add_constraints(
+           model,
+           [x[1], x[2]],
+           [MOI.GreaterThan(0.0), MOI.GreaterThan(1.0)]
+       )
+2-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(2)

This time, a vector of ConstraintIndex are returned.

Use supports_constraint to check if the model supports adding a constraint type.

julia> MOI.supports_constraint(
+           model,
+           MOI.VariableIndex,
+           MOI.GreaterThan{Float64},
+       )
+true

Delete a constraint

Use delete to delete a constraint.

julia> MOI.delete(model, c)
+
+julia> MOI.is_valid(model, c)
+false

Constraint attributes

The following attributes are available for constraints:

Get and set these attributes using get and set.

julia> MOI.set(model, MOI.ConstraintName(), c, "con_c")
+
+julia> MOI.get(model, MOI.ConstraintName(), c)
+"con_c"

Constraints by function-set pairs

Below is a list of common constraint types and how they are represented as function-set pairs in MOI. In the notation below, $x$ is a vector of decision variables, $x_i$ is a scalar decision variable, $\alpha, \beta$ are scalar constants, $a, b$ are constant vectors, A is a constant matrix and $\mathbb{R}_+$ (resp. $\mathbb{R}_-$) is the set of non-negative (resp. non-positive) real numbers.

Linear constraints

Mathematical ConstraintMOI FunctionMOI Set
$a^Tx \le \beta$ScalarAffineFunctionLessThan
$a^Tx \ge \alpha$ScalarAffineFunctionGreaterThan
$a^Tx = \beta$ScalarAffineFunctionEqualTo
$\alpha \le a^Tx \le \beta$ScalarAffineFunctionInterval
$x_i \le \beta$VariableIndexLessThan
$x_i \ge \alpha$VariableIndexGreaterThan
$x_i = \beta$VariableIndexEqualTo
$\alpha \le x_i \le \beta$VariableIndexInterval
$Ax + b \in \mathbb{R}_+^n$VectorAffineFunctionNonnegatives
$Ax + b \in \mathbb{R}_-^n$VectorAffineFunctionNonpositives
$Ax + b = 0$VectorAffineFunctionZeros

By convention, solvers are not expected to support nonzero constant terms in the ScalarAffineFunctions the first four rows of the preceding table because they are redundant with the parameters of the sets. For example, encode $2x + 1 \le 2$ as $2x \le 1$.

Constraints with VariableIndex in LessThan, GreaterThan, EqualTo, or Interval sets have a natural interpretation as variable bounds. As such, it is typically not natural to impose multiple lower- or upper-bounds on the same variable, and the solver interfaces will throw respectively LowerBoundAlreadySet or UpperBoundAlreadySet.

Moreover, adding two VariableIndex constraints on the same variable with the same set is impossible because they share the same index as it is the index of the variable, see ConstraintIndex.

It is natural, however, to impose upper- and lower-bounds separately as two different constraints on a single variable. The difference between imposing bounds by using a single Interval constraint and by using separate LessThan and GreaterThan constraints is that the latter will allow the solver to return separate dual multipliers for the two bounds, while the former will allow the solver to return only a single dual for the interval constraint.

Conic constraints

Mathematical ConstraintMOI FunctionMOI Set
$\lVert Ax + b\rVert_2 \le c^Tx + d$VectorAffineFunctionSecondOrderCone
$y \ge \lVert x \rVert_2$VectorOfVariablesSecondOrderCone
$2yz \ge \lVert x \rVert_2^2, y,z \ge 0$VectorOfVariablesRotatedSecondOrderCone
$(a_1^Tx + b_1,a_2^Tx + b_2,a_3^Tx + b_3) \in \mathcal{E}$VectorAffineFunctionExponentialCone
$A(x) \in \mathcal{S}_+$VectorAffineFunctionPositiveSemidefiniteConeTriangle
$B(x) \in \mathcal{S}_+$VectorAffineFunctionPositiveSemidefiniteConeSquare
$x \in \mathcal{S}_+$VectorOfVariablesPositiveSemidefiniteConeTriangle
$x \in \mathcal{S}_+$VectorOfVariablesPositiveSemidefiniteConeSquare

where $\mathcal{E}$ is the exponential cone (see ExponentialCone), $\mathcal{S}_+$ is the set of positive semidefinite symmetric matrices, $A$ is an affine map that outputs symmetric matrices and $B$ is an affine map that outputs square matrices.

Quadratic constraints

Mathematical ConstraintMOI FunctionMOI Set
$\frac{1}{2}x^TQx + a^Tx + b \ge 0$ScalarQuadraticFunctionGreaterThan
$\frac{1}{2}x^TQx + a^Tx + b \le 0$ScalarQuadraticFunctionLessThan
$\frac{1}{2}x^TQx + a^Tx + b = 0$ScalarQuadraticFunctionEqualTo
Bilinear matrix inequalityVectorQuadraticFunctionPositiveSemidefiniteCone...
Note

For more details on the internal format of the quadratic functions see ScalarQuadraticFunction or VectorQuadraticFunction.

Discrete and logical constraints

Mathematical ConstraintMOI FunctionMOI Set
$x_i \in \mathbb{Z}$VariableIndexInteger
$x_i \in \{0,1\}$VariableIndexZeroOne
$x_i \in \{0\} \cup [l,u]$VariableIndexSemicontinuous
$x_i \in \{0\} \cup \{l,l+1,\ldots,u-1,u\}$VariableIndexSemiinteger
At most one component of $x$ can be nonzeroVectorOfVariablesSOS1
At most two components of $x$ can be nonzero, and if so they must be adjacent componentsVectorOfVariablesSOS2
$y = 1 \implies a^T x \in S$VectorAffineFunctionIndicator

JuMP mapping

The following bullet points show examples of how JuMP constraints are translated into MOI function-set pairs:

  • @constraint(m, 2x + y <= 10) becomes ScalarAffineFunction-in-LessThan
  • @constraint(m, 2x + y >= 10) becomes ScalarAffineFunction-in-GreaterThan
  • @constraint(m, 2x + y == 10) becomes ScalarAffineFunction-in-EqualTo
  • @constraint(m, 0 <= 2x + y <= 10) becomes ScalarAffineFunction-in-Interval
  • @constraint(m, 2x + y in ArbitrarySet()) becomes ScalarAffineFunction-in-ArbitrarySet.

Variable bounds are handled in a similar fashion:

  • @variable(m, x <= 1) becomes VariableIndex-in-LessThan
  • @variable(m, x >= 1) becomes VariableIndex-in-GreaterThan

One notable difference is that a variable with an upper and lower bound is translated into two constraints, rather than an interval, that is:

  • @variable(m, 0 <= x <= 1) becomes VariableIndex-in-LessThan and VariableIndex-in-GreaterThan.
diff --git a/previews/PR2418/manual/models/index.html b/previews/PR2418/manual/models/index.html new file mode 100644 index 0000000000..768c78a925 --- /dev/null +++ b/previews/PR2418/manual/models/index.html @@ -0,0 +1,2 @@ + +Models · MathOptInterface

Models

The most significant part of MOI is the definition of the model API that is used to specify an instance of an optimization problem (for example, by adding variables and constraints). Objects that implement the model API must inherit from the ModelLike abstract type.

Notably missing from the model API is the method to solve an optimization problem. ModelLike objects may store an instance (for example, in memory or backed by a file format) without being linked to a particular solver. In addition to the model API, MOI defines AbstractOptimizer and provides methods to solve the model and interact with solutions. See the Solutions section for more details.

Info

Throughout the rest of the manual, model is used as a generic ModelLike, and optimizer is used as a generic AbstractOptimizer.

Tip

MOI does not export functions, but for brevity we often omit qualifying names with the MOI module. Best practice is to have

import MathOptInterface as MOI

and prefix all MOI methods with MOI. in user code. If a name is also available in base Julia, we always explicitly use the module prefix, for example, with MOI.get.

Attributes

Attributes are properties of the model that can be queried and modified. These include constants such as the number of variables in a model NumberOfVariables), and properties of variables and constraints such as the name of a variable (VariableName).

There are four types of attributes:

Some attributes are values that can be queried by the user but not modified, while other attributes can be modified by the user.

All interactions with attributes occur through the get and set functions.

Consult the docstrings of each attribute for information on what it represents.

ModelLike API

The following attributes are available:

AbstractOptimizer API

The following attributes are available:

diff --git a/previews/PR2418/manual/modification/index.html b/previews/PR2418/manual/modification/index.html new file mode 100644 index 0000000000..47a94f4b2f --- /dev/null +++ b/previews/PR2418/manual/modification/index.html @@ -0,0 +1,151 @@ + +Problem modification · MathOptInterface

Problem modification

In addition to adding and deleting constraints and variables, MathOptInterface supports modifying, in-place, coefficients in the constraints and the objective function of a model.

These modifications can be grouped into two categories:

  • modifications which replace the set of function of a constraint with a new set or function
  • modifications which change, in-place, a component of a function
Warning

Some ModelLike objects do not support problem modification.

Modify the set of a constraint

Use set and ConstraintSet to modify the set of a constraint by replacing it with a new instance of the same type.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.EqualTo(2.0));
+
+julia> MOI.get(model, MOI.ConstraintSet(), c) == MOI.EqualTo(2.0)
+true

However, the following will fail as the new set is of a different type to the original set:

julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan(2.0))
+ERROR: [...]

Special cases: set transforms

If our constraint is an affine inequality, then this corresponds to modifying the right-hand side of a constraint in linear programming.

In some special cases, solvers may support efficiently changing the set of a constraint (for example, from LessThan to GreaterThan). For these cases, MathOptInterface provides the transform method.

The transform function returns a new constraint index, and the old constraint index (that is, c) is no longer valid.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.LessThan(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}(1)
+
+julia> new_c = MOI.transform(model, c, MOI.GreaterThan(2.0));
+
+julia> MOI.is_valid(model, c)
+false
+
+julia> MOI.is_valid(model, new_c)
+true
Note

transform cannot be called with a set of the same type. Use set instead.

Modify the function of a constraint

Use set and ConstraintFunction to modify the function of a constraint by replacing it with a new instance of the same type.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 1.0);
+
+julia> MOI.set(model, MOI.ConstraintFunction(), c, new_f);
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

However, the following will fail as the new function is of a different type to the original function:

julia> MOI.set(model, MOI.ConstraintFunction(), c, x)
+ERROR: [...]

Modify constant term in a scalar function

Use modify and ScalarConstantChange to modify the constant term in a ScalarAffineFunction or ScalarQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.modify(model, c, MOI.ScalarConstantChange(1.0));
+
+julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 1.0);
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

ScalarConstantChange can also be used to modify the objective function by passing an instance of ObjectiveFunction:

julia> MOI.set(
+           model,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+           new_f,
+       );
+
+julia> MOI.modify(
+           model,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+           MOI.ScalarConstantChange(-1.0)
+       );
+
+julia> MOI.get(
+           model,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+       ) ≈ MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], -1.0)
+true

Modify constant terms in a vector function

Use modify and VectorConstantChange to modify the constant vector in a VectorAffineFunction or VectorQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.VectorAffineFunction([
+                   MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
+                   MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
+               ],
+               [0.0, 0.0],
+           ),
+           MOI.Nonnegatives(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.modify(model, c, MOI.VectorConstantChange([3.0, 4.0]));
+
+julia> new_f = MOI.VectorAffineFunction(
+           [
+        MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
+        MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
+           ],
+           [3.0, 4.0],
+       );
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

Modify affine coefficients in a scalar function

Use modify and ScalarCoefficientChange to modify the affine coefficient of a ScalarAffineFunction or ScalarQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.modify(model, c, MOI.ScalarCoefficientChange(x, 2.0));
+
+julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 0.0);
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

ScalarCoefficientChange can also be used to modify the objective function by passing an instance of ObjectiveFunction.

Modify quadratic coefficients in a scalar function

Use modify and ScalarQuadraticCoefficientChange to modify the quadratic coefficient of a ScalarQuadraticFunction.

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variables(model, 2);
+
+julia> c = MOI.add_constraint(
+           model,
+           1.0 * x[1] * x[1] + 2.0 * x[1] * x[2],
+           MOI.EqualTo(1.0),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadraticFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
+
+julia> MOI.modify(
+           model,
+           c,
+           MOI.ScalarQuadraticCoefficientChange(x[1], x[1], 3.0),
+       );
+
+julia> MOI.modify(
+           model,
+           c,
+           MOI.ScalarQuadraticCoefficientChange(x[1], x[2], 4.0),
+       );
+
+julia> new_f = 1.5 * x[1] * x[1] + 4.0 * x[1] * x[2];
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true

ScalarQuadraticCoefficientChange can also be used to modify the objective function by passing an instance of ObjectiveFunction.

Modify affine coefficients in a vector function

Use modify and MultirowChange to modify a vector of affine coefficients in a VectorAffineFunction or a VectorQuadraticFunction.

julia> c = MOI.add_constraint(
+           model,
+           MOI.VectorAffineFunction([
+                   MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
+                   MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
+               ],
+               [0.0, 0.0],
+           ),
+           MOI.Nonnegatives(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.modify(model, c, MOI.MultirowChange(x, [(1, 3.0), (2, 4.0)]));
+
+julia> new_f = MOI.VectorAffineFunction(
+           [
+        MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x)),
+        MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(4.0, x)),
+           ],
+           [0.0, 0.0],
+       );
+
+julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
+true
diff --git a/previews/PR2418/manual/solutions/index.html b/previews/PR2418/manual/solutions/index.html new file mode 100644 index 0000000000..f8451a4724 --- /dev/null +++ b/previews/PR2418/manual/solutions/index.html @@ -0,0 +1,35 @@ + +Solutions · MathOptInterface

Solutions

Solving and retrieving the results

Once an optimizer is loaded with the objective function and all of the constraints, we can ask the solver to solve the model by calling optimize!.

MOI.optimize!(optimizer)

Why did the solver stop?

The optimization procedure may stop for a number of reasons. The TerminationStatus attribute of the optimizer returns a TerminationStatusCode object which explains why the solver stopped.

The termination statuses distinguish between proofs of optimality, infeasibility, local convergence, limits, and termination because of something unexpected like invalid problem data or failure to converge.

A typical usage of the TerminationStatus attribute is as follows:

status = MOI.get(optimizer, TerminationStatus())
+if status == MOI.OPTIMAL
+    # Ok, we solved the problem!
+else
+    # Handle other cases.
+end

After checking the TerminationStatus, check ResultCount. This attribute returns the number of results that the solver has available to return. A result is defined as a primal-dual pair, but either the primal or the dual may be missing from the result. While the OPTIMAL termination status normally implies that at least one result is available, other statuses do not. For example, in the case of infeasibility, a solver may return no result or a proof of infeasibility. The ResultCount attribute distinguishes between these two cases.

Primal solutions

Use the PrimalStatus optimizer attribute to return a ResultStatusCode describing the status of the primal solution.

Common returns are described below in the Common status situations section.

Query the primal solution using the VariablePrimal and ConstraintPrimal attributes.

Query the objective function value using the ObjectiveValue attribute.

Dual solutions

Warning

See Duality for a discussion of the MOI conventions for primal-dual pairs and certificates.

Use the DualStatus optimizer attribute to return a ResultStatusCode describing the status of the dual solution.

Query the dual solution using the ConstraintDual attribute.

Query the dual objective function value using the DualObjectiveValue attribute.

Common status situations

The sections below describe how to interpret typical or interesting status cases for three common classes of solvers. The example cases are illustrative, not comprehensive. Solver wrappers may provide additional information on how the solver's statuses map to MOI statuses.

Info

* in the tables indicate that multiple different values are possible.

Primal-dual convex solver

Linear programming and conic optimization solvers fall into this category.

What happened?TerminationStatusResultCountPrimalStatusDualStatus
Proved optimalityOPTIMAL1FEASIBLE_POINTFEASIBLE_POINT
Proved infeasibleINFEASIBLE1NO_SOLUTIONINFEASIBILITY_CERTIFICATE
Optimal within relaxed tolerancesALMOST_OPTIMAL1FEASIBLE_POINTFEASIBLE_POINT
Optimal within relaxed tolerancesALMOST_OPTIMAL1ALMOST_FEASIBLE_POINTALMOST_FEASIBLE_POINT
Detected an unbounded ray of the primalDUAL_INFEASIBLE1INFEASIBILITY_CERTIFICATENO_SOLUTION
StallSLOW_PROGRESS1**

Global branch-and-bound solvers

Mixed-integer programming solvers fall into this category.

What happened?TerminationStatusResultCountPrimalStatusDualStatus
Proved optimalityOPTIMAL1FEASIBLE_POINTNO_SOLUTION
Presolve detected infeasibility or unboundednessINFEASIBLE_OR_UNBOUNDED0NO_SOLUTIONNO_SOLUTION
Proved infeasibilityINFEASIBLE0NO_SOLUTIONNO_SOLUTION
Timed out (no solution)TIME_LIMIT0NO_SOLUTIONNO_SOLUTION
Timed out (with a solution)TIME_LIMIT1FEASIBLE_POINTNO_SOLUTION
CPXMIP_OPTIMAL_INFEASALMOST_OPTIMAL1INFEASIBLE_POINTNO_SOLUTION
Info

CPXMIP_OPTIMAL_INFEAS is a CPLEX status that indicates that a preprocessed problem was solved to optimality, but the solver was unable to recover a feasible solution to the original problem. Handling this status was one of the motivating drivers behind the design of MOI.

Local search solvers

Nonlinear programming solvers fall into this category. It also includes non-global tree search solvers like Juniper.

What happened?TerminationStatusResultCountPrimalStatusDualStatus
Converged to a stationary pointLOCALLY_SOLVED1FEASIBLE_POINTFEASIBLE_POINT
Completed a non-global tree search (with a solution)LOCALLY_SOLVED1FEASIBLE_POINTFEASIBLE_POINT
Converged to an infeasible pointLOCALLY_INFEASIBLE1INFEASIBLE_POINT*
Completed a non-global tree search (no solution found)LOCALLY_INFEASIBLE0NO_SOLUTIONNO_SOLUTION
Iteration limitITERATION_LIMIT1**
Diverging iteratesNORM_LIMIT or OBJECTIVE_LIMIT1**

Querying solution attributes

Some solvers will not implement every solution attribute. Therefore, a call like MOI.get(model, MOI.SolveTimeSec()) may throw an UnsupportedAttribute error.

If you need to write code that is agnostic to the solver (for example, you are writing a library that an end-user passes their choice of solver to), you can work-around this problem using a try-catch:

function get_solve_time(model)
+    try
+        return MOI.get(model, MOI.SolveTimeSec())
+    catch err
+        if err isa MOI.UnsupportedAttribute
+            return NaN  # Solver doesn't support. Return a placeholder value.
+        end
+        rethrow(err)  # Something else went wrong. Rethrow the error
+    end
+end

If, after careful profiling, you find that the try-catch is taking a significant portion of your runtime, you can improve performance by caching the result of the try-catch:

mutable struct CachedSolveTime{M}
+    model::M
+    supports_solve_time::Bool
+    CachedSolveTime(model::M) where {M} = new(model, true)
+end
+
+function get_solve_time(model::CachedSolveTime)
+    if !model.supports_solve_time
+        return NaN
+    end
+    try
+        return MOI.get(model, MOI.SolveTimeSec())
+    catch err
+        if err isa MOI.UnsupportedAttribute
+            model.supports_solve_time = false
+            return NaN
+        end
+        rethrow(err)  # Something else went wrong. Rethrow the error
+    end
+end
diff --git a/previews/PR2418/manual/standard_form/index.html b/previews/PR2418/manual/standard_form/index.html new file mode 100644 index 0000000000..1e918a8b79 --- /dev/null +++ b/previews/PR2418/manual/standard_form/index.html @@ -0,0 +1,6 @@ + +Standard form problem · MathOptInterface

Standard form problem

MathOptInterface represents optimization problems in the standard form:

\[\begin{align} + & \min_{x \in \mathbb{R}^n} & f_0(x) + \\ + & \;\;\text{s.t.} & f_i(x) & \in \mathcal{S}_i & i = 1 \ldots m +\end{align}\]

where:

  • the functions $f_0, f_1, \ldots, f_m$ are specified by AbstractFunction objects
  • the sets $\mathcal{S}_1, \ldots, \mathcal{S}_m$ are specified by AbstractSet objects
Tip

For more information on this standard form, read our paper.

MOI defines some commonly used functions and sets, but the interface is extensible to other sets recognized by the solver.

Functions

The function types implemented in MathOptInterface.jl are:

FunctionDescription
VariableIndex$x_j$, the projection onto a single coordinate defined by a variable index $j$.
VectorOfVariablesThe projection onto multiple coordinates (that is, extracting a sub-vector).
ScalarAffineFunction$a^T x + b$, where $a$ is a vector and $b$ scalar.
ScalarNonlinearFunction$f(x)$, where $f$ is a nonlinear function.
VectorAffineFunction$A x + b$, where $A$ is a matrix and $b$ is a vector.
ScalarQuadraticFunction$\frac{1}{2} x^T Q x + a^T x + b$, where $Q$ is a symmetric matrix, $a$ is a vector, and $b$ is a constant.
VectorQuadraticFunctionA vector of scalar-valued quadratic functions.
VectorNonlinearFunction$f(x)$, where $f$ is a vector-valued nonlinear function.

Extensions for nonlinear programming are present but not yet well documented.

One-dimensional sets

The one-dimensional set types implemented in MathOptInterface.jl are:

SetDescription
LessThan(u)$(-\infty, u]$
GreaterThan(l)$[l, \infty)$
EqualTo(v)$\{v\}$
Interval(l, u)$[l, u]$
Integer()$\mathbb{Z}$
ZeroOne()$\{ 0, 1 \}$
Semicontinuous(l, u)$\{ 0\} \cup [l, u]$
Semiinteger(l, u)$\{ 0\} \cup \{l,l+1,\ldots,u-1,u\}$

Vector cones

The vector-valued set types implemented in MathOptInterface.jl are:

SetDescription
Reals(d)$\mathbb{R}^{d}$
Zeros(d)$0^{d}$
Nonnegatives(d)$\{ x \in \mathbb{R}^{d} : x \ge 0 \}$
Nonpositives(d)$\{ x \in \mathbb{R}^{d} : x \le 0 \}$
SecondOrderCone(d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \lVert x \rVert_2 \}$
RotatedSecondOrderCone(d)$\{ (t,u,x) \in \mathbb{R}^{d} : 2tu \ge \lVert x \rVert_2^2, t \ge 0,u \ge 0 \}$
ExponentialCone()$\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}$
DualExponentialCone()$\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le \exp(1) w, u < 0 \}$
GeometricMeanCone(d)$\{ (t,x) \in \mathbb{R}^{1+n} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}$ where $n$ is $d - 1$
PowerCone(α)$\{ (x,y,z) \in \mathbb{R}^3 : x^{\alpha} y^{1-\alpha} \ge |z|, x \ge 0,y \ge 0 \}$
DualPowerCone(α)$\{ (u,v,w) \in \mathbb{R}^3 : \left(\frac{u}{\alpha}\right)^{\alpha}\left(\frac{v}{1-\alpha}\right)^{1-\alpha} \ge |w|, u,v \ge 0 \}$
NormOneCone(d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \sum_i \lvert x_i \rvert \}$
NormInfinityCone(d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \max_i \lvert x_i \rvert \}$
RelativeEntropyCone(d)$\{ (u, v, w) \in \mathbb{R}^{d} : u \ge \sum_i w_i \log (\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}$
HyperRectangle(l, u)$\{x \in \bar{\mathbb{R}}^d: x_i \in [l_i, u_i] \forall i=1,\ldots,d\}$
NormCone(p, d)$\{ (t,x) \in \mathbb{R}^{d} : t \ge \left(\sum\limits_i \lvert x_i \rvert^p\right)^{\frac{1}{p}} \}$

Matrix cones

The matrix-valued set types implemented in MathOptInterface.jl are:

SetDescription
RootDetConeTriangle(d)$\{ (t,X) \in \mathbb{R}^{1+d(1+d)/2} : t \le \det(X)^{1/d}, X \mbox{ is the upper triangle of a PSD matrix} \}$
RootDetConeSquare(d)$\{ (t,X) \in \mathbb{R}^{1+d^2} : t \le \det(X)^{1/d}, X \mbox{ is a PSD matrix} \}$
PositiveSemidefiniteConeTriangle(d)$\{ X \in \mathbb{R}^{d(d+1)/2} : X \mbox{ is the upper triangle of a PSD matrix} \}$
PositiveSemidefiniteConeSquare(d)$\{ X \in \mathbb{R}^{d^2} : X \mbox{ is a PSD matrix} \}$
LogDetConeTriangle(d)$\{ (t,u,X) \in \mathbb{R}^{2+d(1+d)/2} : t \le u\log(\det(X/u)), X \mbox{ is the upper triangle of a PSD matrix}, u > 0 \}$
LogDetConeSquare(d)$\{ (t,u,X) \in \mathbb{R}^{2+d^2} : t \le u \log(\det(X/u)), X \mbox{ is a PSD matrix}, u > 0 \}$
NormSpectralCone(r, c)$\{ (t, X) \in \mathbb{R}^{1 + r \times c} : t \ge \sigma_1(X), X \mbox{ is a } r\times c\mbox{ matrix} \}$
NormNuclearCone(r, c)$\{ (t, X) \in \mathbb{R}^{1 + r \times c} : t \ge \sum_i \sigma_i(X), X \mbox{ is a } r\times c\mbox{ matrix} \}$
HermitianPositiveSemidefiniteConeTriangle(d)The cone of Hermitian positive semidefinite matrices, with
side_dimension rows and columns.
Scaled(S)The set S scaled so that Utilities.set_dot corresponds to LinearAlgebra.dot

Some of these cones can take two forms: XXXConeTriangle and XXXConeSquare.

In XXXConeTriangle sets, the matrix is assumed to be symmetric, and the elements are provided by a vector, in which the entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row).

In XXXConeSquare sets, the entries of the matrix are given column by column (or equivalently, row by row), and the matrix is constrained to be symmetric. As an example, given a 2-by-2 matrix of variables X and a one-dimensional variable t, we can specify a root-det constraint as [t, X11, X12, X22] ∈ RootDetConeTriangle or [t, X11, X12, X21, X22] ∈ RootDetConeSquare.

We provide both forms to enable flexibility for solvers who may natively support one or the other. Transformations between XXXConeTriangle and XXXConeSquare are handled by bridges, which removes the chance of conversion mistakes by users or solver developers.

Multi-dimensional sets with combinatorial structure

Other sets are vector-valued, with a particular combinatorial structure. Read their docstrings for more information on how to interpret them.

SetDescription
SOS1A Special Ordered Set (SOS) of Type I
SOS2A Special Ordered Set (SOS) of Type II
IndicatorA set to specify an indicator constraint
ComplementsA set to specify a mixed complementarity constraint
AllDifferentThe all_different global constraint
BinPackingThe bin_packing global constraint
CircuitThe circuit global constraint
CountAtLeastThe at_least global constraint
CountBelongsThe nvalue global constraint
CountDistinctThe distinct global constraint
CountGreaterThanThe count_gt global constraint
CumulativeThe cumulative global constraint
PathThe path global constraint
TableThe table global constraint
diff --git a/previews/PR2418/manual/variables/index.html b/previews/PR2418/manual/variables/index.html new file mode 100644 index 0000000000..1f1b25da91 --- /dev/null +++ b/previews/PR2418/manual/variables/index.html @@ -0,0 +1,13 @@ + +Variables · MathOptInterface

Variables

Add a variable

Use add_variable to add a single variable.

julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)

add_variable returns a VariableIndex type, which is used to refer to the added variable in other calls.

Check if a VariableIndex is valid using is_valid.

julia> MOI.is_valid(model, x)
+true

Use add_variables to add a number of variables.

julia> y = MOI.add_variables(model, 2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
Warning

The integer does not necessarily correspond to the column inside an optimizer.

Delete a variable

Delete a variable using delete.

julia> MOI.delete(model, x)
+
+julia> MOI.is_valid(model, x)
+false
Warning

Not all ModelLike models support deleting variables. A DeleteNotAllowed error is thrown if this is not supported.

Variable attributes

The following attributes are available for variables:

Get and set these attributes using get and set.

julia> MOI.set(model, MOI.VariableName(), x, "var_x")
+
+julia> MOI.get(model, MOI.VariableName(), x)
+"var_x"
diff --git a/previews/PR2418/reference/callbacks/index.html b/previews/PR2418/reference/callbacks/index.html new file mode 100644 index 0000000000..6d1dcd3fea --- /dev/null +++ b/previews/PR2418/reference/callbacks/index.html @@ -0,0 +1,32 @@ + +Callbacks · MathOptInterface

Callbacks

MathOptInterface.AbstractCallbackType
abstract type AbstractCallback <: AbstractModelAttribute end

Abstract type for a model attribute representing a callback function. The value set to subtypes of AbstractCallback is a function that may be called during optimize!. As optimize! is in progress, the result attributes (that is, the attributes attr such that is_set_by_optimize(attr)) may not be accessible from the callback, hence trying to get result attributes might throw a OptimizeInProgress error.

At most one callback of each type can be registered. If an optimizer already has a function for a callback type, and the user registers a new function, then the old one is replaced.

The value of the attribute should be a function taking only one argument, commonly called callback_data, that can be used for instance in LazyConstraintCallback, HeuristicCallback and UserCutCallback.

source
MathOptInterface.submitFunction
submit(
+    optimizer::AbstractOptimizer,
+    sub::AbstractSubmittable,
+    values...,
+)::Nothing

Submit values to the submittable sub of the optimizer optimizer.

An UnsupportedSubmittable error is thrown if model does not support the attribute attr (see supports) and a SubmitNotAllowed error is thrown if it supports the submittable sub but it cannot be submitted.

source

Attributes

MathOptInterface.CallbackNodeStatusCodeType
CallbackNodeStatusCode

An Enum of possible return values from calling get with CallbackNodeStatus.

Values

Possible values are:

source

Lazy constraints

MathOptInterface.LazyConstraintCallbackType
LazyConstraintCallback() <: AbstractCallback

The callback can be used to reduce the feasible set given the current primal solution by submitting a LazyConstraint. For instance, it may be called at an incumbent of a mixed-integer problem. Note that there is no guarantee that the callback is called at every feasible primal solution.

The current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
+MOI.set(optimizer, MOI.LazyConstraintCallback(), callback_data -> begin
+    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
+    if # should add a lazy constraint
+        func = # computes function
+        set = # computes set
+        MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)
+    end
+end)
source
MathOptInterface.LazyConstraintType
LazyConstraint(callback_data)

Lazy constraint func-in-set submitted as func, set. The optimal solution returned by VariablePrimal will satisfy all lazy constraints that have been submitted.

This can be submitted only from the LazyConstraintCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the feasible solution callback.

Examples

Suppose x and y are VariableIndexs of optimizer. To add a LazyConstraint for 2x + 3y <= 1, write

func = 2.0x + 3.0y
+set = MOI.LessThan(1.0)
+MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)

inside a LazyConstraintCallback of data callback_data.

source

User cuts

MathOptInterface.UserCutCallbackType
UserCutCallback() <: AbstractCallback

The callback can be used to submit UserCut given the current primal solution. For instance, it may be called at fractional (that is, non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is not guarantee that the callback is called everytime the solver has an infeasible solution.

The infeasible solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
+MOI.set(optimizer, MOI.UserCutCallback(), callback_data -> begin
+    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
+    if # can find a user cut
+        func = # computes function
+        set = # computes set
+        MOI.submit(optimizer, MOI.UserCut(callback_data), func, set)
+    end
+end
source
MathOptInterface.UserCutType
UserCut(callback_data)

Constraint func-to-set suggested to help the solver detect the solution given by CallbackVariablePrimal as infeasible. The cut is submitted as func, set. Typically CallbackVariablePrimal will violate integrality constraints, and a cut would be of the form ScalarAffineFunction-in-LessThan or ScalarAffineFunction-in-GreaterThan. Note that, as opposed to LazyConstraint, the provided constraint cannot modify the feasible set, the constraint should be redundant, for example, it may be a consequence of affine and integrality constraints.

This can be submitted only from the UserCutCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the infeasible solution callback.

Note that the solver may silently ignore the provided constraint.

source

Heuristic solutions

MathOptInterface.HeuristicCallbackType
HeuristicCallback() <: AbstractCallback

The callback can be used to submit HeuristicSolution given the current primal solution. For example, it may be called at fractional (that is, non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is no guarantee that the callback is called every time the solver has an infeasible solution.

The current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
+MOI.set(optimizer, MOI.HeuristicCallback(), callback_data -> begin
+    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
+    if # can find a heuristic solution
+        values = # computes heuristic solution
+        MOI.submit(optimizer, MOI.HeuristicSolution(callback_data), x,
+                   values)
+    end
+end
source
MathOptInterface.HeuristicSolutionType
HeuristicSolution(callback_data)

Heuristically obtained feasible solution. The solution is submitted as variables, values where values[i] gives the value of variables[i], similarly to set. The submit call returns a HeuristicSolutionStatus indicating whether the provided solution was accepted or rejected.

This can be submitted only from the HeuristicCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the heuristic callback.

Some solvers require a complete solution, others only partial solutions.

source
diff --git a/previews/PR2418/reference/constraints/index.html b/previews/PR2418/reference/constraints/index.html new file mode 100644 index 0000000000..2a39947cb3 --- /dev/null +++ b/previews/PR2418/reference/constraints/index.html @@ -0,0 +1,12 @@ + +Constraints · MathOptInterface

Constraints

Types

MathOptInterface.ConstraintIndexType
ConstraintIndex{F, S}

A type-safe wrapper for Int64 for use in referencing F-in-S constraints in a model. The parameter F is the type of the function in the constraint, and the parameter S is the type of set in the constraint. To allow for deletion, indices need not be consecutive. Indices within a constraint type (that is, F-in-S) must be unique, but non-unique indices across different constraint types are allowed. If F is VariableIndex then the index is equal to the index of the variable. That is for an index::ConstraintIndex{VariableIndex}, we always have

index.value == MOI.get(model, MOI.ConstraintFunction(), index).value
source

Functions

MathOptInterface.is_validMethod
is_valid(model::ModelLike, index::Index)::Bool

Return a Bool indicating whether this index refers to a valid object in the model model.

source
MathOptInterface.add_constraintFunction
add_constraint(model::ModelLike, func::F, set::S)::ConstraintIndex{F,S} where {F,S}

Add the constraint $f(x) \in \mathcal{S}$ where $f$ is defined by func, and $\mathcal{S}$ is defined by set.

add_constraint(model::ModelLike, v::VariableIndex, set::S)::ConstraintIndex{VariableIndex,S} where {S}
+add_constraint(model::ModelLike, vec::Vector{VariableIndex}, set::S)::ConstraintIndex{VectorOfVariables,S} where {S}

Add the constraint $v \in \mathcal{S}$ where $v$ is the variable (or vector of variables) referenced by v and $\mathcal{S}$ is defined by set.

source
MOI.add_constraint(map::Map, vi::MOI.VariableIndex, set::MOI.AbstractScalarSet)

Record that a constraint vi-in-set is added and throws if a lower or upper bound is set by this constraint and such bound has already been set for vi.

source
MathOptInterface.add_constraintsFunction
add_constraints(model::ModelLike, funcs::Vector{F}, sets::Vector{S})::Vector{ConstraintIndex{F,S}} where {F,S}

Add the set of constraints specified by each function-set pair in funcs and sets. F and S should be concrete types. This call is equivalent to add_constraint.(model, funcs, sets) but may be more efficient.

source
MathOptInterface.transformFunction

Transform Constraint Set

transform(model::ModelLike, c::ConstraintIndex{F,S1}, newset::S2)::ConstraintIndex{F,S2}

Replace the set in constraint c with newset. The constraint index c will no longer be valid, and the function returns a new constraint index with the correct type.

Solvers may only support a subset of constraint transforms that they perform efficiently (for example, changing from a LessThan to GreaterThan set). In addition, set modification (where S1 = S2) should be performed via the modify function.

Typically, the user should delete the constraint and add a new one.

Examples

If c is a ConstraintIndex{ScalarAffineFunction{Float64},LessThan{Float64}},

c2 = transform(model, c, GreaterThan(0.0))
+transform(model, c, LessThan(0.0)) # errors
source
MathOptInterface.supports_constraintFunction
MOI.supports_constraint(
+    BT::Type{<:AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.

Implementation notes

  • This method depends only on the type of the inputs, not the runtime values.
  • There is a default fallback, so you need only implement this method for constraint types that the bridge implements.
source
supports_constraint(
+    model::ModelLike,
+    ::Type{F},
+    ::Type{S},
+)::Bool where {F<:AbstractFunction,S<:AbstractSet}

Return a Bool indicating whether model supports F-in-S constraints, that is, copy_to(model, src) does not throw UnsupportedConstraint when src contains F-in-S constraints. If F-in-S constraints are only not supported in specific circumstances, for example, F-in-S constraints cannot be combined with another type of constraint, it should still return true.

source

Attributes

MathOptInterface.ConstraintNameType
ConstraintName()

A constraint attribute for a string identifying the constraint.

It is valid for constraints variables to have the same name; however, constraints with duplicate names cannot be looked up using get, regardless of whether they have the same F-in-S type.

ConstraintName has a default value of "" if not set.

Notes

You should not implement ConstraintName for VariableIndex constraints.

source
MathOptInterface.ConstraintPrimalType
ConstraintPrimal(result_index::Int = 1)

A constraint attribute for the assignment to some constraint's primal value in result result_index.

If the constraint is f(x) in S, then in most cases the ConstraintPrimal is the value of f, evaluated at the corresponding VariablePrimal solution.

However, some conic solvers reformulate b - Ax in S to s = b - Ax, s in S. These solvers may return the value of s for ConstraintPrimal, rather than b - Ax. (Although these are constrained by an equality constraint, due to numerical tolerances they may not be identical.)

If the solver does not have a primal value for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintPrimal attribute.

If result_index is omitted, it is 1 by default. See ResultCount for information on how the results are ordered.

source
MathOptInterface.ConstraintDualType
ConstraintDual(result_index::Int = 1)

A constraint attribute for the assignment to some constraint's dual value in result result_index. If result_index is omitted, it is 1 by default.

If the solver does not have a dual value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the ConstraintDual attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.ConstraintBasisStatusType
ConstraintBasisStatus(result_index::Int = 1)

A constraint attribute for the BasisStatusCode of some constraint in result result_index, with respect to an available optimal solution basis. If result_index is omitted, it is 1 by default.

If the solver does not have a basis statue for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintBasisStatus attribute.

See ResultCount for information on how the results are ordered.

Notes

For the basis status of a variable, query VariableBasisStatus.

ConstraintBasisStatus does not apply to VariableIndex constraints. You can infer the basis status of a VariableIndex constraint by looking at the result of VariableBasisStatus.

source
MathOptInterface.ConstraintFunctionType
ConstraintFunction()

A constraint attribute for the AbstractFunction object used to define the constraint.

It is guaranteed to be equivalent but not necessarily identical to the function provided by the user.

source
MathOptInterface.CanonicalConstraintFunctionType
CanonicalConstraintFunction()

A constraint attribute for a canonical representation of the AbstractFunction object used to define the constraint.

Getting this attribute is guaranteed to return a function that is equivalent but not necessarily identical to the function provided by the user.

By default, MOI.get(model, MOI.CanonicalConstraintFunction(), ci) fallbacks to MOI.Utilities.canonical(MOI.get(model, MOI.ConstraintFunction(), ci)). However, if model knows that the constraint function is canonical then it can implement a specialized method that directly return the function without calling Utilities.canonical. Therefore, the value returned cannot be assumed to be a copy of the function stored in model. Moreover, Utilities.Model checks with Utilities.is_canonical whether the function stored internally is already canonical and if it's the case, then it returns the function stored internally instead of a copy.

source
MathOptInterface.BasisStatusCodeType
BasisStatusCode

An Enum of possible values for the ConstraintBasisStatus and VariableBasisStatus attributes, explaining the status of a given element with respect to an optimal solution basis.

Notes

  • NONBASIC_AT_LOWER and NONBASIC_AT_UPPER should be used only for

constraints with the Interval set. In this case, they are necessary to distinguish which side of the constraint is active. One-sided constraints (for example, LessThan and GreaterThan) should use NONBASIC instead of the NONBASIC_AT_* values. This restriction does not apply to VariableBasisStatus, which should return NONBASIC_AT_* regardless of whether the alternative bound exists.

  • In linear programs, SUPER_BASIC occurs when a variable with no bounds is not

in the basis.

Values

Possible values are:

source
diff --git a/previews/PR2418/reference/errors/index.html b/previews/PR2418/reference/errors/index.html new file mode 100644 index 0000000000..6759066b8d --- /dev/null +++ b/previews/PR2418/reference/errors/index.html @@ -0,0 +1,48 @@ + +Errors · MathOptInterface

Errors

When an MOI call fails on a model, precise errors should be thrown when possible instead of simply calling error with a message. The docstrings for the respective methods describe the errors that the implementation should throw in certain situations. This error-reporting system allows code to distinguish between internal errors (that should be shown to the user) and unsupported operations which may have automatic workarounds.

When an invalid index is used in an MOI call, an InvalidIndex is thrown:

When an invalid result index is used to retrieve an attribute, a ResultIndexBoundsError is thrown:

MathOptInterface.ResultIndexBoundsErrorType
struct ResultIndexBoundsError{AttrType} <: Exception
+    attr::AttrType
+    result_count::Int
+end

An error indicating that the requested attribute attr could not be retrieved, because the solver returned too few results compared to what was requested. For instance, the user tries to retrieve VariablePrimal(2) when only one solution is available, or when the model is infeasible and has no solution.

See also: check_result_index_bounds.

source

As discussed in JuMP mapping, for scalar constraint with a nonzero function constant, a ScalarFunctionConstantNotZero exception may be thrown:

Some VariableIndex constraints cannot be combined on the same variable:

As discussed in AbstractCallback, trying to get attributes inside a callback may throw:

MathOptInterface.OptimizeInProgressType
struct OptimizeInProgress{AttrType<:AnyAttribute} <: Exception
+    attr::AttrType
+end

Error thrown from optimizer when MOI.get(optimizer, attr) is called inside an AbstractCallback while it is only defined once optimize! has completed. This can only happen when is_set_by_optimize(attr) is true.

source

Trying to submit the wrong type of AbstractSubmittable inside an AbstractCallback (for example, a UserCut inside a LazyConstraintCallback) will throw:

The rest of the errors defined in MOI fall in two categories represented by the following two abstract types:

MathOptInterface.NotAllowedErrorType
NotAllowedError <: Exception

Abstract type for error thrown when an operation is supported but cannot be applied in the current state of the model.

source

The different UnsupportedError and NotAllowedError are the following errors:

MathOptInterface.UnsupportedAttributeType
struct UnsupportedAttribute{AttrType} <: UnsupportedError
+    attr::AttrType
+    message::String
+end

An error indicating that the attribute attr is not supported by the model, that is, that supports returns false.

source
MathOptInterface.SetAttributeNotAllowedType
struct SetAttributeNotAllowed{AttrType} <: NotAllowedError
+    attr::AttrType
+    message::String
+end

An error indicating that the attribute attr is supported (see supports) but cannot be set for some reason (see the error string).

source
MathOptInterface.AddVariableNotAllowedType
struct AddVariableNotAllowed <: NotAllowedError
+    message::String # Human-friendly explanation why the attribute cannot be set
+end

An error indicating that variables cannot be added to the model.

source
MathOptInterface.UnsupportedConstraintType
struct UnsupportedConstraint{F<:AbstractFunction, S<:AbstractSet} <: UnsupportedError
+    message::String # Human-friendly explanation why the attribute cannot be set
+end

An error indicating that constraints of type F-in-S are not supported by the model, that is, that supports_constraint returns false.

source
MathOptInterface.AddConstraintNotAllowedType
struct AddConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet} <: NotAllowedError
+    message::String # Human-friendly explanation why the attribute cannot be set
+end

An error indicating that constraints of type F-in-S are supported (see supports_constraint) but cannot be added.

source
MathOptInterface.ModifyConstraintNotAllowedType
struct ModifyConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet,
+                                  C<:AbstractFunctionModification} <: NotAllowedError
+    constraint_index::ConstraintIndex{F, S}
+    change::C
+    message::String
+end

An error indicating that the constraint modification change cannot be applied to the constraint of index ci.

source
MathOptInterface.ModifyObjectiveNotAllowedType
struct ModifyObjectiveNotAllowed{C<:AbstractFunctionModification} <: NotAllowedError
+    change::C
+    message::String
+end

An error indicating that the objective modification change cannot be applied to the objective.

source
MathOptInterface.DeleteNotAllowedType
struct DeleteNotAllowed{IndexType <: Index} <: NotAllowedError
+    index::IndexType
+    message::String
+end

An error indicating that the index index cannot be deleted.

source
MathOptInterface.UnsupportedSubmittableType
struct UnsupportedSubmittable{SubmitType} <: UnsupportedError
+    sub::SubmitType
+    message::String
+end

An error indicating that the submittable sub is not supported by the model, that is, that supports returns false.

source
MathOptInterface.SubmitNotAllowedType
struct SubmitNotAllowed{SubmitTyp<:AbstractSubmittable} <: NotAllowedError
+    sub::SubmitType
+    message::String
+end

An error indicating that the submittable sub is supported (see supports) but cannot be added for some reason (see the error string).

source
MathOptInterface.UnsupportedNonlinearOperatorType
UnsupportedNonlinearOperator(head::Symbol[, message::String]) <: UnsupportedError

An error thrown by optimizers if they do not support the operator head in a ScalarNonlinearFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> throw(MOI.UnsupportedNonlinearOperator(:black_box))
+ERROR: MathOptInterface.UnsupportedNonlinearOperator: The nonlinear operator `:black_box` is not supported by the model.
+Stacktrace:
+[...]
source

Note that setting the ConstraintFunction of a VariableIndex constraint is not allowed:

diff --git a/previews/PR2418/reference/models/index.html b/previews/PR2418/reference/models/index.html new file mode 100644 index 0000000000..e0635fb365 --- /dev/null +++ b/previews/PR2418/reference/models/index.html @@ -0,0 +1,132 @@ + +Models · MathOptInterface

Models

Attribute interface

MathOptInterface.is_set_by_optimizeFunction
is_set_by_optimize(::AnyAttribute)

Return a Bool indicating whether the value of the attribute is set during an optimize! call, that is, the attribute is used to query the result of the optimization.

If an attribute can be set by the user, define is_copyable instead.

An attribute cannot be both is_copyable and is_set_by_optimize.

Default fallback

This function returns false by default so it should be implemented for attributes that are set by optimize!.

Undefined behavior

Querying the value of the attribute that is_set_by_optimize before a call to optimize! is undefined and depends on solver-specific behavior.

source
MathOptInterface.is_copyableFunction
is_copyable(::AnyAttribute)

Return a Bool indicating whether the value of the attribute may be copied during copy_to using set.

If an attribute is_copyable, then it cannot be modified by the optimizer, and get must always return the value that was set by the user.

If an attribute is the result of an optimization, define is_set_by_optimize instead.

An attribute cannot be both is_set_by_optimize and is_copyable.

Default fallback

By default is_copyable(attr) returns !is_set_by_optimize(attr), which is most probably true.

If an attribute should not be copied, define is_copyable(::MyAttribute) = false.

source
MathOptInterface.getFunction
MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64

Return the number of variables created by the bridge b in the model.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)

Return the list of variables created by the bridge b.

See also MOI.ListOfVariableIndices.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}

Return the number of constraints of the type F-in-S created by the bridge b.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}

Return a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.

See also MOI.ListOfConstraintIndices.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
function MOI.get(
+    model::MOI.ModelLike,
+    attr::MOI.AbstractConstraintAttribute,
+    bridge::AbstractBridge,
+)

Return the value of the attribute attr of the model model for the constraint bridged by bridge.

source
get(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute)

Return an attribute attr of the optimizer optimizer.

get(model::ModelLike, attr::AbstractModelAttribute)

Return an attribute attr of the model model.

get(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex)

If the attribute attr is set for the variable v in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.

get(model::ModelLike, attr::AbstractVariableAttribute, v::Vector{VariableIndex})

Return a vector of attributes corresponding to each variable in the collection v in the model model.

get(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex)

If the attribute attr is set for the constraint c in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.

get(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    c::Vector{ConstraintIndex{F,S}},
+) where {F,S}

Return a vector of attributes corresponding to each constraint in the collection c in the model model.

get(model::ModelLike, ::Type{VariableIndex}, name::String)

If a variable with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two variables have the same name.

get(
+    model::ModelLike,
+    ::Type{ConstraintIndex{F,S}},
+    name::String,
+) where {F,S}

If an F-in-S constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two constraints have the same name.

get(model::ModelLike, ::Type{ConstraintIndex}, name::String)

If any constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. This version is available for convenience but may incur a performance penalty because it is not type stable. Errors if two constraints have the same name.

source
MathOptInterface.get!Function
get!(output, model::ModelLike, args...)

An in-place version of get.

The signature matches that of get except that the result is placed in the vector output.

source
MathOptInterface.setFunction
function MOI.set(
+    model::MOI.ModelLike,
+    attr::MOI.AbstractConstraintAttribute,
+    bridge::AbstractBridge,
+    value,
+)

Set the value of the attribute attr of the model model for the constraint bridged by bridge.

source
set(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute, value)

Assign value to the attribute attr of the optimizer optimizer.

set(model::ModelLike, attr::AbstractModelAttribute, value)

Assign value to the attribute attr of the model model.

set(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)

Assign value to the attribute attr of variable v in model model.

set(
+    model::ModelLike,
+    attr::AbstractVariableAttribute,
+    v::Vector{VariableIndex},
+    vector_of_values,
+)

Assign a value respectively to the attribute attr of each variable in the collection v in model model.

set(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    c::ConstraintIndex,
+    value,
+)

Assign a value to the attribute attr of constraint c in model model.

set(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    c::Vector{ConstraintIndex{F,S}},
+    vector_of_values,
+) where {F,S}

Assign a value respectively to the attribute attr of each constraint in the collection c in model model.

An UnsupportedAttribute error is thrown if model does not support the attribute attr (see supports) and a SetAttributeNotAllowed error is thrown if it supports the attribute attr but it cannot be set.

set(
+    model::ModelLike,
+    ::ConstraintSet,
+    c::ConstraintIndex{F,S},
+    set::S,
+) where {F,S}

Change the set of constraint c to the new set set which should be of the same type as the original set.

set(
+    model::ModelLike,
+    ::ConstraintFunction,
+    c::ConstraintIndex{F,S},
+    func::F,
+) where {F,S}

Replace the function in constraint c with func. F must match the original function type used to define the constraint.

Note

Setting the constraint function is not allowed if F is VariableIndex; a SettingVariableIndexNotAllowed error is thrown instead. This is because, it would require changing the index c since the index of VariableIndex constraints must be the same as the index of the variable.

source
MathOptInterface.supportsFunction
MOI.supports(
+    model::MOI.ModelLike,
+    attr::MOI.AbstractConstraintAttribute,
+    BT::Type{<:AbstractBridge},
+)

Return a Bool indicating whether BT supports setting attr to model.

source
supports(model::ModelLike, sub::AbstractSubmittable)::Bool

Return a Bool indicating whether model supports the submittable sub.

supports(model::ModelLike, attr::AbstractOptimizerAttribute)::Bool

Return a Bool indicating whether model supports the optimizer attribute attr. That is, it returns false if copy_to(model, src) shows a warning in case attr is in the ListOfOptimizerAttributesSet of src; see copy_to for more details on how unsupported optimizer attributes are handled in copy.

supports(model::ModelLike, attr::AbstractModelAttribute)::Bool

Return a Bool indicating whether model supports the model attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfModelAttributesSet of src.

supports(
+    model::ModelLike,
+    attr::AbstractVariableAttribute,
+    ::Type{VariableIndex},
+)::Bool

Return a Bool indicating whether model supports the variable attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfVariableAttributesSet of src.

supports(
+    model::ModelLike,
+    attr::AbstractConstraintAttribute,
+    ::Type{ConstraintIndex{F,S}},
+)::Bool where {F,S}

Return a Bool indicating whether model supports the constraint attribute attr applied to an F-in-S constraint. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfConstraintAttributesSet of src.

For all five methods, if the attribute is only not supported in specific circumstances, it should still return true.

Note that supports is only defined for attributes for which is_copyable returns true as other attributes do not appear in the list of attributes set obtained by ListOfXXXAttributesSet.

source
MathOptInterface.attribute_value_typeFunction
attribute_value_type(attr::AnyAttribute)

Given an attribute attr, return the type of value expected by get, or returned by set.

Notes

  • Only implement this if it make sense to do so. If un-implemented, the default is Any.
source

Model interface

MathOptInterface.is_emptyFunction
is_empty(model::ModelLike)

Returns false if the model has any model attribute set or has any variables or constraints.

Note that an empty model can have optimizer attributes set.

source
MathOptInterface.empty!Function
empty!(model::ModelLike)

Empty the model, that is, remove all variables, constraints and model attributes but not optimizer attributes.

source
MathOptInterface.write_to_fileFunction
write_to_file(model::ModelLike, filename::String)

Write the current model to the file at filename.

Supported file types depend on the model type.

source
MathOptInterface.read_from_fileFunction
read_from_file(model::ModelLike, filename::String)

Read the file filename into the model model. If model is non-empty, this may throw an error.

Supported file types depend on the model type.

Note

Once the contents of the file are loaded into the model, users can query the variables via get(model, ListOfVariableIndices()). However, some filetypes, such as LP files, do not maintain an explicit ordering of the variables. Therefore, the returned list may be in an arbitrary order.

To avoid depending on the order of the indices, look up each variable index by name using get(model, VariableIndex, "name").

source
MathOptInterface.copy_toFunction
copy_to(dest::ModelLike, src::ModelLike)::IndexMap

Copy the model from src into dest.

The target dest is emptied, and all previous indices to variables and constraints in dest are invalidated.

Returns an IndexMap object that translates variable and constraint indices from the src model to the corresponding indices in the dest model.

Notes

AbstractOptimizerAttributes are not copied to the dest model.

IndexMap

Implementations of copy_to must return an IndexMap. For technical reasons, this type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide MOI.IndexMap as an alias.

Example

# Given empty `ModelLike` objects `src` and `dest`.
+
+x = add_variable(src)
+
+is_valid(src, x)   # true
+is_valid(dest, x)  # false (`dest` has no variables)
+
+index_map = copy_to(dest, src)
+is_valid(dest, x) # false (unless index_map[x] == x)
+is_valid(dest, index_map[x]) # true
source
MathOptInterface.IndexMapType
IndexMap()

The dictionary-like object returned by copy_to.

IndexMap

Implementations of copy_to must return an IndexMap. For technical reasons, the IndexMap type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide this MOI.IndexMap as an alias.

source

Model attributes

MathOptInterface.NameType
Name()

A model attribute for the string identifying the model. It has a default value of "" if not set`.

source
MathOptInterface.ObjectiveFunctionType
ObjectiveFunction{F<:AbstractScalarFunction}()

A model attribute for the objective function which has a type F<:AbstractScalarFunction.

F should be guaranteed to be equivalent but not necessarily identical to the function type provided by the user.

Throws an InexactError if the objective function cannot be converted to F, for example, the objective function is quadratic and F is ScalarAffineFunction{Float64} or it has non-integer coefficient and F is ScalarAffineFunction{Int}.

source
MathOptInterface.ObjectiveFunctionTypeType
ObjectiveFunctionType()

A model attribute for the type F of the objective function set using the ObjectiveFunction{F} attribute.

Examples

In the following code, attr should be equal to MOI.VariableIndex:

x = MOI.add_variable(model)
+MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x)
+attr = MOI.get(model, MOI.ObjectiveFunctionType())
source
MathOptInterface.ObjectiveSenseType
ObjectiveSense()

A model attribute for the objective sense of the objective function, which must be an OptimizationSense: MIN_SENSE, MAX_SENSE, or FEASIBILITY_SENSE. The default is FEASIBILITY_SENSE.

Interaction with ObjectiveFunction

Setting the sense to FEASIBILITY_SENSE unsets the ObjectiveFunction attribute. That is, if you first set ObjectiveFunction and then set ObjectiveSense to be FEASIBILITY_SENSE, no objective function will be passed to the solver.

In addition, some reformulations of ObjectiveFunction via bridges rely on the value of ObjectiveSense. Therefore, you should set ObjectiveSense before setting ObjectiveFunction.

source
MathOptInterface.ListOfModelAttributesSetType
ListOfModelAttributesSet()

A model attribute for the Vector{AbstractModelAttribute} of all model attributes attr such that:

  1. is_copyable(attr) returns true, and
  2. the attribute was set to the model
source
MathOptInterface.ListOfVariableAttributesSetType
ListOfVariableAttributesSet()

A model attribute for the Vector{AbstractVariableAttribute} of all variable attributes attr such that 1) is_copyable(attr) returns true and 2) the attribute was set to variables.

source
MathOptInterface.ListOfVariablesWithAttributeSetType
ListOfVariablesWithAttributeSet(attr::AbstractVariableAttribute)

A model attribute for the Vector{VariableIndex} of all variables with the attribute attr set.

The returned list may not be minimal, so some elements may have their default value set.

Note

This is an optional attribute to implement. The default fallback is to get ListOfVariableIndices.

source
MathOptInterface.ListOfConstraintsWithAttributeSetType
ListOfConstraintsWithAttributeSet{F,S}(attr:AbstractConstraintAttribute)

A model attribute for the Vector{ConstraintIndex{F,S}} of all constraints with the attribute attr set.

The returned list may not be minimal, so some elements may have their default value set.

Note

This is an optional attribute to implement. The default fallback is to get ListOfConstraintIndices.

source
MathOptInterface.UserDefinedFunctionType
UserDefinedFunction(name::Symbol, arity::Int) <: AbstractModelAttribute

Set this attribute to register a user-defined function by the name of name with arity arguments.

Once registered, name will appear in ListOfSupportedNonlinearOperators.

You cannot register multiple UserDefinedFunctions with the same name but different arity.

Value type

The value to be set is a tuple containing one, two, or three functions to evaluate the function, the first-order derivative, and the second-order derivative respectively. Both derivatives are optional, but if you pass the second-order derivative you must also pass the first-order derivative.

For univariate functions with arity == 1, the functions in the tuple must have the form:

  • f(x::T)::T: returns the value of the function at x
  • ∇f(x::T)::T: returns the first-order derivative of f with respect to x
  • ∇²f(x::T)::T: returns the second-order derivative of f with respect to x.

For multivariate functions with arity > 1, the functions in the tuple must have the form:

  • f(x::T...)::T: returns the value of the function at x
  • ∇f(g::AbstractVector{T}, x::T...)::Nothing: fills the components of g, with g[i] being the first-order partial derivative of f with respect to x[i]
  • ∇²f(H::AbstractMatrix{T}, x::T...)::Nothing: fills the non-zero components of H, with H[i, j] being the second-order partial derivative of f with respect to x[i] and then x[j]. H is initialized to the zero matrix, so you do not need to set any zero elements.

Examples

julia> import MathOptInterface as MOI
+
+julia> f(x, y) = x^2 + y^2
+f (generic function with 1 method)
+
+julia> function ∇f(g, x, y)
+           g .= 2 * x, 2 * y
+           return
+       end
+∇f (generic function with 1 method)
+
+julia> function ∇²f(H, x...)
+           H[1, 1] = H[2, 2] = 2.0
+           return
+       end
+∇²f (generic function with 1 method)
+
+julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+MOIU.UniversalFallback{MOIU.Model{Float64}}
+fallback for MOIU.Model{Float64}
+
+julia> MOI.set(model, MOI.UserDefinedFunction(:f, 2), (f,))
+
+julia> MOI.set(model, MOI.UserDefinedFunction(:g, 2), (f, ∇f))
+
+julia> MOI.set(model, MOI.UserDefinedFunction(:h, 2), (f, ∇f, ∇²f))
+
+julia> x = MOI.add_variables(model, 2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+
+julia> MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+
+julia> obj_f = MOI.ScalarNonlinearFunction(:f, Any[x[1], x[2]])
+f(MOI.VariableIndex(1), MOI.VariableIndex(2))
+
+julia> MOI.set(model, MOI.ObjectiveFunction{typeof(obj_f)}(), obj_f)
+
+julia> print(model)
+Minimize ScalarNonlinearFunction:
+ f(v[1], v[2])
+
+Subject to:
+
source

Optimizer interface

MathOptInterface.AbstractOptimizerType
AbstractOptimizer <: ModelLike

Abstract supertype for objects representing an instance of an optimization problem tied to a particular solver. This is typically a solver's in-memory representation. In addition to ModelLike, AbstractOptimizer objects let you solve the model and query the solution.

source
MathOptInterface.OptimizerWithAttributesType
struct OptimizerWithAttributes
+    optimizer_constructor
+    params::Vector{Pair{AbstractOptimizerAttribute,<:Any}}
+end

Object grouping an optimizer constructor and a list of optimizer attributes. Instances are created with instantiate.

source
MathOptInterface.optimize!Method
optimize!(dest::AbstractOptimizer, src::ModelLike)::Tuple{IndexMap,Bool}

A "one-shot" call that copies the problem from src into dest and then uses dest to optimize the problem.

Returns a tuple of an IndexMap and a Bool copied.

  • The IndexMap object translates variable and constraint indices from the src model to the corresponding indices in the dest optimizer. See copy_to for details.
  • If copied == true, src was copied to dest and then cached, allowing incremental modification if supported by the solver.
  • If copied == false, a cache of the model was not kept in dest. Therefore, only the solution information (attributes for which is_set_by_optimize is true) is available to query.
Note

The main purpose of optimize! method with two arguments is for use in Utilities.CachingOptimizer.

Relationship to the single-argument optimize!

The default fallback of optimize!(dest::AbstractOptimizer, src::ModelLike) is

function optimize!(dest::AbstractOptimizer, src::ModelLike)
+    index_map = copy_to(dest, src)
+    optimize!(dest)
+    return index_map, true
+end

Therefore, subtypes of AbstractOptimizer should either implement this two-argument method, or implement both copy_to(::Optimizer, ::ModelLike) and optimize!(::Optimizer).

source
MathOptInterface.instantiateFunction
instantiate(
+    optimizer_constructor,
+    with_cache_type::Union{Nothing,Type} = nothing,
+    with_bridge_type::Union{Nothing,Type} = nothing,
+)

Create an instance of an optimizer by either:

  • calling optimizer_constructor.optimizer_constructor() and setting the parameters in optimizer_constructor.params if optimizer_constructor is a OptimizerWithAttributes
  • calling optimizer_constructor() if optimizer_constructor is callable.

withcachetype

If with_cache_type is not nothing, then the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the model. This is most useful if the optimizer you are constructing does not support the incremental interface (see supports_incremental_interface).

withbridgetype

If with_bridge_type is not nothing, the optimizer is wrapped in a Bridges.full_bridge_optimizer, enabling all the bridges defined in the MOI.Bridges submodule with coefficient type with_bridge_type.

In addition, if the optimizer created by optimizer_constructor does not support the incremental interface (see supports_incremental_interface), then, irrespective of with_cache_type, the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the bridged model.

If with_cache_type and with_bridge_type are both not nothing, then they must be the same type.

source
MathOptInterface.default_cacheFunction
default_cache(optimizer::ModelLike, ::Type{T}) where {T}

Return a new instance of the default model type to be used as cache for optimizer in a Utilities.CachingOptimizer for holding constraints of coefficient type T. By default, this returns Utilities.UniversalFallback(Utilities.Model{T}()). If copying from a instance of a given model type is faster for optimizer then a new method returning an instance of this model type should be defined.

source

Optimizer attributes

MathOptInterface.SolverVersionType
SolverVersion()

An optimizer attribute for the string identifying the version of the solver.

Note

For solvers supporting semantic versioning, the SolverVersion should be a string of the form "vMAJOR.MINOR.PATCH", so that it can be converted to a Julia VersionNumber (for example, `VersionNumber("v1.2.3")).

We do not require Semantic Versioning because some solvers use alternate versioning systems. For example, CPLEX uses Calendar Versioning, so SolverVersion will return a string like "202001".

source
MathOptInterface.SilentType
Silent()

An optimizer attribute for silencing the output of an optimizer. When set to true, it takes precedence over any other attribute controlling verbosity and requires the solver to produce no output. The default value is false which has no effect. In this case the verbosity is controlled by other attributes.

Note

Every optimizer should have verbosity on by default. For instance, if a solver has a solver-specific log level attribute, the MOI implementation should set it to 1 by default. If the user sets Silent to true, then the log level should be set to 0, even if the user specifically sets a value of log level. If the value of Silent is false then the log level set to the solver is the value given by the user for this solver-specific parameter or 1 if none is given.

source
MathOptInterface.TimeLimitSecType
TimeLimitSec()

An optimizer attribute for setting a time limit (in seconds) for an optimization. When set to nothing, it deactivates the solver time limit. The default value is nothing.

source
MathOptInterface.ObjectiveLimitType
ObjectiveLimit()

An optimizer attribute for setting a limit on the objective value.

The provided limit must be a Union{Real,Nothing}.

When set to nothing, the limit reverts to the solver's default.

The default value is nothing.

The solver may stop when the ObjectiveValue is better (lower for minimization, higher for maximization) than the ObjectiveLimit. If stopped, the TerminationStatus should be OBJECTIVE_LIMIT.

source
MathOptInterface.SolutionLimitType
SolutionLimit()

An optimizer attribute for setting a limit on the number of available feasible solutions.

Default values

The provided limit must be a Union{Nothing,Int}.

When set to nothing, the limit reverts to the solver's default.

The default value is nothing.

Termination criteria

The solver may stop when the ResultCount is larger than or equal to the SolutionLimit. If stopped because of this attribute, the TerminationStatus must be SOLUTION_LIMIT.

Solution quality

The quality of the available solutions is solver-dependent. The set of resulting solutions is not guaranteed to contain an optimal solution.

source
MathOptInterface.NumberOfThreadsType
NumberOfThreads()

An optimizer attribute for setting the number of threads used for an optimization. When set to nothing uses solver default. Values are positive integers. The default value is nothing.

source
MathOptInterface.AbsoluteGapToleranceType
AbsoluteGapTolerance()

An optimizer attribute for setting the absolute gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.

To set a relative gap tolerance, see RelativeGapTolerance.

Warning

The mathematical definition of "absolute gap", and its treatment during the optimization, are solver-dependent. However, assuming no other limit nor issue is encountered during the optimization, most solvers that implement this attribute will stop once $|f - b| ≤ g_{abs}$, where $b$ is the best bound, $f$ is the best feasible objective value, and $g_{abs}$ is the absolute gap.

source
MathOptInterface.RelativeGapToleranceType
RelativeGapTolerance()

An optimizer attribute for setting the relative gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.

If you are looking for the relative gap of the current best solution, see RelativeGap. If no limit nor issue is encountered during the optimization, the value of RelativeGap should be at most as large as RelativeGapTolerance.

# Before optimizing: set relative gap tolerance
+# set 0.1% relative gap tolerance
+MOI.set(model, MOI.RelativeGapTolerance(), 1e-3)
+MOI.optimize!(model)
+
+# After optimizing (assuming all went well)
+# The relative gap tolerance has not changed...
+MOI.get(model, MOI.RelativeGapTolerance())  # returns 1e-3
+# ... and the relative gap of the obtained solution is smaller or equal to the
+# tolerance
+MOI.get(model, MOI.RelativeGap())  # should return something ≤ 1e-3
Warning

The mathematical definition of "relative gap", and its allowed range, are solver-dependent. Typically, solvers expect a value between 0.0 and 1.0.

source

List of attributes useful for optimizers

MathOptInterface.TerminationStatusCodeType
TerminationStatusCode

An Enum of possible values for the TerminationStatus attribute. This attribute is meant to explain the reason why the optimizer stopped executing in the most recent call to optimize!.

Values

Possible values are:

  • OPTIMIZE_NOT_CALLED: The algorithm has not started.
  • OPTIMAL: The algorithm found a globally optimal solution.
  • INFEASIBLE: The algorithm concluded that no feasible solution exists.
  • DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.
  • LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.
  • LOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.
  • INFEASIBLE_OR_UNBOUNDED: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.
  • ALMOST_OPTIMAL: The algorithm found a globally optimal solution to relaxed tolerances.
  • ALMOST_INFEASIBLE: The algorithm concluded that no feasible solution exists within relaxed tolerances.
  • ALMOST_DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.
  • ALMOST_LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.
  • ITERATION_LIMIT: An iterative algorithm stopped after conducting the maximum number of iterations.
  • TIME_LIMIT: The algorithm stopped after a user-specified computation time.
  • NODE_LIMIT: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.
  • SOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.
  • MEMORY_LIMIT: The algorithm stopped because it ran out of memory.
  • OBJECTIVE_LIMIT: The algorithm stopped because it found a solution better than a minimum limit set by the user.
  • NORM_LIMIT: The algorithm stopped because the norm of an iterate became too large.
  • OTHER_LIMIT: The algorithm stopped due to a limit not covered by one of the _LIMIT_ statuses above.
  • SLOW_PROGRESS: The algorithm stopped because it was unable to continue making progress towards the solution.
  • NUMERICAL_ERROR: The algorithm stopped because it encountered unrecoverable numerical error.
  • INVALID_MODEL: The algorithm stopped because the model is invalid.
  • INVALID_OPTION: The algorithm stopped because it was provided an invalid option.
  • INTERRUPTED: The algorithm stopped because of an interrupt signal.
  • OTHER_ERROR: The algorithm stopped because of an error not covered by one of the statuses defined above.
source
MathOptInterface.DUAL_INFEASIBLEConstant
DUAL_INFEASIBLE::TerminationStatusCode

An instance of the TerminationStatusCode enum.

DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.

source
MathOptInterface.LOCALLY_SOLVEDConstant
LOCALLY_SOLVED::TerminationStatusCode

An instance of the TerminationStatusCode enum.

LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.

source
MathOptInterface.LOCALLY_INFEASIBLEConstant
LOCALLY_INFEASIBLE::TerminationStatusCode

An instance of the TerminationStatusCode enum.

LOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.

source
MathOptInterface.SOLUTION_LIMITConstant
SOLUTION_LIMIT::TerminationStatusCode

An instance of the TerminationStatusCode enum.

SOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.

source
MathOptInterface.DualStatusType
DualStatus(result_index::Int = 1)

A model attribute for the ResultStatusCode of the dual result result_index. If result_index is omitted, it defaults to 1.

See ResultCount for information on how the results are ordered.

If result_index is larger than the value of ResultCount then NO_SOLUTION is returned.

source
MathOptInterface.ResultCountType
ResultCount()

A model attribute for the number of results available.

Order of solutions

A number of attributes contain an index, result_index, which is used to refer to one of the available results. Thus, result_index must be an integer between 1 and the number of available results.

As a general rule, the first result (result_index=1) is the most important result (for example, an optimal solution or an infeasibility certificate). Other results will typically be alternate solutions that the solver found during the search for the first result.

If a (local) optimal solution is available, that is, TerminationStatus is OPTIMAL or LOCALLY_SOLVED, the first result must correspond to the (locally) optimal solution. Other results may be alternative optimal solutions, or they may be other suboptimal solutions; use ObjectiveValue to distinguish between them.

If a primal or dual infeasibility certificate is available, that is, TerminationStatus is INFEASIBLE or DUAL_INFEASIBLE and the corresponding PrimalStatus or DualStatus is INFEASIBILITY_CERTIFICATE, then the first result must be a certificate. Other results may be alternate certificates, or infeasible points.

source
MathOptInterface.ObjectiveValueType
ObjectiveValue(result_index::Int = 1)

A model attribute for the objective value of the primal solution result_index.

If the solver does not have a primal value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ObjectiveValue attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.DualObjectiveValueType
DualObjectiveValue(result_index::Int = 1)

A model attribute for the value of the objective function of the dual problem for the result_indexth dual result.

If the solver does not have a dual value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the DualObjectiveValue attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.RelativeGapType
RelativeGap()

A model attribute for the final relative optimality gap.

Warning

The definition of this gap is solver-dependent. However, most solvers implementing this attribute define the relative gap as some variation of $\frac{|b-f|}{|f|}$, where $b$ is the best bound and $f$ is the best feasible objective value.

source
MathOptInterface.SimplexIterationsType
SimplexIterations()

A model attribute for the cumulative number of simplex iterations during the optimization process.

For a mixed-integer program (MIP), the return value is the total simplex iterations for all nodes.

source
MathOptInterface.NodeCountType
NodeCount()

A model attribute for the total number of branch-and-bound nodes explored while solving a mixed-integer program (MIP).

source

ResultStatusCode

MathOptInterface.ResultStatusCodeType
ResultStatusCode

An Enum of possible values for the PrimalStatus and DualStatus attributes.

The values indicate how to interpret the result vector.

Values

Possible values are:

  • NO_SOLUTION: the result vector is empty.
  • FEASIBLE_POINT: the result vector is a feasible point.
  • NEARLY_FEASIBLE_POINT: the result vector is feasible if some constraint tolerances are relaxed.
  • INFEASIBLE_POINT: the result vector is an infeasible point.
  • INFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.
  • NEARLY_INFEASIBILITY_CERTIFICATE: the result satisfies a relaxed criterion for a certificate of infeasibility.
  • REDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.
  • NEARLY_REDUCTION_CERTIFICATE: the result satisfies a relaxed criterion for an ill-posed certificate.
  • UNKNOWN_RESULT_STATUS: the result vector contains a solution with an unknown interpretation.
  • OTHER_RESULT_STATUS: the result vector contains a solution with an interpretation not covered by one of the statuses defined above
source
MathOptInterface.INFEASIBILITY_CERTIFICATEConstant
INFEASIBILITY_CERTIFICATE::ResultStatusCode

An instance of the ResultStatusCode enum.

INFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.

source
MathOptInterface.REDUCTION_CERTIFICATEConstant
REDUCTION_CERTIFICATE::ResultStatusCode

An instance of the ResultStatusCode enum.

REDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.

source

Conflict Status

MathOptInterface.compute_conflict!Function
compute_conflict!(optimizer::AbstractOptimizer)

Computes a minimal subset of constraints such that the model with the other constraint removed is still infeasible.

Some solvers call a set of conflicting constraints an Irreducible Inconsistent Subsystem (IIS).

See also ConflictStatus and ConstraintConflictStatus.

Note

If the model is modified after a call to compute_conflict!, the implementor is not obliged to purge the conflict. Any calls to the above attributes may return values for the original conflict without a warning. Similarly, when modifying the model, the conflict can be discarded.

source
MathOptInterface.ConflictStatusCodeType
ConflictStatusCode

An Enum of possible values for the ConflictStatus attribute. This attribute is meant to explain the reason why the conflict finder stopped executing in the most recent call to compute_conflict!.

Possible values are:

  • COMPUTE_CONFLICT_NOT_CALLED: the function compute_conflict! has not yet been called
  • NO_CONFLICT_EXISTS: there is no conflict because the problem is feasible
  • NO_CONFLICT_FOUND: the solver could not find a conflict
  • CONFLICT_FOUND: at least one conflict could be found
source
MathOptInterface.ConflictParticipationStatusCodeType
ConflictParticipationStatusCode

An Enum of possible values for the ConstraintConflictStatus attribute. This attribute is meant to indicate whether a given constraint participates or not in the last computed conflict.

Values

Possible values are:

  • NOT_IN_CONFLICT: the constraint does not participate in the conflict
  • IN_CONFLICT: the constraint participates in the conflict
  • MAYBE_IN_CONFLICT: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict
source
diff --git a/previews/PR2418/reference/modification/index.html b/previews/PR2418/reference/modification/index.html new file mode 100644 index 0000000000..e439eec995 --- /dev/null +++ b/previews/PR2418/reference/modification/index.html @@ -0,0 +1,31 @@ + +Modifications · MathOptInterface

Modifications

MathOptInterface.modifyFunction

Constraint Function

modify(model::ModelLike, ci::ConstraintIndex, change::AbstractFunctionModification)

Apply the modification specified by change to the function of constraint ci.

An ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by the model model.

Examples

modify(model, ci, ScalarConstantChange(10.0))

Objective Function

modify(model::ModelLike, ::ObjectiveFunction, change::AbstractFunctionModification)

Apply the modification specified by change to the objective function of model. To change the function completely, call set instead.

An ModifyObjectiveNotAllowed error is thrown if modifying objectives is not supported by the model model.

Examples

modify(model, ObjectiveFunction{ScalarAffineFunction{Float64}}(), ScalarConstantChange(10.0))

Multiple modifications in Constraint Functions

modify(
+    model::ModelLike,
+    cis::AbstractVector{<:ConstraintIndex},
+    changes::AbstractVector{<:AbstractFunctionModification},
+)

Apply multiple modifications specified by changes to the functions of constraints cis.

A ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by model.

Examples

modify(
+    model,
+    [ci, ci],
+    [
+        ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),
+        ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),
+    ],
+)

Multiple modifications in the Objective Function

modify(
+    model::ModelLike,
+    attr::ObjectiveFunction,
+    changes::AbstractVector{<:AbstractFunctionModification},
+)

Apply multiple modifications specified by changes to the functions of constraints cis.

A ModifyObjectiveNotAllowed error is thrown if modifying objective coefficients is not supported by model.

Examples

modify(
+    model,
+    ObjectiveFunction{ScalarAffineFunction{Float64}}(),
+    [
+        ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),
+        ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),
+    ],
+)
source
MathOptInterface.AbstractFunctionModificationType
AbstractFunctionModification

An abstract supertype for structs which specify partial modifications to functions, to be used for making small modifications instead of replacing the functions entirely.

source
MathOptInterface.ScalarQuadraticCoefficientChangeType
ScalarQuadraticCoefficientChange{T}(
+    variable_1::VariableIndex,
+    variable_2::VariableIndex,
+    new_coefficient::T,
+)

A struct used to request a change in the quadratic coefficient of a ScalarQuadraticFunction.

Scaling factors

A ScalarQuadraticFunction has an implicit 0.5 scaling factor in front of the Q matrix. This modification applies to terms in the Q matrix.

If variable_1 == variable_2, this modification sets the corresponding diagonal element of the Q matrix to new_coefficient.

If variable_1 != variable_2, this modification is equivalent to setting both the corresponding upper- and lower-triangular elements of the Q matrix to new_coefficient.

As a consequence:

  • to modify the term x^2 to become 2x^2, new_coefficient must be 4
  • to modify the term xy to become 2xy, new_coefficient must be 2
source
diff --git a/previews/PR2418/reference/nonlinear/index.html b/previews/PR2418/reference/nonlinear/index.html new file mode 100644 index 0000000000..7c5c6d954d --- /dev/null +++ b/previews/PR2418/reference/nonlinear/index.html @@ -0,0 +1,78 @@ + +Nonlinear programming · MathOptInterface

Nonlinear programming

Types

MathOptInterface.NLPBoundsPairType
NLPBoundsPair(lower::Float64, upper::Float64)

A struct holding a pair of lower and upper bounds.

-Inf and Inf can be used to indicate no lower or upper bound, respectively.

source
MathOptInterface.NLPBlockDataType
struct NLPBlockData
+    constraint_bounds::Vector{NLPBoundsPair}
+    evaluator::AbstractNLPEvaluator
+    has_objective::Bool
+end

A struct encoding a set of nonlinear constraints of the form $lb \le g(x) \le ub$ and, if has_objective == true, a nonlinear objective function $f(x)$.

Nonlinear objectives override any objective set by using the ObjectiveFunction attribute.

The evaluator is a callback object that is used to query function values, derivatives, and expression graphs. If has_objective == false, then it is an error to query properties of the objective function, and in Hessian-of-the-Lagrangian queries, σ must be set to zero.

Note

Throughout the evaluator, all variables are ordered according to ListOfVariableIndices. Hence, MOI copies of nonlinear problems must not re-order variables.

source

Attributes

Functions

MathOptInterface.initializeFunction
initialize(
+    d::AbstractNLPEvaluator,
+    requested_features::Vector{Symbol},
+)::Nothing

Initialize d with the set of features in requested_features. Check features_available before calling initialize to see what features are supported by d.

Warning

This method must be called before any other methods.

Features

The following features are defined:

In all cases, including when requested_features is empty, eval_objective and eval_constraint are supported.

Examples

MOI.initialize(d, Symbol[])
+MOI.initialize(d, [:ExprGraph])
+MOI.initialize(d, MOI.features_available(d))
source
MathOptInterface.eval_constraintFunction
eval_constraint(d::AbstractNLPEvaluator,
+    g::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

Given a set of vector-valued constraints $l \le g(x) \le u$, evaluate the constraint function $g(x)$, storing the result in the vector g.

Implementation notes

When implementing this method, you must not assume that g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_objective_gradientFunction
eval_objective_gradient(
+    d::AbstractNLPEvaluator,
+    grad::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

Evaluate the gradient of the objective function $grad = \nabla f(x)$ as a dense vector, storing the result in the vector grad.

Implementation notes

When implementing this method, you must not assume that grad is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.jacobian_structureFunction
jacobian_structure(d::AbstractNLPEvaluator)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Jacobian matrix: $J_g(x) = \left[ \begin{array}{c} \nabla g_1(x) \\ \nabla g_2(x) \\ \vdots \\ \nabla g_m(x) \end{array}\right],$ where $g_i$ is the $i\text{th}$ component of the nonlinear constraints $g(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.eval_constraint_gradientFunction
eval_constraint_gradient(
+    d::AbstractNLPEvaluator,
+    ∇g::AbstractVector{T},
+    x::AbstractVector{T},
+    i::Int,
+)::Nothing where {T}

Evaluate the gradient of constraint i, $\nabla g_i(x)$, and store the non-zero values in ∇g, corresponding to the structure returned by constraint_gradient_structure.

Implementation notes

When implementing this method, you must not assume that ∇g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.constraint_gradient_structureFunction
constraint_gradient_structure(d::AbstractNLPEvaluator, i::Int)::Vector{Int64}

Returns a vector of indices, where each element indicates the position of a structurally nonzero element in the gradient of constraint $\nabla g_i(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.eval_constraint_jacobianFunction
eval_constraint_jacobian(d::AbstractNLPEvaluator,
+    J::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

Evaluates the sparse Jacobian matrix $J_g(x) = \left[ \begin{array}{c} \nabla g_1(x) \\ \nabla g_2(x) \\ \vdots \\ \nabla g_m(x) \end{array}\right]$.

The result is stored in the vector J in the same order as the indices returned by jacobian_structure.

Implementation notes

When implementing this method, you must not assume that J is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_constraint_jacobian_productFunction
eval_constraint_jacobian_product(
+    d::AbstractNLPEvaluator,
+    y::AbstractVector{T},
+    x::AbstractVector{T},
+    w::AbstractVector{T},
+)::Nothing where {T}

Computes the Jacobian-vector product $y = J_g(x)w$, storing the result in the vector y.

The vectors have dimensions such that length(w) == length(x), and length(y) is the number of nonlinear constraints.

Implementation notes

When implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_constraint_jacobian_transpose_productFunction
eval_constraint_jacobian_transpose_product(
+    d::AbstractNLPEvaluator,
+    y::AbstractVector{T},
+    x::AbstractVector{T},
+    w::AbstractVector{T},
+)::Nothing where {T}

Computes the Jacobian-transpose-vector product $y = J_g(x)^Tw$, storing the result in the vector y.

The vectors have dimensions such that length(y) == length(x), and length(w) is the number of nonlinear constraints.

Implementation notes

When implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.hessian_lagrangian_structureFunction
hessian_lagrangian_structure(
+    d::AbstractNLPEvaluator,
+)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian-of-the-Lagrangian matrix: $\nabla^2 f(x) + \sum_{i=1}^m \nabla^2 g_i(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.hessian_objective_structureFunction
hessian_objective_structure(
+    d::AbstractNLPEvaluator,
+)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: $\nabla^2 f(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.hessian_constraint_structureFunction
hessian_constraint_structure(
+    d::AbstractNLPEvaluator,
+    i::Int64,
+)::Vector{Tuple{Int64,Int64}}

Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: $\nabla^2 g_i(x)$.

The indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

The sparsity structure is assumed to be independent of the point $x$.

source
MathOptInterface.eval_hessian_objectiveFunction
eval_hessian_objective(
+    d::AbstractNLPEvaluator,
+    H::AbstractVector{T},
+    x::AbstractVector{T},
+)::Nothing where {T}

This function computes the sparse Hessian matrix: $\nabla^2 f(x)$, storing the result in the vector H in the same order as the indices returned by hessian_objective_structure.

Implementation notes

When implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_hessian_constraintFunction
eval_hessian_constraint(
+    d::AbstractNLPEvaluator,
+    H::AbstractVector{T},
+    x::AbstractVector{T},
+    i::Int64,
+)::Nothing where {T}

This function computes the sparse Hessian matrix: $\nabla^2 g_i(x)$, storing the result in the vector H in the same order as the indices returned by hessian_constraint_structure.

Implementation notes

When implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_hessian_lagrangianFunction
eval_hessian_lagrangian(
+    d::AbstractNLPEvaluator,
+    H::AbstractVector{T},
+    x::AbstractVector{T},
+    σ::T,
+    μ::AbstractVector{T},
+)::Nothing where {T}

Given scalar weight σ and vector of constraint weights μ, this function computes the sparse Hessian-of-the-Lagrangian matrix: $\sigma\nabla^2 f(x) + \sum_{i=1}^m \mu_i \nabla^2 g_i(x)$, storing the result in the vector H in the same order as the indices returned by hessian_lagrangian_structure.

Implementation notes

When implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.eval_hessian_lagrangian_productFunction
eval_hessian_lagrangian_product(
+    d::AbstractNLPEvaluator,
+    h::AbstractVector{T},
+    x::AbstractVector{T},
+    v::AbstractVector{T},
+    σ::T,
+    μ::AbstractVector{T},
+)::Nothing where {T}

Given scalar weight σ and vector of constraint weights μ, computes the Hessian-of-the-Lagrangian-vector product $h = \left(\sigma\nabla^2 f(x) + \sum_{i=1}^m \mu_i \nabla^2 g_i(x)\right)v$, storing the result in the vector h.

The vectors have dimensions such that length(h) == length(x) == length(v).

Implementation notes

When implementing this method, you must not assume that h is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.

source
MathOptInterface.objective_exprFunction
objective_expr(d::AbstractNLPEvaluator)::Expr

Returns a Julia Expr object representing the expression graph of the objective function.

Format

The expression has a number of limitations, compared with arbitrary Julia expressions:

  • All sums and products are flattened out as simple Expr(:+, ...) and Expr(:*, ...) objects.
  • All decision variables must be of the form Expr(:ref, :x, MOI.VariableIndex(i)), where i is the $i$th variable in ListOfVariableIndices.
  • There are currently no restrictions on recognized functions; typically these will be built-in Julia functions like ^, exp, log, cos, tan, sqrt, etc., but modeling interfaces may choose to extend these basic functions, or error if they encounter unsupported functions.

Examples

The expression $x_1+\sin(x_2/\exp(x_3))$ is represented as

:(x[MOI.VariableIndex(1)] + sin(x[MOI.VariableIndex(2)] / exp(x[MOI.VariableIndex[3]])))

or equivalently

Expr(
+    :call,
+    :+,
+    Expr(:ref, :x, MOI.VariableIndex(1)),
+    Expr(
+        :call,
+        :/,
+        Expr(:call, :sin, Expr(:ref, :x, MOI.VariableIndex(2))),
+        Expr(:call, :exp, Expr(:ref, :x, MOI.VariableIndex(3))),
+    ),
+)
source
MathOptInterface.constraint_exprFunction
constraint_expr(d::AbstractNLPEvaluator, i::Integer)::Expr

Returns a Julia Expr object representing the expression graph for the $i\text{th}$ nonlinear constraint.

Format

The format is the same as objective_expr, with an additional comparison operator indicating the sense of and bounds on the constraint.

For single-sided comparisons, the body of the constraint must be on the left-hand side, and the right-hand side must be a constant.

For double-sided comparisons (that is, $l \le f(x) \le u$), the body of the constraint must be in the middle, and the left- and right-hand sides must be constants.

The bounds on the constraints must match the NLPBoundsPairs passed to NLPBlockData.

Examples

:(x[MOI.VariableIndex(1)]^2 <= 1.0)
+:(x[MOI.VariableIndex(1)]^2 >= 2.0)
+:(x[MOI.VariableIndex(1)]^2 == 3.0)
+:(4.0 <= x[MOI.VariableIndex(1)]^2 <= 5.0)
source
diff --git a/previews/PR2418/reference/standard_form/index.html b/previews/PR2418/reference/standard_form/index.html new file mode 100644 index 0000000000..1381ee977d --- /dev/null +++ b/previews/PR2418/reference/standard_form/index.html @@ -0,0 +1,992 @@ + +Standard form · MathOptInterface

Standard form

Functions

MathOptInterface.AbstractFunctionType
AbstractFunction

Abstract supertype for function objects.

Required methods

All functions must implement:

Abstract subtypes of AbstractFunction may require additional methods to be implemented.

source
MathOptInterface.constantFunction
constant(f::AbstractFunction[, ::Type{T}]) where {T}

Returns the constant term of a scalar-valued function, or the constant vector of a vector-valued function.

If f is untyped and T is provided, returns zero(T).

source
constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})

Returns the constant term of the set set.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.constant(MOI.GreaterThan(1.0))
+1.0
+
+julia> MOI.constant(MOI.LessThan(2.5))
+2.5
+
+julia> MOI.constant(MOI.EqualTo(3))
+3
+
+julia> MOI.constant(MOI.Parameter(4.5))
+4.5
source

Scalar functions

MathOptInterface.VariableIndexType
VariableIndex

A type-safe wrapper for Int64 for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.

source
MathOptInterface.ScalarAffineTermType
ScalarAffineTerm{T}(coefficient::T, variable::VariableIndex) where {T}

Represents the scalar-valued term coefficient * variable.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> MOI.ScalarAffineTerm(2.0, x)
+MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))
source
MathOptInterface.ScalarAffineFunctionType
ScalarAffineFunction{T}(
+    terms::Vector{ScalarAffineTerm{T}},
+    constant::T,
+) where {T}

Represents the scalar-valued affine function $a^\top x + b$, where:

  • $a^\top x$ is represented by the vector of ScalarAffineTerms
  • $b$ is a scalar constant::T

Duplicates

Duplicate variable indices in terms are accepted, and the corresponding coefficients are summed together.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> terms = [MOI.ScalarAffineTerm(2.0, x), MOI.ScalarAffineTerm(3.0, x)]
+2-element Vector{MathOptInterface.ScalarAffineTerm{Float64}}:
+ MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))
+ MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1))
+
+julia> f = MOI.ScalarAffineFunction(terms, 4.0)
+4.0 + 2.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)
source
MathOptInterface.ScalarQuadraticTermType
ScalarQuadraticTerm{T}(
+    coefficient::T,
+    variable_1::VariableIndex,
+    variable_2::VariableIndex,
+) where {T}

Represents the scalar-valued term $c x_i x_j$ where $c$ is coefficient, $x_i$ is variable_1 and $x_j$ is variable_2.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> MOI.ScalarQuadraticTerm(2.0, x, x)
+MathOptInterface.ScalarQuadraticTerm{Float64}(2.0, MOI.VariableIndex(1), MOI.VariableIndex(1))
source
MathOptInterface.ScalarQuadraticFunctionType
ScalarQuadraticFunction{T}(
+    quadratic_terms::Vector{ScalarQuadraticTerm{T}},
+    affine_terms::Vector{ScalarAffineTerm{T}},
+    constant::T,
+) wher {T}

The scalar-valued quadratic function $\frac{1}{2}x^\top Q x + a^\top x + b$, where:

Duplicates

Duplicate indices in quadratic_terms or affine_terms are accepted, and the corresponding coefficients are summed together.

In quadratic_terms, "mirrored" indices, (q, r) and (r, q) where r and q are VariableIndexes, are considered duplicates; only one needs to be specified.

The 0.5 factor

Coupled with the interpretation of mirrored indices, the 0.5 factor in front of the $Q$ matrix is a common source of bugs.

As a rule, to represent $a * x^2 + b * x * y$:

  • The coefficient $a$ in front of squared variables (diagonal elements in $Q$) must be doubled when creating a ScalarQuadraticTerm
  • The coefficient $b$ in front of off-diagonal elements in $Q$ should be left as $b$, be cause the mirrored index $b * y * x$ will be implicitly added.

Example

To represent the function $f(x, y) = 2 * x^2 + 3 * x * y + 4 * x + 5$, do:

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> y = MOI.VariableIndex(2);
+
+julia> constant = 5.0;
+
+julia> affine_terms = [MOI.ScalarAffineTerm(4.0, x)];
+
+julia> quadratic_terms = [
+           MOI.ScalarQuadraticTerm(4.0, x, x),  # Note the changed coefficient
+           MOI.ScalarQuadraticTerm(3.0, x, y),
+       ]
+2-element Vector{MathOptInterface.ScalarQuadraticTerm{Float64}}:
+ MathOptInterface.ScalarQuadraticTerm{Float64}(4.0, MOI.VariableIndex(1), MOI.VariableIndex(1))
+ MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(2))
+
+julia> f = MOI.ScalarQuadraticFunction(quadratic_terms, affine_terms, constant)
+5.0 + 4.0 MOI.VariableIndex(1) + 2.0 MOI.VariableIndex(1)² + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)
source
MathOptInterface.ScalarNonlinearFunctionType
ScalarNonlinearFunction(head::Symbol, args::Vector{Any})

The scalar-valued nonlinear function head(args...), represented as a symbolic expression tree, with the call operator head and ordered arguments in args.

head

The head::Symbol must be an operator supported by the model.

The default list of supported univariate operators is given by:

and the default list of supported multivariate operators is given by:

Additional operators can be registered by setting a UserDefinedFunction attribute.

See the full list of operators supported by a ModelLike by querying ListOfSupportedNonlinearOperators.

args

The vector args contains the arguments to the nonlinear function. If the operator is univariate, it must contain one element. Otherwise, it may contain multiple elements.

Each element must be one of the following:

Unsupported operators

If the optimizer does not support head, an UnsupportedNonlinearOperator error will be thrown.

There is no guarantee about when this error will be thrown; it may be thrown when the function is first added to the model, or it may be thrown when optimize! is called.

Example

To represent the function $f(x) = sin(x)^2$, do:

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> MOI.ScalarNonlinearFunction(
+           :^,
+           Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2],
+       )
+^(sin(MOI.VariableIndex(1)), (2))
source

Vector functions

MathOptInterface.VectorOfVariablesType
VectorOfVariables(variables::Vector{VariableIndex}) <: AbstractVectorFunction

The vector-valued function f(x) = variables, where variables is a subset of VariableIndexes in the model.

The list of variables may contain duplicates.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex.(1:2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+
+julia> f = MOI.VectorOfVariables([x[1], x[2], x[1]])
+┌                    ┐
+│MOI.VariableIndex(1)│
+│MOI.VariableIndex(2)│
+│MOI.VariableIndex(1)│
+└                    ┘
+
+julia> MOI.output_dimension(f)
+3
source
MathOptInterface.VectorAffineTermType
VectorAffineTerm{T}(
+    output_index::Int64,
+    scalar_term::ScalarAffineTerm{T},
+) where {T}

A VectorAffineTerm is a scalar_term that appears in the output_index row of the vector-valued VectorAffineFunction or VectorQuadraticFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x))
+MathOptInterface.VectorAffineTerm{Float64}(2, MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1)))
source
MathOptInterface.VectorAffineFunctionType
VectorAffineFunction{T}(
+    terms::Vector{VectorAffineTerm{T}},
+    constants::Vector{T},
+) where {T}

The vector-valued affine function $A x + b$, where:

  • $A x$ is the sparse matrix given by the vector of VectorAffineTerms
  • $b$ is the vector constants

Duplicates

Duplicate indices in the $A$ are accepted, and the corresponding coefficients are summed together.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> terms = [
+           MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),
+           MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),
+       ];
+
+julia> f = MOI.VectorAffineFunction(terms, [4.0, 5.0])
+┌                              ┐
+│4.0 + 2.0 MOI.VariableIndex(1)│
+│5.0 + 3.0 MOI.VariableIndex(1)│
+└                              ┘
+
+julia> MOI.output_dimension(f)
+2
source
MathOptInterface.VectorQuadraticTermType
VectorQuadraticTerm{T}(
+    output_index::Int64,
+    scalar_term::ScalarQuadraticTerm{T},
+) where {T}

A VectorQuadraticTerm is a ScalarQuadraticTerm scalar_term that appears in the output_index row of the vector-valued VectorQuadraticFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, x))
+MathOptInterface.VectorQuadraticTerm{Float64}(2, MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(1)))
source
MathOptInterface.VectorQuadraticFunctionType
VectorQuadraticFunction{T}(
+    quadratic_terms::Vector{VectorQuadraticTerm{T}},
+    affine_terms::Vector{VectorAffineTerm{T}},
+    constants::Vector{T},
+) where {T}

The vector-valued quadratic function with ith component ("output index") defined as $\frac{1}{2}x^\top Q_i x + a_i^\top x + b_i$, where:

  • $\frac{1}{2}x^\top Q_i x$ is the symmetric matrix given by the VectorQuadraticTerm elements in quadratic_terms with output_index == i
  • $a_i^\top x$ is the sparse vector given by the VectorAffineTerm elements in affine_terms with output_index == i
  • $b_i$ is a scalar given by constants[i]

Duplicates

Duplicate indices in quadratic_terms and affine_terms with the same output_index are handled in the same manner as duplicates in ScalarQuadraticFunction.

Example

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1);
+
+julia> y = MOI.VariableIndex(2);
+
+julia> constants = [4.0, 5.0];
+
+julia> affine_terms = [
+           MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),
+           MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),
+       ];
+
+julia> quad_terms = [
+        MOI.VectorQuadraticTerm(Int64(1), MOI.ScalarQuadraticTerm(2.0, x, x)),
+        MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, y)),
+           ];
+
+julia> f = MOI.VectorQuadraticFunction(quad_terms, affine_terms, constants)
+┌                                                                              ┐
+│4.0 + 2.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²                    │
+│5.0 + 3.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)│
+└                                                                              ┘
+
+julia> MOI.output_dimension(f)
+2
source
MathOptInterface.VectorNonlinearFunctionType
VectorNonlinearFunction(args::Vector{ScalarNonlinearFunction})

The vector-valued nonlinear function composed of a vector of ScalarNonlinearFunction.

args

The vector args contains the scalar elements of the nonlinear function. Each element must be a ScalarNonlinearFunction, but if you pass a Vector{Any}, the elements can be automatically converted from one of the following:

Example

To represent the function $f(x) = [sin(x)^2, x]$, do:

julia> import MathOptInterface as MOI
+
+julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> g = MOI.ScalarNonlinearFunction(
+           :^,
+           Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2.0],
+       )
+^(sin(MOI.VariableIndex(1)), 2.0)
+
+julia> MOI.VectorNonlinearFunction([g, x])
+┌                                 ┐
+│^(sin(MOI.VariableIndex(1)), 2.0)│
+│+(MOI.VariableIndex(1))          │
+└                                 ┘

Note the automatic conversion from x to +(x).

source

Sets

MathOptInterface.AbstractSetType
AbstractSet

Abstract supertype for set objects used to encode constraints.

Required methods

For sets of type S with isbitstype(S) == false, you must implement:

  • Base.copy(set::S)
  • Base.:(==)(x::S, y::S)

Subtypes of AbstractSet such as AbstractScalarSet and AbstractVectorSet may prescribe additional required methods.

Optional methods

You may optionally implement:

Note for developers

When creating a new set, the set struct must not contain any VariableIndex or ConstraintIndex objects.

source
MathOptInterface.AbstractVectorSetType
AbstractVectorSet

Abstract supertype for subsets of $\mathbb{R}^n$ for some $n$.

Required methods

All AbstractVectorSets of type S must implement:

  • dimension, unless the dimension is stored in the set.dimension field
  • Utilities.set_dot, unless the dot product between two vectors in the set is equivalent to LinearAlgebra.dot.
source

Utilities

MathOptInterface.dimensionFunction
dimension(set::AbstractSet)

Return the output_dimension that an AbstractFunction should have to be used with the set set.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.dimension(MOI.Reals(4))
+4
+
+julia> MOI.dimension(MOI.LessThan(3.0))
+1
+
+julia> MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2))
+3
source
MathOptInterface.dual_setFunction
dual_set(set::AbstractSet)

Return the dual set of set, that is the dual cone of the set. This follows the definition of duality discussed in Duality.

See Dual cone for more information.

If the dual cone is not defined it returns an error.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.dual_set(MOI.Reals(4))
+MathOptInterface.Zeros(4)
+
+julia> MOI.dual_set(MOI.SecondOrderCone(5))
+MathOptInterface.SecondOrderCone(5)
+
+julia> MOI.dual_set(MOI.ExponentialCone())
+MathOptInterface.DualExponentialCone()
source
MathOptInterface.dual_set_typeFunction
dual_set_type(S::Type{<:AbstractSet})

Return the type of dual set of sets of type S, as returned by dual_set. If the dual cone is not defined it returns an error.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.dual_set_type(MOI.Reals)
+MathOptInterface.Zeros
+
+julia> MOI.dual_set_type(MOI.SecondOrderCone)
+MathOptInterface.SecondOrderCone
+
+julia> MOI.dual_set_type(MOI.ExponentialCone)
+MathOptInterface.DualExponentialCone
source
MathOptInterface.constantMethod
constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})

Returns the constant term of the set set.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.constant(MOI.GreaterThan(1.0))
+1.0
+
+julia> MOI.constant(MOI.LessThan(2.5))
+2.5
+
+julia> MOI.constant(MOI.EqualTo(3))
+3
+
+julia> MOI.constant(MOI.Parameter(4.5))
+4.5
source
MathOptInterface.supports_dimension_updateFunction
supports_dimension_update(S::Type{<:MOI.AbstractVectorSet})

Return a Bool indicating whether the elimination of any dimension of n-dimensional sets of type S give an n-1-dimensional set S. By default, this function returns false so it should only be implemented for sets that supports dimension update.

For instance, supports_dimension_update(MOI.Nonnegatives) is true because the elimination of any dimension of the n-dimensional nonnegative orthant gives the n-1-dimensional nonnegative orthant. However supports_dimension_update(MOI.ExponentialCone) is false.

source

Scalar sets

List of recognized scalar sets.

MathOptInterface.GreaterThanType
GreaterThan{T<:Real}(lower::T)

The set $[lower, \infty) \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.GreaterThan(0.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
source
MathOptInterface.LessThanType
LessThan{T<:Real}(upper::T)

The set $(-\infty, upper] \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.LessThan(2.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64}}(1)
source
MathOptInterface.EqualToType
EqualTo{T<:Number}(value::T)

The set containing the single point $\{value\} \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.EqualTo(2.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)
source
MathOptInterface.IntervalType
Interval{T<:Real}(lower::T, upper::T)

The interval $[lower, upper] \subseteq \mathbb{R} \cup \{-\infty, +\infty\}$.

If lower or upper is -Inf or Inf, respectively, the set is interpreted as a one-sided interval.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Interval(1.0, 2.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
source
MathOptInterface.IntegerType
Integer()

The set of integers, $\mathbb{Z}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Integer())
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)
source
MathOptInterface.ZeroOneType
ZeroOne()

The set $\{0, 1\}$.

Variables belonging to the ZeroOne set are also known as "binary" variables.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.ZeroOne())
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)
source
MathOptInterface.SemicontinuousType
Semicontinuous{T<:Real}(lower::T, upper::T)

The set $\{0\} \cup [lower, upper]$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Semicontinuous(2.0, 3.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semicontinuous{Float64}}(1)
source
MathOptInterface.SemiintegerType
Semiinteger{T<:Real}(lower::T, upper::T)

The set $\{0\} \cup \{lower, lower+1, \ldots, upper-1, upper\}$.

Note that if lower and upper are not equivalent to an integer, then the solver may throw an error, or it may round up lower and round down upper to the nearest integers.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(model, x, MOI.Semiinteger(2.0, 3.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semiinteger{Float64}}(1)
source
MathOptInterface.ParameterType
Parameter{T<:Number}(value::T)

The set containing the single point $\{value\} \subseteq \mathbb{R}$.

The Parameter set is conceptually similar to the EqualTo set, except that a variable constrained to the Parameter set cannot have other constraints added to it, and the Parameter set can never be deleted. Thus, solvers are free to treat the variable as a constant, and they need not add it as a decision variable to the model.

Because of this behavior, you must add parameters using add_constrained_variable, and solvers should declare supports_add_constrained_variable and not supports_constraint for the Parameter set.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> p, ci = MOI.add_constrained_variable(model, MOI.Parameter(2.5))
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Parameter{Float64}}(1))
+
+julia> MOI.set(model, MOI.ConstraintSet(), ci, MOI.Parameter(3.0))
+
+julia> MOI.get(model, MOI.ConstraintSet(), ci)
+MathOptInterface.Parameter{Float64}(3.0)
source

Vector sets

List of recognized vector sets.

MathOptInterface.RealsType
Reals(dimension::Int)

The set $\mathbb{R}^{dimension}$ (containing all points) of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Reals(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Reals}(1)
source
MathOptInterface.ZerosType
Zeros(dimension::Int)

The set $\{ 0 \}^{dimension}$ (containing only the origin) of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Zeros(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros}(1)
source
MathOptInterface.NonnegativesType
Nonnegatives(dimension::Int)

The nonnegative orthant $\{ x \in \mathbb{R}^{dimension} : x \ge 0 \}$ of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)
source
MathOptInterface.NonpositivesType
Nonpositives(dimension::Int)

The nonpositive orthant $\{ x \in \mathbb{R}^{dimension} : x \le 0 \}$ of non-negative dimension dimension.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonpositives(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonpositives}(1)
source
MathOptInterface.NormInfinityConeType
NormInfinityCone(dimension::Int)

The $\ell_\infty$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_\infty = \max_i \lvert x_i \rvert \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormInfinityCone(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormInfinityCone}(1)
source
MathOptInterface.NormOneConeType
NormOneCone(dimension::Int)

The $\ell_1$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_1 = \sum_i \lvert x_i \rvert \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormOneCone(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormOneCone}(1)
source
MathOptInterface.NormConeType
NormCone(p::Float64, dimension::Int)

The $\ell_p$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \left(\sum\limits_i |x_i|^p\right)^{\frac{1}{p}} \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormCone(3, 4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormCone}(1)
source
MathOptInterface.SecondOrderConeType
SecondOrderCone(dimension::Int)

The second-order cone (or Lorenz cone or $\ell_2$-norm cone) $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_2 \}$ of dimension dimension.

The dimension must be at least 1.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.SecondOrderCone(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SecondOrderCone}(1)
source
MathOptInterface.RotatedSecondOrderConeType
RotatedSecondOrderCone(dimension::Int)

The rotated second-order cone $\{ (t,u,x) \in \mathbb{R}^{dimension} : 2tu \ge \lVert x \rVert_2^2, t,u \ge 0 \}$ of dimension dimension.

The dimension must be at least 2.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> u = MOI.add_variable(model)
+MOI.VariableIndex(2)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; u; x]),
+           MOI.RotatedSecondOrderCone(5),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RotatedSecondOrderCone}(1)
source
MathOptInterface.GeometricMeanConeType
GeometricMeanCone(dimension::Int)

The geometric mean cone $\{ (t,x) \in \mathbb{R}^{n+1} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}$, where dimension = n + 1 >= 2.

Duality note

The dual of the geometric mean cone is $\{ (u, v) \in \mathbb{R}^{n+1} : u \le 0, v \ge 0, -u \le n \sqrt[n]{\prod_i v_i} \}$, where dimension = n + 1 >= 2.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; x]),
+           MOI.GeometricMeanCone(4),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.GeometricMeanCone}(1)
source
MathOptInterface.ExponentialConeType
ExponentialCone()

The 3-dimensional exponential cone $\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.ExponentialCone())
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.ExponentialCone}(1)
source
MathOptInterface.DualExponentialConeType
DualExponentialCone()

The 3-dimensional dual exponential cone $\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le \exp(1) w, u < 0 \}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualExponentialCone())
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualExponentialCone}(1)
source
MathOptInterface.PowerConeType
PowerCone{T<:Real}(exponent::T)

The 3-dimensional power cone $\{ (x,y,z) \in \mathbb{R}^3 : x^{exponent} y^{1-exponent} \ge |z|, x \ge 0, y \ge 0 \}$ with parameter exponent.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.PowerCone(0.5))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.PowerCone{Float64}}(1)
source
MathOptInterface.DualPowerConeType
DualPowerCone{T<:Real}(exponent::T)

The 3-dimensional power cone $\{ (u,v,w) \in \mathbb{R}^3 : (\frac{u}{exponent})^{exponent} (\frac{v}{1-exponent})^{1-exponent} \ge |w|, u \ge 0, v \ge 0 \}$ with parameter exponent.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualPowerCone(0.5))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualPowerCone{Float64}}(1)
source
MathOptInterface.RelativeEntropyConeType
RelativeEntropyCone(dimension::Int)

The relative entropy cone $\{ (u, v, w) \in \mathbb{R}^{1+2n} : u \ge \sum_{i=1}^n w_i \log(\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}$, where dimension = 2n + 1 >= 1.

Duality note

The dual of the relative entropy cone is $\{ (u, v, w) \in \mathbb{R}^{1+2n} : \forall i, w_i \ge u (\log (\frac{u}{v_i}) - 1), v_i \ge 0, u > 0 \}$ of dimension dimension${}=2n+1$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> u = MOI.add_variable(model);
+
+julia> v = MOI.add_variables(model, 3);
+
+julia> w = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([u; v; w]),
+           MOI.RelativeEntropyCone(7),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RelativeEntropyCone}(1)
source
MathOptInterface.NormSpectralConeType
NormSpectralCone(row_dim::Int, column_dim::Int)

The epigraph of the matrix spectral norm (maximum singular value function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sigma_1(X) \}$, where $\sigma_i$ is the $i$th singular value of the matrix $X$ of non-negative row dimension row_dim and column dimension column_dim.

The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 6), 2, 3)
+2×3 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)  MOI.VariableIndex(6)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)  MOI.VariableIndex(7)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.NormSpectralCone(2, 3),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormSpectralCone}(1)
source
MathOptInterface.NormNuclearConeType
NormNuclearCone(row_dim::Int, column_dim::Int)

The epigraph of the matrix nuclear norm (sum of singular values function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sum_i \sigma_i(X) \}$, where $\sigma_i$ is the $i$th singular value of the matrix $X$ of non-negative row dimension row_dim and column dimension column_dim.

The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 6), 2, 3)
+2×3 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)  MOI.VariableIndex(6)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)  MOI.VariableIndex(7)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.NormNuclearCone(2, 3),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormNuclearCone}(1)
source
MathOptInterface.SOS1Type
SOS1{T<:Real}(weights::Vector{T})

The set corresponding to the Special Ordered Set (SOS) constraint of Type I.

Of the variables in the set, at most one can be nonzero.

The weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Solvers may use these weights to improve the efficiency of the solution process, but the ordering does not change the set of feasible solutions.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables(x),
+           MOI.SOS1([1.0, 3.0, 2.5]),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS1{Float64}}(1)
source
MathOptInterface.SOS2Type
SOS2{T<:Real}(weights::Vector{T})

The set corresponding to the Special Ordered Set (SOS) constraint of Type II.

The weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Therefore, the weights must be unique.

Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables(x),
+           MOI.SOS2([1.0, 3.0, 2.5]),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS2{Float64}}(1)
source
MathOptInterface.IndicatorType
Indicator{A<:ActivationCondition,S<:AbstractScalarSet}(set::S)

The set corresponding to an indicator constraint.

When A is ACTIVATE_ON_ZERO, this means: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 0 \implies x \in set\}$

When A is ACTIVATE_ON_ONE, this means: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 1 \implies x \in set\}$

Notes

Most solvers expect that the first row of the function is interpretable as a variable index x_i (for example, 1.0 * x + 0.0). An error will be thrown if this is not the case.

Example

The constraint $\{(y, x) \in \{0, 1\} \times \mathbb{R}^2 : y = 1 \implies x_1 + x_2 \leq 9 \}$ is defined as

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 2)
+2-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+
+julia> y, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
+(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3))
+
+julia> f = MOI.VectorAffineFunction(
+           [
+               MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, y)),
+               MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[1])),
+               MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[2])),
+           ],
+           [0.0, 0.0],
+       )
+┌                                                         ┐
+│0.0 + 1.0 MOI.VariableIndex(3)                           │
+│0.0 + 1.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(2)│
+└                                                         ┘
+
+julia> s = MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))
+MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}(MathOptInterface.LessThan{Float64}(9.0))
+
+julia> MOI.add_constraint(model, f, s)
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}}(1)
source
MathOptInterface.ComplementsType
Complements(dimension::Base.Integer)

The set corresponding to a mixed complementarity constraint.

Complementarity constraints should be specified with an AbstractVectorFunction-in-Complements(dimension) constraint.

The dimension of the vector-valued function F must be dimension. This defines a complementarity constraint between the scalar function F[i] and the variable in F[i + dimension/2]. Thus, F[i + dimension/2] must be interpretable as a single variable x_i (for example, 1.0 * x + 0.0), and dimension must be even.

The mixed complementarity problem consists of finding x_i in the interval [lb, ub] (that is, in the set Interval(lb, ub)), such that the following holds:

  1. F_i(x) == 0 if lb_i < x_i < ub_i
  2. F_i(x) >= 0 if lb_i == x_i
  3. F_i(x) <= 0 if x_i == ub_i

Classically, the bounding set for x_i is Interval(0, Inf), which recovers: 0 <= F_i(x) ⟂ x_i >= 0, where the operator implies F_i(x) * x_i = 0.

Example

The problem:

x -in- Interval(-1, 1)
+[-4 * x - 3, x] -in- Complements(2)

defines the mixed complementarity problem where the following holds:

  1. -4 * x - 3 == 0 if -1 < x < 1
  2. -4 * x - 3 >= 0 if x == -1
  3. -4 * x - 3 <= 0 if x == 1

There are three solutions:

  1. x = -3/4 with F(x) = 0
  2. x = -1 with F(x) = 1
  3. x = 1 with F(x) = -7
julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x, _ = MOI.add_constrained_variable(model, MOI.Interval(-1.0, 1.0));
+
+julia> MOI.add_constraint(
+            model,
+            MOI.Utilities.vectorize([-4.0 * x - 3.0, x]),
+            MOI.Complements(2),
+        )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Complements}(1)

The function F can also be defined in terms of single variables. For example, the problem:

[x_3, x_4] -in- Nonnegatives(2)
+[x_1, x_2, x_3, x_4] -in- Complements(4)

defines the complementarity problem where 0 <= x_1 ⟂ x_3 >= 0 and 0 <= x_2 ⟂ x_4 >= 0.

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 4);
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x[3:4]), MOI.Nonnegatives(2))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.add_constraint(
+            model,
+            MOI.VectorOfVariables(x),
+            MOI.Complements(4),
+        )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Complements}(1)
source
MathOptInterface.HyperRectangleType
HyperRectangle(lower::Vector{T}, upper::Vector{T}) where {T}

The set $\{x \in \bar{\mathbb{R}}^d: x_i \in [lower_i, upper_i] \forall i=1,\ldots,d\}$.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3)
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables(x),
+           MOI.HyperRectangle(zeros(3), ones(3)),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.HyperRectangle{Float64}}(1)
source
MathOptInterface.ScaledType
struct Scaled{S<:AbstractVectorSet} <: AbstractVectorSet
+    set::S
+end

Given a vector $a \in \mathbb{R}^d$ and a set representing the set $\mathcal{S} \in \mathbb{R}^d$ such that Utilities.set_dot for $x \in \mathcal{S}$ and $y \in \mathcal{S}^*$ is

\[\sum_{i=1}^d a_i x_i y_i\]

the set Scaled(set) is defined as

\[\{ (\sqrt{a_1} x_1, \sqrt{a_2} x_2, \ldots, \sqrt{a_d} x_d) : x \in S \}\]

Example

This can be used to scale a vector of numbers

julia> import MathOptInterface as MOI
+
+julia> set = MOI.PositiveSemidefiniteConeTriangle(2)
+MathOptInterface.PositiveSemidefiniteConeTriangle(2)
+
+julia> a = MOI.Utilities.SetDotScalingVector{Float64}(set)
+3-element MathOptInterface.Utilities.SetDotScalingVector{Float64, MathOptInterface.PositiveSemidefiniteConeTriangle}:
+ 1.0
+ 1.4142135623730951
+ 1.0
+
+julia> using LinearAlgebra
+
+julia> MOI.Utilities.operate(*, Float64, Diagonal(a), ones(3))
+3-element Vector{Float64}:
+ 1.0
+ 1.4142135623730951
+ 1.0

It can be also used to scale a vector of function

julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3);
+
+julia> func = MOI.VectorOfVariables(x)
+┌                    ┐
+│MOI.VariableIndex(1)│
+│MOI.VariableIndex(2)│
+│MOI.VariableIndex(3)│
+└                    ┘
+
+julia> set = MOI.PositiveSemidefiniteConeTriangle(2)
+MathOptInterface.PositiveSemidefiniteConeTriangle(2)
+
+julia> MOI.Utilities.operate(*, Float64, Diagonal(a), func)
+┌                                             ┐
+│0.0 + 1.0 MOI.VariableIndex(1)               │
+│0.0 + 1.4142135623730951 MOI.VariableIndex(2)│
+│0.0 + 1.0 MOI.VariableIndex(3)               │
+└                                             ┘
source

Constraint programming sets

MathOptInterface.AllDifferentType
AllDifferent(dimension::Int)

The set $\{x \in \mathbb{Z}^{d}\}$ such that no two elements in $x$ take the same value and dimension = d.

Also known as

This constraint is called all_different in MiniZinc, and is sometimes also called distinct.

Example

To enforce x[1] != x[2] AND x[1] != x[3] AND x[2] != x[3]:

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.AllDifferent(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.AllDifferent}(1)
source
MathOptInterface.BinPackingType
BinPacking(c::T, w::Vector{T}) where {T}

The set $\{x \in \mathbb{Z}^d\}$ where d = length(w), such that each item i in 1:d of weight w[i] is put into bin x[i], and the total weight of each bin does not exceed c.

There are additional assumptions that the capacity, c, and the weights, w, must all be non-negative.

The bin numbers depend on the bounds of x, so they may be something other than the integers 1:d.

Also known as

This constraint is called bin_packing in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> bins = MOI.add_variables(model, 5)
+5-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+
+julia> weights = Float64[1, 1, 2, 2, 3]
+5-element Vector{Float64}:
+ 1.0
+ 1.0
+ 2.0
+ 2.0
+ 3.0
+
+julia> MOI.add_constraint.(model, bins, MOI.Integer())
+5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(4)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(5)
+
+julia> MOI.add_constraint.(model, bins, MOI.Interval(4.0, 6.0))
+5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(2)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(3)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(4)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(5)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(bins), MOI.BinPacking(3.0, weights))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.BinPacking{Float64}}(1)
source
MathOptInterface.CircuitType
Circuit(dimension::Int)

The set $\{x \in \{1..d\}^d\}$ that constraints $x$ to be a circuit, such that $x_i = j$ means that $j$ is the successor of $i$, and dimension = d.

Graphs with multiple independent circuits, such as [2, 1, 3] and [2, 1, 4, 3], are not valid.

Also known as

This constraint is called circuit in MiniZinc, and it is equivalent to forming a (potentially sub-optimal) tour in the travelling salesperson problem.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Circuit(3))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Circuit}(1)
source
MathOptInterface.CountAtLeastType
CountAtLeast(n::Int, d::Vector{Int}, set::Set{Int})

The set $\{x \in \mathbb{Z}^{d_1 + d_2 + \ldots d_N}\}$, where x is partitioned into N subsets ($\{x_1, \ldots, x_{d_1}\}$, $\{x_{d_1 + 1}, \ldots, x_{d_1 + d_2}\}$ and so on), and at least $n$ elements of each subset take one of the values in set.

Also known as

This constraint is called at_least in MiniZinc.

Example

To ensure that 3 appears at least once in each of the subsets {a, b} and {b, c}:

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> a, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
+
+julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3))
+
+julia> x, d, set = [a, b, b, c], [2, 2], [3]
+(MathOptInterface.VariableIndex[MOI.VariableIndex(1), MOI.VariableIndex(2), MOI.VariableIndex(2), MOI.VariableIndex(3)], [2, 2], [3])
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.CountAtLeast(1, d, Set(set)))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountAtLeast}(1)
source
MathOptInterface.CountBelongsType
CountBelongs(dimenson::Int, set::Set{Int})

The set $\{(n, x) \in \mathbb{Z}^{1+d}\}$, such that n elements of the vector x take on of the values in set and dimension = 1 + d.

Also known as

This constraint is called among by MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+
+julia> set = Set([3, 4, 5])
+Set{Int64} with 3 elements:
+  5
+  4
+  3
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([n; x]), MOI.CountBelongs(4, set))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountBelongs}(1)
source
MathOptInterface.CountDistinctType
CountDistinct(dimension::Int)

The set $\{(n, x) \in \mathbb{Z}^{1+d}\}$, such that the number of distinct values in x is n and dimension = 1 + d.

Also known as

This constraint is called nvalues in MiniZinc.

Example

To model:

  • if n == 1`, thenx[1] == x[2] == x[3]`
  • if n == 2, then
    • x[1] == x[2] != x[3] or
    • x[1] != x[2] == x[3] or
    • x[1] == x[3] != x[2]
  • if n == 3, then x[1] != x[2], x[2] != x[3] and x[3] != x[1]
julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(vcat(n, x)), MOI.CountDistinct(4))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountDistinct}(1)

Relationship to AllDifferent

When the first element is d, CountDistinct is equivalent to an AllDifferent constraint.

source
MathOptInterface.CountGreaterThanType
CountGreaterThan(dimension::Int)

The set $\{(c, y, x) \in \mathbb{Z}^{1+1+d}\}$, such that c is strictly greater than the number of occurences of y in x and dimension = 1 + 1 + d.

Also known as

This constraint is called count_gt in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> y, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
+
+julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([c; y; x]), MOI.CountGreaterThan(5))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountGreaterThan}(1)
source
MathOptInterface.CumulativeType
Cumulative(dimension::Int)

The set $\{(s, d, r, b) \in \mathbb{Z}^{3n+1}\}$, representing the cumulative global constraint, where n == length(s) == length(r) == length(b) and dimension = 3n + 1.

Cumulative requires that a set of tasks given by start times $s$, durations $d$, and resource requirements $r$, never requires more than the global resource bound $b$ at any one time.

Also known as

This constraint is called cumulative in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> d = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+ MOI.VariableIndex(6)
+
+julia> r = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(7)
+ MOI.VariableIndex(8)
+ MOI.VariableIndex(9)
+
+julia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(10), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(10))
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([s; d; r; b]), MOI.Cumulative(10))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Cumulative}(1)
source
MathOptInterface.PathType
Path(from::Vector{Int}, to::Vector{Int})

Given a graph comprised of a set of nodes 1..N and a set of arcs 1..E represented by an edge from node from[i] to node to[i], Path constrains the set $(s, t, ns, es) \in (1..N)\times(1..E)\times\{0,1\}^N\times\{0,1\}^E$, to form subgraph that is a path from node s to node t, where node n is in the path if ns[n] is 1, and edge e is in the path if es[e] is 1.

The path must be acyclic, and it must traverse all nodes n for which ns[n] is 1, and all edges e for which es[e] is 1.

Also known as

This constraint is called path in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> N, E = 4, 5
+(4, 5)
+
+julia> from = [1, 1, 2, 2, 3]
+5-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 2
+ 3
+
+julia> to = [2, 3, 3, 4, 4]
+5-element Vector{Int64}:
+ 2
+ 3
+ 3
+ 4
+ 4
+
+julia> s, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
+
+julia> t, _ = MOI.add_constrained_variable(model, MOI.Integer())
+(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
+
+julia> ns = MOI.add_variables(model, N)
+4-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(3)
+ MOI.VariableIndex(4)
+ MOI.VariableIndex(5)
+ MOI.VariableIndex(6)
+
+julia> MOI.add_constraint.(model, ns, MOI.ZeroOne())
+4-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(4)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(5)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(6)
+
+julia> es = MOI.add_variables(model, E)
+5-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(7)
+ MOI.VariableIndex(8)
+ MOI.VariableIndex(9)
+ MOI.VariableIndex(10)
+ MOI.VariableIndex(11)
+
+julia> MOI.add_constraint.(model, es, MOI.ZeroOne())
+5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(7)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(8)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(9)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(10)
+ MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(11)
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables([s; t; ns; es]), MOI.Path(from, to))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Path}(1)
source
MathOptInterface.ReifiedType
Reified(set::AbstractSet)

The constraint $[z; f(x)] \in Reified(S)$ ensures that $f(x) \in S$ if and only if $z == 1$, where $z \in \{0, 1\}$.

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+MOIU.UniversalFallback{MOIU.Model{Float64}}
+fallback for MOIU.Model{Float64}
+
+julia> z, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
+(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1))
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(2)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.Utilities.vectorize([z, 2.0 * x]),
+           MOI.Reified(MOI.GreaterThan(1.0)),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Reified{MathOptInterface.GreaterThan{Float64}}}(1)
source
MathOptInterface.TableType
Table(table::Matrix{T}) where {T}

The set $\{x \in \mathbb{R}^d\}$ where d = size(table, 2), such that x belongs to one row of table. That is, there exists some j in 1:size(table, 1), such that x[i] = table[j, i] for all i=1:size(table, 2).

Also known as

This constraint is called table in MiniZinc.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> x = MOI.add_variables(model, 3)
+3-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+ MOI.VariableIndex(2)
+ MOI.VariableIndex(3)
+
+julia> table = Float64[1 1 0; 0 1 1; 1 0 1; 1 1 1]
+4×3 Matrix{Float64}:
+ 1.0  1.0  0.0
+ 0.0  1.0  1.0
+ 1.0  0.0  1.0
+ 1.0  1.0  1.0
+
+julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Table(table))
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Table{Float64}}(1)
source

Matrix sets

Matrix sets are vectorized to be subtypes of AbstractVectorSet.

For sets of symmetric matrices, storing both the (i, j) and (j, i) elements is redundant. Use the AbstractSymmetricMatrixSetTriangle set to represent only the vectorization of the upper triangular part of the matrix.

When the matrix of expressions constrained to be in the set is not symmetric, and hence additional constraints are needed to force the equality of the (i, j) and (j, i) elements, use the AbstractSymmetricMatrixSetSquare set.

The Bridges.Constraint.SquareBridge can transform a set from the square form to the triangular_form by adding appropriate constraints if the (i, j) and (j, i) expressions are different.

MathOptInterface.AbstractSymmetricMatrixSetTriangleType
abstract type AbstractSymmetricMatrixSetTriangle <: AbstractVectorSet end

Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row). A vectorized cone of dimension $n$ corresponds to a square matrix with side dimension $\sqrt{1/4 + 2 n} - 1/2$. (Because a $d \times d$ matrix has $d(d + 1) / 2$ elements in the upper or lower triangle.)

Example

The matrix

\[\begin{bmatrix} + 1 & 2 & 4\\ + 2 & 3 & 5\\ + 4 & 5 & 6 +\end{bmatrix}\]

has side_dimension 3 and vectorization $(1, 2, 3, 4, 5, 6)$.

Note

Two packed storage formats exist for symmetric matrices, the respective orders of the entries are:

  • upper triangular column by column (or lower triangular row by row);
  • lower triangular column by column (or upper triangular row by row).

The advantage of the first format is the mapping between the (i, j) matrix indices and the k index of the vectorized form. It is simpler and does not depend on the side dimension of the matrix. Indeed,

  • the entry of matrix indices (i, j) has vectorized index k = div((j - 1) * j, 2) + i if $i \leq j$ and k = div((i - 1) * i, 2) + j if $j \leq i$;
  • and the entry with vectorized index k has matrix indices i = div(1 + isqrt(8k - 7), 2) and j = k - div((i - 1) * i, 2) or j = div(1 + isqrt(8k - 7), 2) and i = k - div((j - 1) * j, 2).

Duality note

The scalar product for the symmetric matrix in its vectorized form is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries; see [p. 634, 1]. This has important consequence for duality.

Consider for example the following problem (PositiveSemidefiniteConeTriangle is a subtype of AbstractSymmetricMatrixSetTriangle)

\[\begin{align*} + & \max_{x \in \mathbb{R}} & x + \\ + & \;\;\text{s.t.} & + (1, -x, 1) & \in \text{PositiveSemidefiniteConeTriangle}(2). +\end{align*}\]

The dual is the following problem

\[\begin{align*} + & \min_{x \in \mathbb{R}^3} & y_1 + y_3 + \\ + & \;\;\text{s.t.} & 2y_2 & = 1\\ + & & y & \in \text{PositiveSemidefiniteConeTriangle}(2). +\end{align*}\]

Why do we use $2y_2$ in the dual constraint instead of $y_2$ ? The reason is that $2y_2$ is the scalar product between $y$ and the symmetric matrix whose vectorized form is $(0, 1, 0)$. Indeed, with our modified scalar products we have

\[\langle +(0, 1, 0), +(y_1, y_2, y_3) +\rangle += +\mathrm{trace} +\begin{pmatrix} + 0 & 1\\ + 1 & 0 +\end{pmatrix} +\begin{pmatrix} + y_1 & y_2\\ + y_2 & y_3 +\end{pmatrix} += 2y_2.\]

References

[1] Boyd, S. and Vandenberghe, L.. Convex optimization. Cambridge university press, 2004.

source
MathOptInterface.AbstractSymmetricMatrixSetSquareType
abstract type AbstractSymmetricMatrixSetSquare <: AbstractVectorSet end

Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to have its triangular_form belong to the corresponding set. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.

Example

PositiveSemidefiniteConeSquare is a subtype of AbstractSymmetricMatrixSetSquare and constraining the matrix

\[\begin{bmatrix} + 1 & -y\\ + -z & 0\\ +\end{bmatrix}\]

to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2). It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2), since triangular_form(PositiveSemidefiniteConeSquare) is PositiveSemidefiniteConeTriangle.

source

List of recognized matrix sets.

MathOptInterface.PositiveSemidefiniteConeSquareType
PositiveSemidefiniteConeSquare(side_dimension::Int) <: AbstractSymmetricMatrixSetSquare

The cone of symmetric positive semidefinite matrices, with non-negative side length side_dimension.

See AbstractSymmetricMatrixSetSquare for more details on the vectorized form.

The entries of the matrix are given column by column (or equivalently, row by row).

The matrix is both constrained to be symmetric and to be positive semidefinite. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.

Example

Constraining the matrix

\[\begin{bmatrix} + 1 & -y\\ + -z & 0\\ +\end{bmatrix}\]

to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2).

It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2).

source
MathOptInterface.HermitianPositiveSemidefiniteConeTriangleType
HermitianPositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractVectorSet

The (vectorized) cone of Hermitian positive semidefinite matrices, with non-negative side_dimension rows and columns.

Becaue the matrix is Hermitian, the diagonal elements are real, and the complex-valued lower triangular entries are obtained as the conjugate of corresponding upper triangular entries.

Vectorization format

The vectorized form starts with real part of the entries of the upper triangular part of the matrix, given column by column as explained in AbstractSymmetricMatrixSetSquare.

It is then followed by the imaginary part of the off-diagonal entries of the upper triangular part, also given column by column.

For example, the matrix

\[\begin{bmatrix} + 1 & 2 + 7im & 4 + 8im\\ + 2 - 7im & 3 & 5 + 9im\\ + 4 - 8im & 5 - 9im & 6 +\end{bmatrix}\]

has side_dimension 3 and is represented as the vector $[1, 2, 3, 4, 5, 6, 7, 8, 9]$.

source
MathOptInterface.LogDetConeTriangleType
LogDetConeTriangle(side_dimension::Int)

The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d(d+1)/2} : t \le u \log(\det(X/u)), u > 0 \}$, where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.

The non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; X]),
+           MOI.LogDetConeTriangle(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeTriangle}(1)
source
MathOptInterface.LogDetConeSquareType
LogDetConeSquare(side_dimension::Int)

The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d^2} : t \le u \log(\det(X/u)), X \text{ symmetric}, u > 0 \}$, where the matrix X is represented in the same format as in the PositiveSemidefiniteConeSquare.

Similarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.

The non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 4), 2, 2)
+2×2 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.LogDetConeSquare(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeSquare}(1)
source
MathOptInterface.RootDetConeTriangleType
RootDetConeTriangle(side_dimension::Int)

The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d(d+1)/2} : t \le \det(X)^{1/d} \}$, where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.

The non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = MOI.add_variables(model, 3);
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; X]),
+           MOI.RootDetConeTriangle(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeTriangle}(1)
source
MathOptInterface.RootDetConeSquareType
RootDetConeSquare(side_dimension::Int)

The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d^2} : t \le \det(X)^{1/d}, X \text{ symmetric} \}$, where the matrix X is represented in the same format as PositiveSemidefiniteConeSquare.

Similarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.

The non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.

Example

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> t = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> X = reshape(MOI.add_variables(model, 4), 2, 2)
+2×2 Matrix{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(2)  MOI.VariableIndex(4)
+ MOI.VariableIndex(3)  MOI.VariableIndex(5)
+
+julia> MOI.add_constraint(
+           model,
+           MOI.VectorOfVariables([t; vec(X)]),
+           MOI.RootDetConeSquare(2),
+       )
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeSquare}(1)
source
diff --git a/previews/PR2418/reference/variables/index.html b/previews/PR2418/reference/variables/index.html new file mode 100644 index 0000000000..1fd7f0541e --- /dev/null +++ b/previews/PR2418/reference/variables/index.html @@ -0,0 +1,24 @@ + +Variables · MathOptInterface

Variables

Functions

MathOptInterface.add_variablesFunction
add_variables(model::ModelLike, n::Int)::Vector{VariableIndex}

Add n scalar variables to the model, returning a vector of variable indices.

A AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.

source
MathOptInterface.add_constrained_variableFunction
add_constrained_variable(
+    model::ModelLike,
+    set::AbstractScalarSet
+)::Tuple{MOI.VariableIndex,
+         MOI.ConstraintIndex{MOI.VariableIndex, typeof(set)}}

Add to model a scalar variable constrained to belong to set, returning the index of the variable created and the index of the constraint constraining the variable to belong to set.

By default, this function falls back to creating a free variable with add_variable and then constraining it to belong to set with add_constraint.

source
MathOptInterface.add_constrained_variablesFunction
add_constrained_variables(
+    model::ModelLike,
+    sets::AbstractVector{<:AbstractScalarSet}
+)::Tuple{
+    Vector{MOI.VariableIndex},
+    Vector{MOI.ConstraintIndex{MOI.VariableIndex,eltype(sets)}},
+}

Add to model scalar variables constrained to belong to sets, returning the indices of the variables created and the indices of the constraints constraining the variables to belong to each set in sets. That is, if it returns variables and constraints, constraints[i] is the index of the constraint constraining variable[i] to belong to sets[i].

By default, this function falls back to calling add_constrained_variable on each set.

source
add_constrained_variables(
+    model::ModelLike,
+    set::AbstractVectorSet,
+)::Tuple{
+    Vector{MOI.VariableIndex},
+    MOI.ConstraintIndex{MOI.VectorOfVariables,typeof(set)},
+}

Add to model a vector of variables constrained to belong to set, returning the indices of the variables created and the index of the constraint constraining the vector of variables to belong to set.

By default, this function falls back to creating free variables with add_variables and then constraining it to belong to set with add_constraint.

source
MathOptInterface.supports_add_constrained_variableFunction
supports_add_constrained_variable(
+    model::ModelLike,
+    S::Type{<:AbstractScalarSet}
+)::Bool

Return a Bool indicating whether model supports constraining a variable to belong to a set of type S either on creation of the variable with add_constrained_variable or after the variable is created with add_constraint.

By default, this function falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VariableIndex, S) which is the correct definition for most models.

Example

Suppose that a solver supports only two kind of variables: binary variables and continuous variables with a lower bound. If the solver decides not to support VariableIndex-in-Binary and VariableIndex-in-GreaterThan constraints, it only has to implement add_constrained_variable for these two sets which prevents the user to add both a binary constraint and a lower bound on the same variable. Moreover, if the user adds a VariableIndex-in-GreaterThan constraint, implementing this interface (that is, supports_add_constrained_variables) enables the constraint to be transparently bridged into a supported constraint.

source
MathOptInterface.supports_add_constrained_variablesFunction
supports_add_constrained_variables(
+    model::ModelLike,
+    S::Type{<:AbstractVectorSet}
+)::Bool

Return a Bool indicating whether model supports constraining a vector of variables to belong to a set of type S either on creation of the vector of variables with add_constrained_variables or after the variable is created with add_constraint.

By default, if S is Reals then this function returns true and otherwise, it falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VectorOfVariables, S) which is the correct definition for most models.

Example

In the standard conic form (see Duality), the variables are grouped into several cones and the constraints are affine equality constraints. If Reals is not one of the cones supported by the solvers then it needs to implement supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false as free variables are not supported. The solvers should then implement supports_add_constrained_variables(::Optimizer, ::Type{<:SupportedCones}) = true where SupportedCones is the union of all cone types that are supported; it does not have to implement the method supports_constraint(::Type{VectorOfVariables}, Type{<:SupportedCones}) as it should return false and it's the default. This prevents the user to constrain the same variable in two different cones. When a VectorOfVariables-in-S is added, the variables of the vector have already been created so they already belong to given cones. If bridges are enabled, the constraint will therefore be bridged by adding slack variables in S and equality constraints ensuring that the slack variables are equal to the corresponding variables of the given constraint function.

Note that there may also be sets for which !supports_add_constrained_variables(model, S) and supports_constraint(model, MOI.VectorOfVariables, S). For instance, suppose a solver supports positive semidefinite variable constraints and two types of variables: binary variables and nonnegative variables. Then the solver should support adding VectorOfVariables-in-PositiveSemidefiniteConeTriangle constraints, but it should not support creating variables constrained to belong to the PositiveSemidefiniteConeTriangle because the variables in PositiveSemidefiniteConeTriangle should first be created as either binary or non-negative.

source
MathOptInterface.is_validMethod
is_valid(model::ModelLike, index::Index)::Bool

Return a Bool indicating whether this index refers to a valid object in the model model.

source
MathOptInterface.deleteMethod
delete(model::ModelLike, index::Index)

Delete the referenced object from the model. Throw DeleteNotAllowed if if index cannot be deleted.

The following modifications also take effect if Index is VariableIndex:

  • If index used in the objective function, it is removed from the function, that is, it is substituted for zero.
  • For each func-in-set constraint of the model:
    • If func isa VariableIndex and func == index then the constraint is deleted.
    • If func isa VectorOfVariables and index in func.variables then
      • if length(func.variables) == 1 is one, the constraint is deleted;
      • if length(func.variables) > 1 and supports_dimension_update(set) then then the variable is removed from func and set is replaced by update_dimension(set, MOI.dimension(set) - 1).
      • Otherwise, a DeleteNotAllowed error is thrown.
    • Otherwise, the variable is removed from func, that is, it is substituted for zero.
source
MathOptInterface.deleteMethod
delete(model::ModelLike, indices::Vector{R<:Index}) where {R}

Delete the referenced objects in the vector indices from the model. It may be assumed that R is a concrete type. The default fallback sequentially deletes the individual items in indices, although specialized implementations may be more efficient.

source

Attributes

MathOptInterface.VariableNameType
VariableName()

A variable attribute for a string identifying the variable. It is valid for two variables to have the same name; however, variables with duplicate names cannot be looked up using get. It has a default value of "" if not set`.

source
MathOptInterface.VariablePrimalStartType
VariablePrimalStart()

A variable attribute for the initial assignment to some primal variable's value that the optimizer may use to warm-start the solve. May be a number or nothing (unset).

source
MathOptInterface.VariablePrimalType
VariablePrimal(result_index::Int = 1)

A variable attribute for the assignment to some primal variable's value in result result_index. If result_index is omitted, it is 1 by default.

If the solver does not have a primal value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariablePrimal attribute.

See ResultCount for information on how the results are ordered.

source
MathOptInterface.VariableBasisStatusType
VariableBasisStatus(result_index::Int = 1)

A variable attribute for the BasisStatusCode of a variable in result result_index, with respect to an available optimal solution basis.

If the solver does not have a basis statue for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariableBasisStatus attribute.

See ResultCount for information on how the results are ordered.

source
diff --git a/previews/PR2418/release_notes/index.html b/previews/PR2418/release_notes/index.html new file mode 100644 index 0000000000..5886071175 --- /dev/null +++ b/previews/PR2418/release_notes/index.html @@ -0,0 +1,30 @@ + +Release notes · MathOptInterface

Release notes

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

v1.25.2 (January 29, 2024)

Fixed

Other

  • Clarified ordering of nonlinear tape in documentation (#2401)
  • Updated vale.sh (#2403) (#2404)
  • Tidied `src/Utilities/results.jl (#2411)

v1.25.1 (January 11, 2024)

Fixed

Other

  • Removed a duplicated test (#2395)

v1.25.0 (January 5, 2024)

Added

  • Added the AutomaticDifferentiationBackend attribute (#2386)

Fixed

v1.24.0 (January 2, 2024)

Added

  • Added get_fallback for ConstraintDual of variable bounds (#2373)

Fixed

  • Fixed RSOCtoPSDBridge for dimension 2 (#2359)
  • Fixed getting ConstraintFunction in conversion bridge (#2360)
  • Fixed map_indices (#2367)
  • Fixed SlackBridgePrimalDualStart for non-slack bridges (#2365)
  • Fixed test_attribute_TimeLimitSec (#2370)
  • Fixed order of model attributes during copy_to (#2372)
  • Fixed ConstraintIndex conflicts between variable and constraint bridges (#2362)
  • Fixed corner-case deletion in bridges (#2377)
  • Fixed ListOfVariablesWithAttributeSet for variable bridges (#2380)
  • Fixed SlackBridge if scalar constant is not zero (#2382)
  • Fixed setting multiple bounds on a bridged variable (#2383)

Other

  • Minor documentation improvements (#2355), (#2374)
  • Improved side_dimension_for_vectorized_dimension (#2356)
  • Added DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)
  • Refactored SDPAModel into a separate test file and test more widely (#2364), (#2357)

v1.23.0 (November 29, 2023)

Added

Fixed

  • Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)
  • Fixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)

v1.22.0 (November 6, 2023)

Added

Fixed

Other

  • Fixed typo in docstring of ScalarAffineFunction (#2326)
  • Added Gurobi to solver-tests.yml (#2332)
  • Improved the error message when a bridge does not support an attribute (#2329)
  • Improved documentation for implementing a bridge (#2334)
  • Updated [compat] bounds in Project.toml (#2344)

v1.21.0 (October 25, 2023)

Added

Fixed

  • Fixed test_attribute_TimeLimitSec (#2256)
  • Fixed conversion cost in objective bridges (#2309)

Other

  • Fixed flakey link checking in documentation (#2297)
  • Minor documentation fixes (#2304) (#2313)
  • Fixed [compat] section of Project.toml (#2310)
  • Added MultiObjectiveAlgorithms to solver-tests.yml (#2312)

v1.20.1 (September 24, 2023)

Fixed

Other

  • Added MathOptSetDistances to solver-tests.yml (#2265)
  • Updated Documenter (#2266)
  • Fixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)
  • Various style improvements
    • Replaced using Package with import Package where possible (#2274)
    • Removed Utilities.EMPTYSTRING (#2283)
    • Removed unnecessary const acronyms in Utilities (#2280) (#2281)
    • Removed invalid and unused method (#2286)
  • Refactored src/Utilities/model.jl (#2287)

v1.20.0 (September 7, 2023)

Added

Other

v1.19.0 (August 15, 2023)

Added

Fixed

Other

  • Added extensions to solver-tests.yml (#2229)
  • Refactored test/Benchmarks (#2234)
  • Fixed warnings in tests (#2241) (#2243)
  • Small refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)
  • Fixed various typos (#2251) (#2255)
  • Partitioned how we run the tests on GitHub actions (#2252) (#2253)

v1.18.0 (June 23, 2023)

Added

Fixed

  • Fixed a missing @require in MOI.Test (#2195) (#2196)
  • Fixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)
  • Fixed splatting nonlinear expression with univariate operator (#2221)

Other

  • Removed unused argument names (#2199)
  • Reduced memory requirement for tests (#2204)
  • Refactored Utilities.promote_operation (#2206)
  • Improved code style in Utilities/mutable_arithmetics.jl (#2209)
  • Refactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)

v1.17.1 (June 6, 2023)

Fixed

Other

  • Added documentation for enum instances (#2186)
  • Updated chatroom links in documentation (#2188)
  • Changed the documentation to build on Julia v1.9 (#2191)

v1.17.0 (June 1, 2023)

Added

Fixed

  • Fixed support for external sets in Utilities.loadfromstring! (#2177)
  • Fixed promote_operation for ScalarNonlinearFunction (#2179)
  • Fixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)

v1.16.0 (May 16, 2023)

Added

Fixed

Other

  • Fixed solver-tests.yml (#2157)
  • Updated documentation links to developer chatroom (#2160)
  • Added various tests for bridges (#2156)
  • Added checklists to the developer documentation (#2167) (#2168)

v1.15.1 (April 25, 2023)

Fixed

  • Fixed deleting a variable in a bridged objective (#2150)

v1.15.0 (April 19, 2023)

Added

Fixed

Other

  • Add a test for variables in one-sided open Interval sets (#2133)
  • Minor style fixes in the source code (#2148)

v1.14.1 (April 6, 2023)

Fixed

Other

v1.14.0 (April 4, 2023)

Added

Fixed

v1.13.2 (March 21, 2023)

Fixed

Other

  • Fixed typos in the documentation (#2114)
  • Functions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)

v1.13.1 (March 3, 2023)

Other

  • Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)
  • Improved the docstrings in src/functions.jl (#2108)

v1.13.0 (February 28, 2023)

Added

Fixed

Other

  • Added tests for vector-valued objective functions in FileFormats.MOF (#2093)
  • Used and documented preference for import MathOptInterface as MOI (#2096)
  • Fix and test links in the documentation with linkcheck = true (#2098)
  • Improved docstrings of sets in src/sets.jl (#2099)
  • Skip checking flakey links in documentation with linkcheck_ignore (#2103)

v1.12.0 (February 10, 2023)

Added

Fixed

  • Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)

Other

v1.11.5 (January 24, 2023)

Fixed

  • Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)

Other

  • Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)

v1.11.4 (January 12, 2023)

Fixed

  • Fixed a bug reading .lp files with an Integer section (#2078)

v1.11.3 (January 12, 2023)

Fixed

  • Fixed a performance bug when deleting a vector of constraints (#2072)
  • Fixed a bug reading .lp files with terms like x -1 y (#2076)

Other

v1.11.2 (January 2, 2023)

Fixed

  • Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)
  • Fixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)

v1.11.1 (December 22, 2022)

Fixed

  • Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)

v1.11.0 (December 2, 2022)

Added

Other

  • Tidied these release notes (#2055)

v1.10.0 (November 22, 2022)

Added

Fixed

  • Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)
  • Fixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)
  • Fixed reading of free variables in FileFormats.LP (#2044)
  • Fixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)
  • Fixed situations in which x^y returns a complex value in Nonlinear (#2050)

Other

  • Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)
  • Removed specialized iterators for keys and values in Utilities.CleverDicts (#2051)

v1.9.0 (October 29, 2022)

Added

Fixed

  • Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)
  • Fixed reading free rows in FileFormats.MPS files (#2009)
  • Fixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)
  • Fixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)
  • Fixed the requirements check in Test.test_constraint_get_ConstraintIndex (#2024)

v1.8.2 (September 20, 2022)

Documentation

  • Added vale as a documentation linter (#2002)
  • Improved styling of code blocks in the PDF (#1999) (#2000)
  • Fixed a number of typos in the documentation (#2001) (#2003)

v1.8.1 (September 12, 2022)

Fixed

  • Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)

v1.8.0 (September 1, 2022)

Added

Fixed

  • Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)
  • Allow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)

v1.7.0 (August 16, 2022)

Added

Fixed

  • Fixed some missing promotion rules

Other

  • Improved the performance of Jacobian products in Nonlinear
  • Removed an un-needed copy in Utilities.modify_function
  • Various clean-ups in Bridges/bridge_optimizer.jl

v1.6.1 (July 23, 2022)

Fixed

  • Added support for ExponentialCone in MatrixOfConstraints
  • Fix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint

v1.6.0 (July 2, 2022)

Added

  • Added Bridges.needs_final_touch and Bridges.final_touch
  • Added new bridges from constraint programming sets to mixed-integer linear programs:
    • AllDifferentToCountDistinctBridge
    • CountAtLeastToCountBelongsBridge
    • CountBelongsToMILPBridge
    • CountDistinctToMILPBridge
    • CountGreaterThanToMILPBridge
    • CircuitToMILPBridge

Fixed

  • Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear
  • Fix BinPackingToMILPBridge to respect variable bounds
  • Fix SemiToBinaryBridge to throw error if other bounds are set

v1.5.0 (June 27, 2022)

Added

  • Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error
  • Added Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue
  • Added new bridges:
    • RootDetConeSquare to RootDetConeTriangle
    • LogDetConeSquare to LogDetConeTriangle
    • BinPacking to a mixed-integer linear program
    • Table to a mixed-integer linear program
  • Added Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer

Fixed

  • Fixed ZeroOne tests with lower and upper bounds
  • Fixed error in FileFormats.LP when reading a malformed file
  • Fixed reading of nonlinear programs in FileFormats.MOF
  • Fixed bug in ConstraintDual when using SquareBridge

Other

  • Improved documentation of nonlinear API
  • Documented duality convention for PositiveSemidefiniteConeSquare sets
  • Fixed typo in Bridges.Constraint.QuadToSOCBridge docstring

v1.4.0 (June 9, 2022)

Added

  • Added a number of sets for constraint programming:
    • AllDifferent
    • BinPacking
    • Circuit
    • CountAtLeast
    • CountBelongs
    • CountDistinct
    • CountGreaterThan
    • Cumulative
    • Path
    • Table
  • Added support for user-defined hessians in Nonlinear
  • Added Bridges.runtests to simplify the testing of bridge implementations

Fixed

  • Fixed a bug in FileFormats.NL when writing univariate *

Other

  • Began a large refactoring of the Bridges submodule, with greatly improved documentation.

v1.3.0 (May 27, 2022)

Added

  • Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.
  • Add FileFormats.NL.SolFileResults(::IO, ::Model)
  • Add FileFormats.NL.read!(::IO, ::Model)
  • Add MOI.modify that accepts a vector of modifications

Fixed

  • Fixed a bug in Test which attempted to include non-.jl files
  • Fixed a bug in FileFormats for models with open interval constraints

Other

  • Fixed a performance issue in Utilities.DoubleDict
  • Various minor improvements to the documentation

v1.2.0 (April 25, 2022)

Added

  • Add support for the FORMAT_REW/.rew file format in FileFormats.

Fixed

  • Fix bug handling of default variable bounds in FileFormats.LP
  • Fix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.

v1.1.2 (March 31, 2022)

Fixed

  • Fix a range of bugs in FileFormats.LP
  • Fix reading of problem dimensions in FileFormats.SDPA

v1.1.1 (March 23, 2022)

Fixed

  • Fix bug in test_model_UpperBoundAlreadySet
  • Fix bug in test_infeasible_ tests
  • Fix bug in test_objective_ObjectiveFunction_blank
  • Relax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.

New tests

  • Add test_conic_empty_matrix that checks conic solvers support problems with no variables.

v1.1.0 (March 2, 2022)

Added

  • Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.

v1.0.2 (March 1, 2022)

Fixed

  • Fixed a bug in the test_model_ScalarFunctionConstantNotZero test
  • Fixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute
  • Identified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.

v1.0.1 (February 25, 2022)

Fixed

  • Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer
  • Fixed a bug in which shift_constant did not promote mixed types of coefficients
  • Fixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed
  • Fixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function
  • Fixed a bug when modifying scalar constants of a function containing a bridged variable
  • Fixed a bug in which final_touch was not always called with a CachingOptimizer

v1.0.0 (February 17, 2022)

Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.

Breaking

  • Julia 1.6 is now the minimum supported version
  • All deprecations have been removed

Troubleshooting problems when updating

If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)

To find the deprecated features you are using, start Julia with --depwarn=yes:

$ julia --depwarn=yes

Then install MathOptInterface v0.10.9:

julia> using Pkg
+julia> pkg"add MathOptInterface@0.10"

And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.

v0.10.9 (February 16, 2022)

Added

  • Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers
  • Added MOI.default_cache for specifying the model used in CachingOptimizer

Fixed

  • Fixed LaTeX printing of MOI.Interval sets

Other

  • Added Aqua.jl as a CI check, and fixed suggested issues
  • The constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.

v0.10.8 (February 3, 2022)

Added

  • Added a Base.read! for FileFormats.LP.

Fixed

  • Fixed a bug in MutableSparseMatrix
  • Fixed a bug when calling operate!(vcat, ...) with Number arguments
  • Removed unintended export of deprecated symbols
  • Fixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.

v0.10.7 (January 5, 2022)

Added

  • Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.

Fixed

  • Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.
  • Fixed an error message in FileFormats.CBF
  • Fixed comparison in test_linear_integration_Interval
  • Fixed errors for ConstraintPrimal in a CachingOptimizer
  • Fixed printing of models with non-Float64 coefficients.

Other

  • Various improvements to reduce time-to-first-solve latency
  • Improved error message when an optimizer does not support compute_conflict!

v0.10.6 (November 30, 2021)

Added

  • Added new documentation and tests for infeasibility certificates
  • Added a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v"0.10.5" to run tests added in v0.10.5 and earlier.
  • MOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).
  • Added infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE
  • CachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.

Fixed

  • Fixed a StackOverflow bug in copy_to
  • Fixed error thrown when nonconvex quadratic constraints cannot be bridged
  • Fixed a bug in copy_to for FileFormats.NL.Model
  • Fixed a bug in FileFormats.NL when printing large integers
  • Remove a common test failure for LowerBoundAlreadySet tests
  • Utilities.num_rows is now exported
  • Remove parts of failing test_model_copy_to_xxx tests due to bridges

v0.10.5 (November 7, 2021)

Fixed

  • Fixed getter in UniversalFallback
  • Fixed test_solve_conflict_zeroone_ii

Other

  • Make normalize_and_add_constraint more flexible
  • Update paper BibTeX

v0.10.4 (October 26, 2021)

Added

  • Add SolverVersion attribute
  • Add new tests:
    • test_solve_conflict_zeroone_ii
    • test_nonlinear_objective
  • Utilities.VariablesContainer now supports ConstraintFunction and ConstraintSet
  • The documentation is now available as a PDF

Other

  • Update to MutableArithmetics 0.3
  • Various improvements to the documentation

v0.10.3 (September 18, 2021)

Fixed

  • Fixed bug which prevented callbacks from working through a CachingOptimizer
  • Fixed bug in Test submodule

v0.10.2 (September 16, 2021)

  • Updated MathOptFormat to v1.0
  • Updated JSONSchema to v1.0
  • Added Utilities.set_with_dimension
  • Added two-argument optimize!(::AbstractOptimizer, ::ModelLike)
  • The experimental feature copy_to_and_optimize! has been removed
  • Det bridges now support getting ConstraintFunction and ConstraintSet
  • Various minor bug fixes identified by improved testing

v0.10.1 (September 8, 2021)

  • Various fixes to MOI.Test

v0.10.0 (September 6, 2021)

MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.

Breaking in MOI

  • SingleVariable has been removed; use VariableIndex instead
  • SingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError
  • SettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed
  • VariableIndex constraints should not support ConstraintName
  • VariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead
  • ListOfConstraints has been renamed to ListOfConstraintTypesPresent
  • ListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}
  • SolveTime has been renamed to SolveTimeSec
  • IndicatorSet has been renamed to Indicator
  • RawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument
  • The .N field in result attributes has been renamed to .result_index
  • The .variable_index field in ScalarAffineTerm has been renamed to .variable
  • The .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1
  • The .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2
  • The order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.
  • The index_value function has been removed. Use .value instead.
  • isapprox has been removed for SOS1 and SOS2.
  • The dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.
  • copy_to no longer takes keyword arguments:
    • copy_names: now copy names if they are supported by the destination solver
    • filter_constraints: use Utilities.ModelFilter instead
    • warn_attributes: never warn about optimizer attributes

Breaking in Bridges

  • Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge
  • Constraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge
  • Bridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.
  • Bridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges
  • The signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).

Breaking in FileFormats

  • FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.

Breaking in Utilities

  • The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.
  • Utilities.supports_default_copy has been renamed to supports_incremental_interface
  • Utilities.automatic_copy_to has been renamed to Utilities.default_copy_to
  • The allocate-load API has been removed
  • CachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.
  • The field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.
  • The size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.
  • The size argument to Utilities.IndexMap(::Integer) has been removed.
  • Utilities.DoubleDicts have been significantly refactored. Consult the source code for details.
  • Utilities.test_models_equal has been moved to MOI.Test

Breaking in Test

  • MOI.Test has been renamed to MOI.DeprecatedTest
  • An entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.

Other changes:

  • attribute_value_type has been added
  • copy_to_and_optimize! has been added
  • VariableBasisStatus has been added
  • print(model) now prints a human-readable description of the model
  • Various improvements to the FileFormats submodule
    • FileFormats.CBF was refactored and received bugfixes
    • Support for MathOptFormat v0.6 was added in FileFormats.MOF
    • FileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.
    • FileFormats.NL has been added to support nonlinear files
  • Improved type inference throughout to reduce latency

Updating

A helpful script when updating is:

for (root, dirs, files) in walkdir(".")
+    for file in files
+        if !endswith(file, ".jl")
+            continue
+        end
+        path = joinpath(root, file)
+        s = read(path, String)
+        for pair in [
+            ".variable_index" => ".variable",
+            "RawParameter" => "RawOptimizerAttribute",
+            "ListOfConstraints" => "ListOfConstraintTypesPresent",
+            "TestConfig" => "Config",
+            "attr.N" => "attr.result_index",
+            "SolveTime" => "SolveTimeSec",
+            "DataType" => "Type",
+            "Utilities.supports_default_copy_to" =>
+                "supports_incremental_interface",
+            "SingleVariableConstraintNameError" =>
+                "VariableIndexConstraintNameError",
+            "SettingSingleVariableFunctionNotAllowed" =>
+                "SettingVariableIndexFunctionNotAllowed",
+            "automatic_copy_to" => "default_copy_to",
+        ]
+            s = replace(s, pair)
+        end
+        write(path, s)
+    end
+end

v0.9.22 (May 22, 2021)

This release contains backports from the ongoing development of the v0.10 release.

  • Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.
  • Improved performance of Utilities.is_canonical.
  • Fixed Utilities.pass_nonvariable_constraints with bridged variables.
  • Fixed performance regression of Utilities.Model.
  • Fixed ordering of objective setting in parser.

v0.9.21 (April 23, 2021)

  • Added supports_shift_constant.
  • Improve performance of bridging quadratic constraints.
  • Add precompilation statements.
  • Large improvements to the documentation.
  • Fix a variety of inference issues, benefiting precompilation and reducing initial latency.
  • RawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.
  • Utilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.

v0.9.20 (February 20, 2021)

  • Improved performance of Utilities.ScalarFunctionIterator
  • Added support for compute_conflict to MOI layers
  • Added test with zero off-diagonal quadratic term in objective
  • Fixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints
  • Fixed modification of un-set objective
  • Fixed function modification with duplicate terms
  • Made unit tests abort without failing if the problem class is not supported
  • Formatted code with JuliaFormatter
  • Clarified BasisStatusCode's docstring

v0.9.19 (December 1, 2020)

  • Added CallbackNodeStatus attribute
  • Added bridge from GreaterThan or LessThan to Interval
  • Added tests for infeasibility certificates and double optimize
  • Fixed support for Julia v1.6
  • Re-organized MOI docs and added documentation for adding a test

v0.9.18 (November 3, 2020)

  • Various improvements for working with complex numbers
  • Added GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint

v0.9.17 (September 21, 2020)

  • Fixed CleverDict with variable of negative index value
  • Implement supports_add_constrained_variable for MockOptimizer

v0.9.16 (September 17, 2020)

  • Various fixes:
    • 32-bit support
    • CleverDict with abstract value type
    • Checks in test suite

v0.9.15 (September 14, 2020)

  • Bridges improvements:
    • (R)SOCtoNonConvexQuad bridge
    • ZeroOne bridge
    • Use supports_add_constrained_variable in LazyBridgeOptimizer
    • Exposed VariableBridgeCost and ConstraintBridgeCost attributes
    • Prioritize constraining variables on creation according to these costs
    • Refactor bridge debugging
  • Large performance improvements across all submodules
  • Lots of documentation improvements
  • FileFormats improvements:
    • Update MathOptFormat to v0.5
    • Fix supported objectives in FileFormats
  • Testing improvements:
    • Add name option for basic_constraint_test
  • Bug fixes and missing methods
    • Add length for iterators
    • Fix bug with duplicate terms
    • Fix order of LinearOfConstraintIndices

v0.9.14 (May 30, 2020)

  • Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).
  • Bump JSONSchema dependency from v0.2 to v0.3 (#1090).
  • Documentation improvements:
    • Fix typos (#1054, #1060, #1061, #1064, #1069, #1070).
    • Remove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).
  • Utilities improvements:
    • Fix is_canonical for quadratic functions (#1081, #1089).
    • Implement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).
    • Add support for custom objective functions for UniversalFallback (#1086).
    • Deterministic ordering of constraints in UniversalFallback (#1088).
  • Testing improvements:
    • Add NormOneCone/NormInfinityCone tests (#1045).
  • Bridges improvements:
    • Add bridges from Semiinteger and Semicontinuous (#1059).
    • Implement getting ConstraintSet for Variable.FlipSignBridge (#1066).
    • Fix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).
    • Fix NormOne/NormInf bridges with nonzero constants (#1045).
    • Fix StackOverflow in debug (#1063).
  • FileFormats improvements:
    • [SDPA] Implement the extension for integer variables (#1079).
    • [SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).
    • [SDPA] No scaling of off-diagonal coefficient (#1076).
    • [SDPA] Add missing negation of constant (#1075).

v0.9.13 (March 24, 2020)

  • Added tests for Semicontinuous and Semiinteger variables (#1033).
  • Added tests for using ExprGraphs from NLP evaluators (#1043).
  • Update version compatibilities of dependencies (#1034, #1051, #1052).
  • Fixed typos in documentation (#1044).

v0.9.12 (February 28, 2020)

  • Fixed writing NLPBlock in MathOptFormat (#1037).
  • Fixed MockOptimizer for result attributes with non-one result index (#1039).
  • Updated test template with instantiate (#1032).

v0.9.11 (February 21, 2020)

  • Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).
  • Described dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).
  • Fixed typos in documentation (#1022, #1024).
  • Fixed warning of unsupported attribute (#1027).
  • Added more rootdet/logdet conic tests (#1026).
  • Implemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).

v0.9.10 (January 31, 2020)

  • Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).
  • Added RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).
  • Added NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).
  • Added supports_constrained_variable(s) (#1004).
  • Added dual_set_type (#1002).
  • Added tests for vector specialized version of delete (#989, #1011).
  • Added PSD3 test (#1007).
  • Clarified dual solution of Tests.pow1v and Tests.pow1f (#1013).
  • Added support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).
  • Fixed Utilities.vectorize for empty vector (#1003).
  • Fixed free variables in LP writer (#1006).

v0.9.9 (December 29, 2019)

  • Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).
  • Improved performance of deletion of vector of variables in MOI.Utilities.Model (#983).
  • Updated to MutableArithmetics v0.2 (#981).
  • Added MutableArithmetics.promote_operation allocation tests (#975).
  • Fixed inference issue on Julia v1.1 (#982).

v0.9.8 (December 19, 2019)

  • Implemented MutableArithmetics API (#924).
  • Fixed callbacks with CachingOptimizer (#959).
  • Fixed MOI.dimension for MOI.Complements (#948).
  • Added fallback for add_variables (#972).
  • Added is_diagonal_vectorized_index utility (#965).
  • Improved linear constraints display in manual (#963, #964).
  • Bridges improvements:
    • Added IndicatorSet to SOS1 bridge (#877).
    • Added support for starting values for Variable.VectorizeBridge (#944).
    • Fixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).
    • Fixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).
    • Fixed choice between variable or constraint bridges for constrained variables (#973).
    • Improve performance of bridge shortest path (#945, #946, #956).
    • Added docstring for test_delete_bridge (#954).
    • Added Variable bridge tests (#952).

v0.9.7 (October 30, 2019)

  • Implemented _result_index_field for NLPBlockDual (#934).
  • Fixed copy of model with starting values for vector constraints (#941).
  • Bridges improvements:
    • Improved performance of add_bridge and added has_bridge (#935).
    • Added AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).
    • Added support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).

v0.9.6 (October 25, 2019)

  • Added complementarity constraints (#913).
  • Allowed ModelLike objects as value of attributes (#928).
  • Testing improvements:
    • Added dual_objective_value option to MOI.Test.TestConfig (#922).
    • Added InvalidIndex tests in basic_constraint_tests (#921).
    • Added tests for the constant term in indicator constraint (#929).
  • Bridges improvements:
    • Added support for starting values for Functionize bridges (#923).
    • Added variable indices context to variable bridges (#920).
    • Fixed a typo in printing o debug_supports (#927).

v0.9.5 (October 9, 2019)

  • Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).
  • Added tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).
  • Use 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).
  • Bridges improvements:
    • Added debug utilities for unsupported variable/constraint/objective (#861).
    • Fixed deletion of variables in bridged VectorOfVariables constraints (#909).
    • Fixed result_index with objective bridges (#911).

v0.9.4 (October 2, 2019)

  • Added solver-independent MIP callbacks (#782).
  • Implements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).
  • Added tests for result count of solution attributes (#901, #904).
  • Added NumberOfThreads attribute (#892).
  • Added Utilities.get_bounds to get the bounds on a variable (#890).
  • Added a note on duplicate coefficients in documentation (#581).
  • Added result index in ConstraintBasisStatus (#898).
  • Added extension dictionary to Utilities.Model (#884, #895).
  • Fixed deletion of constrained variables for CachingOptimizer (#905).
  • Implemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).
  • Bridges improvements:
    • Added Variable.RSOCtoSOCBridge (#907).
    • Implemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).

v0.9.3 (September 20, 2019)

  • Fixed ambiguity detected in Julia v1.3 (#891, #893).
  • Fixed missing sets from ListOfSupportedConstraints (#880).
  • Fixed copy of VectorOfVariables constraints with duplicate indices (#886).
  • Added extension dictionary to MOIU.Model (#884).
  • Implemented MOI.get for function and set for GeoMeanBridge (#888).
  • Updated documentation for SingleVariable indices and bridges (#885).
  • Testing improvements:
    • Added more comprehensive tests for names (#882).
    • Added tests for SingleVariable duals (#883).
    • Added tests for DualExponentialCone and DualPowerCone (#873).
  • Improvements for arbitrary coefficient type:
    • Fixed == for sets with mutable fields (#887).
    • Removed some Float64 assumptions in bridges (#878).
    • Automatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).

v0.9.2 (September 5, 2019)

  • Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).
  • Generalized contlinear tests for arbitrary coefficient type (#855).
  • Fixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).
  • Fixed Allocate-Load copy for single variable constraints (#856).
  • Bridges improvements:
    • Add objective bridges (#789).
    • Fixed Variable.RSOCtoPSDBridge for dimension 2 (#869).
    • Added Variable.SOCtoRSOCBridge (#865).
    • Added Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).
    • Fixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).

v0.9.1 (August 22, 2019)

  • Fix support for Julia v1.2 (#834).
  • L1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).
  • Added tests to MOI.Test.nametest (#833).
  • Fix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).
  • Implements operate for operators * and / between vector function and constant (#837).
  • Implements show for MOI.Utilities.IndexMap (#847).
  • Fix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).
  • Fix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).

v0.9.0 (August 13, 2019)

  • Support for Julia v0.6 and v0.7 was dropped (#714, #717).
  • A MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).
  • add_constrained_variable and add_constrained_variables were added (#759).
  • Support for indicator constraints was added (#709, #712).
  • DualObjectiveValue attribute was added (#473).
  • RawParameter attribute was added (#733).
  • A dual_set function was added (#804).
  • A Benchmarks submodule was added to facilitate solver benchmarking (#769).
  • A submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).
  • The field of ObjectiveValue was renamed to result_index (#729).
  • The _constant and Utilities.getconstant function were renamed to constant
  • REDUCTION_CERTIFICATE result status was added (#734).
  • Abstract matrix sets were added (#731).
  • Testing improvements:
    • The testing guideline was updated (#728).
    • Quadratic tests were added (#697).
    • Unit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).
    • A rotated second-order cone test was added (#759).
    • A power cone test was added (#768).
    • Tests for ZeroOne variables with variable bounds were added (#772).
    • An unbounded test was added (#773).
    • Existing tests had a few updates (#702, #703, #763).
  • Documentation improvements:
    • Added a section on CachingOptimizer (#777).
    • Added a section on UniversalFallback, Model and @model (#762).
    • Transition the knapsack example to a doctest with MockOptimizer (#786).
  • Utilities improvements:
    • A CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).
    • The Utilities.constant function was renamed to Utilities.constant_vector (#740).
    • Implement optimizer attributes for CachingOptimizer (#745).
    • Rename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).
    • operate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).
    • Fix a type piracy of operate (#784).
    • The load_constraint fallback signature was fixed (#760).
    • The set_dot function was extended to work with sparse arrays (#805).
  • Bridges improvements:
    • The bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).
    • Bridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).
    • Fix constraint attributes for bridges (#699).
    • Constraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).
    • Variable bridges were added in (#759).
    • Various improvements (#746, #747).

v0.8.4 (March 13, 2019)

  • Performance improvement in default_copy_to and bridge optimizer (#696).
  • Add Silent and implement setting optimizer attributes in caching and mock optimizers (#695).
  • Add Functionize bridges (SingleVariable and VectorOfVariables) (#659).
  • Minor typo fixes (#694).

v0.8.3 (March 6, 2019)

  • Use zero constant in scalar constraint function of MOI.Test.copytest (#691).
  • Fix variable deletion with SingleVariable objective function (#690).
  • Fix LazyBridgeOptimizer with bridges that add no constraints (#689).
  • Error message improvements (#673, #685, #686, #688).
  • Documentation improvements (#682, #683, #687).
  • Basis status:
    • Remove VariableBasisStatus (#679).
    • Test ConstraintBasisStatus and implement it in bridges (#678).
  • Fix inference of NumberOfVariables and NumberOfConstraints (#677).
  • Implement division between a quadratic function and a number (#675).

v0.8.2 (February 7, 2019)

  • Add RawStatusString attribute (#629).
  • Do not set names to the optimizer but only to the cache in CachingOptimizer (#638).
  • Make scalar MOI functions act as scalars in broadcast (#646).
  • Add function utilities:
    • Implement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).
    • Add a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).
  • Improve support for starting values:
    • Show a warning in copy when starting values are not supported instead of throwing an error (#630).
    • Fix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).
    • Add a test in contlineartest with partially set VariablePrimalStart.
  • Bridges improvements:
    • Fix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.
    • Add Slack bridges (#610, #650).
    • Add FlipSign bridges (#658).
  • Add tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).
  • Use tolerance to compare VariablePrimal in rotatedsoc1 test (#632).
  • Use a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).

v0.8.1 (January 7, 2019)

  • Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).
  • Rename fullbridgeoptimizer into full_bridge_optimizer (#621).
  • Allow custom constraint types with full_bridge_optimizer (#617).
  • Add Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).

v0.8.0 (December 18, 2018)

  • Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.
  • Rename CachingOptimizer methods for style compliance.
  • Add an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.

v0.7.0 (December 13, 2018)

  • Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.
  • Check supports_default_copy_to in tests (#594).
  • Key pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.
  • Add perspective dimension to log-det cone (#593).

v0.6.4 (November 27, 2018)

  • Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).
  • Add a solver naming guideline (#578).
  • Make FeasibilitySense the default ObjectiveSense (#579).
  • Fix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).
  • Document solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).

v0.6.3 (November 16, 2018)

  • Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)
  • Attributes may now be partially set (some values could be nothing). (#563)
  • Performance improvements in Utilities.Model (#549, #567, #568)
  • Fix bug in QuadtoSOC (#558).
  • New supports_default_copy_to method that optimizers should implement to control caching behavior.
  • Documentation improvements.

v0.6.2 (October 26, 2018)

  • Improve hygiene of @model macro (#544).
  • Fix bug in copy tests (#543).
  • Fix bug in UniversalFallback attribute getter (#540).
  • Allow all correct solutions for solve_blank_obj unit test (#537).
  • Add errors for Allocate-Load and bad constraints (#534).
  • [performance] Add specialized implementation of hash for VariableIndex (#533).
  • [performance] Construct the name to object dictionaries lazily in model (#535).
  • Add the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).

v0.6.1 (September 22, 2018)

  • Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).
  • Add warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).
  • Modify MOIT.copytest to not add multiples constraints on the same variable (#521).
  • Add missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).

v0.6.0 (August 30, 2018)

  • The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.
  • Rename functions according to the JuMP style guide:
    • copy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;
    • set! -> set;
    • addvariable[s]! -> add_variable[s];
    • supportsconstraint -> supports_constraint;
    • addconstraint[s]! -> add_constraint[s];
    • isvalid -> is_valid;
    • isempty -> is_empty;
    • Base.delete! -> delete;
    • modify! -> modify;
    • transform! -> transform;
    • initialize! -> initialize;
    • write -> write_to_file; and
    • read! -> read_from_file.
  • Remove free! (use Base.finalize instead).
  • Add the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.
  • Add result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.
  • Add tests for ObjectiveBound.
  • Add test for empty rows in vector linear constraint.
  • Rework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)
  • canget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).

v0.5.0 (August 5, 2018)

  • Fix names with CachingOptimizer.
  • Cleanup thanks to @mohamed82008.
  • Added a universal fallback for constraints.
  • Fast utilities for function canonicalization thanks to @rdeits.
  • Renamed dimension field to side_dimension in the context of matrix-like sets.
  • New and improved tests for cases like duplicate terms and ObjectiveBound.
  • Removed cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.
  • The API for copy! is updated to remove the CopyResult type.
  • Updates for the new JuMP style guide.

v0.4.1 (June 28, 2018)

  • Fixes vector function modification on 32 bits.
  • Fixes Bellman-Ford algorithm for bridges.
  • Added an NLP test with FeasibilitySense.
  • Update modification documentation.

v0.4.0 (June 23, 2018)

  • Helper constructors for VectorAffineTerm and VectorQuadraticTerm.
  • Added modify_lhs to TestConfig.
  • Additional unit tests for optimizers.
  • Added a type parameter to CachingOptimizer for the optimizer field.
  • New API for problem modification (#388)
  • Tests pass without deprecation warnings on Julia 0.7.
  • Small fixes and documentation updates.

v0.3.0 (May 25, 2018)

  • Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.
  • Improvements to MockOptimizer.
  • Significant changes to Bridges.
  • New and improved unit tests.
  • Fixes for Julia 0.7.

v0.2.0 (April 24, 2018)

  • Improvements to and better coverage of Tests.
  • Documentation fixes.
  • SolverName attribute.
  • Changes to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).
  • Addition of NLP tests.
  • Introduction of UniversalFallback.
  • copynames keyword argument to MOI.copy!.
  • Add Bridges submodule.

v0.1.0 (February 28, 2018)

  • Initial public release.
  • The framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.
diff --git a/previews/PR2418/search_index.js b/previews/PR2418/search_index.js new file mode 100644 index 0000000000..3c396d4351 --- /dev/null +++ b/previews/PR2418/search_index.js @@ -0,0 +1,3 @@ +var documenterSearchIndex = {"docs": +[{"location":"background/motivation/#Motivation","page":"Motivation","title":"Motivation","text":"","category":"section"},{"location":"background/motivation/","page":"Motivation","title":"Motivation","text":"MathOptInterface (MOI) is a replacement for MathProgBase, the first-generation abstraction layer for mathematical optimization previously used by JuMP and Convex.jl.","category":"page"},{"location":"background/motivation/","page":"Motivation","title":"Motivation","text":"To address a number of limitations of MathProgBase, MOI is designed to:","category":"page"},{"location":"background/motivation/","page":"Motivation","title":"Motivation","text":"Be simple and extensible\nunifying linear, quadratic, and conic optimization,\nseamlessly facilitating extensions to essentially arbitrary constraints and functions (for example, indicator constraints, complementarity constraints, and piecewise-linear functions)\nBe fast\nby allowing access to a solver's in-memory representation of a problem without writing intermediate files (when possible)\nby using multiple dispatch and avoiding requiring containers of non-concrete types\nAllow a solver to return multiple results (for example, a pool of solutions)\nAllow a solver to return extra arbitrary information via attributes (for example, variable- and constraint-wise membership in an irreducible inconsistent subset for infeasibility analysis)\nProvide a greatly expanded set of status codes explaining what happened during the optimization procedure\nEnable a solver to more precisely specify which problem classes it supports\nEnable both primal and dual warm starts\nEnable adding and removing both variables and constraints by indices that are not required to be consecutive\nEnable any modification that the solver supports to an existing model\nAvoid requiring the solver wrapper to store an additional copy of the problem data","category":"page"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/constraints/#constraints_ref","page":"Constraints","title":"Constraints","text":"","category":"section"},{"location":"reference/constraints/#Types","page":"Constraints","title":"Types","text":"","category":"section"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"ConstraintIndex","category":"page"},{"location":"reference/constraints/#MathOptInterface.ConstraintIndex","page":"Constraints","title":"MathOptInterface.ConstraintIndex","text":"ConstraintIndex{F, S}\n\nA type-safe wrapper for Int64 for use in referencing F-in-S constraints in a model. The parameter F is the type of the function in the constraint, and the parameter S is the type of set in the constraint. To allow for deletion, indices need not be consecutive. Indices within a constraint type (that is, F-in-S) must be unique, but non-unique indices across different constraint types are allowed. If F is VariableIndex then the index is equal to the index of the variable. That is for an index::ConstraintIndex{VariableIndex}, we always have\n\nindex.value == MOI.get(model, MOI.ConstraintFunction(), index).value\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#Functions","page":"Constraints","title":"Functions","text":"","category":"section"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"is_valid(::ModelLike,::ConstraintIndex)\nadd_constraint\nadd_constraints\ntransform\nsupports_constraint","category":"page"},{"location":"reference/constraints/#MathOptInterface.is_valid-Tuple{MathOptInterface.ModelLike, MathOptInterface.ConstraintIndex}","page":"Constraints","title":"MathOptInterface.is_valid","text":"is_valid(model::ModelLike, index::Index)::Bool\n\nReturn a Bool indicating whether this index refers to a valid object in the model model.\n\n\n\n\n\n","category":"method"},{"location":"reference/constraints/#MathOptInterface.add_constraint","page":"Constraints","title":"MathOptInterface.add_constraint","text":"add_constraint(model::ModelLike, func::F, set::S)::ConstraintIndex{F,S} where {F,S}\n\nAdd the constraint f(x) in mathcalS where f is defined by func, and mathcalS is defined by set.\n\nadd_constraint(model::ModelLike, v::VariableIndex, set::S)::ConstraintIndex{VariableIndex,S} where {S}\nadd_constraint(model::ModelLike, vec::Vector{VariableIndex}, set::S)::ConstraintIndex{VectorOfVariables,S} where {S}\n\nAdd the constraint v in mathcalS where v is the variable (or vector of variables) referenced by v and mathcalS is defined by set.\n\nAn UnsupportedConstraint error is thrown if model does not support F-in-S constraints,\na AddConstraintNotAllowed error is thrown if it supports F-in-S constraints but it cannot add the constraint in its current state and\na ScalarFunctionConstantNotZero error may be thrown if func is an AbstractScalarFunction with nonzero constant and set is EqualTo, GreaterThan, LessThan or Interval.\na LowerBoundAlreadySet error is thrown if F is a VariableIndex and a constraint was already added to this variable that sets a lower bound.\na UpperBoundAlreadySet error is thrown if F is a VariableIndex and a constraint was already added to this variable that sets an upper bound.\n\n\n\n\n\nMOI.add_constraint(map::Map, vi::MOI.VariableIndex, set::MOI.AbstractScalarSet)\n\nRecord that a constraint vi-in-set is added and throws if a lower or upper bound is set by this constraint and such bound has already been set for vi.\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#MathOptInterface.add_constraints","page":"Constraints","title":"MathOptInterface.add_constraints","text":"add_constraints(model::ModelLike, funcs::Vector{F}, sets::Vector{S})::Vector{ConstraintIndex{F,S}} where {F,S}\n\nAdd the set of constraints specified by each function-set pair in funcs and sets. F and S should be concrete types. This call is equivalent to add_constraint.(model, funcs, sets) but may be more efficient.\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#MathOptInterface.transform","page":"Constraints","title":"MathOptInterface.transform","text":"Transform Constraint Set\n\ntransform(model::ModelLike, c::ConstraintIndex{F,S1}, newset::S2)::ConstraintIndex{F,S2}\n\nReplace the set in constraint c with newset. The constraint index c will no longer be valid, and the function returns a new constraint index with the correct type.\n\nSolvers may only support a subset of constraint transforms that they perform efficiently (for example, changing from a LessThan to GreaterThan set). In addition, set modification (where S1 = S2) should be performed via the modify function.\n\nTypically, the user should delete the constraint and add a new one.\n\nExamples\n\nIf c is a ConstraintIndex{ScalarAffineFunction{Float64},LessThan{Float64}},\n\nc2 = transform(model, c, GreaterThan(0.0))\ntransform(model, c, LessThan(0.0)) # errors\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#MathOptInterface.supports_constraint","page":"Constraints","title":"MathOptInterface.supports_constraint","text":"MOI.supports_constraint(\n BT::Type{<:AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.\n\nImplementation notes\n\nThis method depends only on the type of the inputs, not the runtime values.\nThere is a default fallback, so you need only implement this method for constraint types that the bridge implements.\n\n\n\n\n\nsupports_constraint(\n model::ModelLike,\n ::Type{F},\n ::Type{S},\n)::Bool where {F<:AbstractFunction,S<:AbstractSet}\n\nReturn a Bool indicating whether model supports F-in-S constraints, that is, copy_to(model, src) does not throw UnsupportedConstraint when src contains F-in-S constraints. If F-in-S constraints are only not supported in specific circumstances, for example, F-in-S constraints cannot be combined with another type of constraint, it should still return true.\n\n\n\n\n\n","category":"function"},{"location":"reference/constraints/#Attributes","page":"Constraints","title":"Attributes","text":"","category":"section"},{"location":"reference/constraints/","page":"Constraints","title":"Constraints","text":"AbstractConstraintAttribute\nConstraintName\nConstraintPrimalStart\nConstraintDualStart\nConstraintPrimal\nConstraintDual\nConstraintBasisStatus\nConstraintFunction\nCanonicalConstraintFunction\nConstraintSet\nBasisStatusCode\nBASIC\nNONBASIC\nNONBASIC_AT_LOWER\nNONBASIC_AT_UPPER\nSUPER_BASIC","category":"page"},{"location":"reference/constraints/#MathOptInterface.AbstractConstraintAttribute","page":"Constraints","title":"MathOptInterface.AbstractConstraintAttribute","text":"AbstractConstraintAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of constraints in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintName","page":"Constraints","title":"MathOptInterface.ConstraintName","text":"ConstraintName()\n\nA constraint attribute for a string identifying the constraint.\n\nIt is valid for constraints variables to have the same name; however, constraints with duplicate names cannot be looked up using get, regardless of whether they have the same F-in-S type.\n\nConstraintName has a default value of \"\" if not set.\n\nNotes\n\nYou should not implement ConstraintName for VariableIndex constraints.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintPrimalStart","page":"Constraints","title":"MathOptInterface.ConstraintPrimalStart","text":"ConstraintPrimalStart()\n\nA constraint attribute for the initial assignment to some constraint's ConstraintPrimal that the optimizer may use to warm-start the solve.\n\nMay be nothing (unset), a number for AbstractScalarFunction, or a vector for AbstractVectorFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintDualStart","page":"Constraints","title":"MathOptInterface.ConstraintDualStart","text":"ConstraintDualStart()\n\nA constraint attribute for the initial assignment to some constraint's ConstraintDual that the optimizer may use to warm-start the solve.\n\nMay be nothing (unset), a number for AbstractScalarFunction, or a vector for AbstractVectorFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintPrimal","page":"Constraints","title":"MathOptInterface.ConstraintPrimal","text":"ConstraintPrimal(result_index::Int = 1)\n\nA constraint attribute for the assignment to some constraint's primal value in result result_index.\n\nIf the constraint is f(x) in S, then in most cases the ConstraintPrimal is the value of f, evaluated at the corresponding VariablePrimal solution.\n\nHowever, some conic solvers reformulate b - Ax in S to s = b - Ax, s in S. These solvers may return the value of s for ConstraintPrimal, rather than b - Ax. (Although these are constrained by an equality constraint, due to numerical tolerances they may not be identical.)\n\nIf the solver does not have a primal value for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintPrimal attribute.\n\nIf result_index is omitted, it is 1 by default. See ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintDual","page":"Constraints","title":"MathOptInterface.ConstraintDual","text":"ConstraintDual(result_index::Int = 1)\n\nA constraint attribute for the assignment to some constraint's dual value in result result_index. If result_index is omitted, it is 1 by default.\n\nIf the solver does not have a dual value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the ConstraintDual attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintBasisStatus","page":"Constraints","title":"MathOptInterface.ConstraintBasisStatus","text":"ConstraintBasisStatus(result_index::Int = 1)\n\nA constraint attribute for the BasisStatusCode of some constraint in result result_index, with respect to an available optimal solution basis. If result_index is omitted, it is 1 by default.\n\nIf the solver does not have a basis statue for the constraint because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ConstraintBasisStatus attribute.\n\nSee ResultCount for information on how the results are ordered.\n\nNotes\n\nFor the basis status of a variable, query VariableBasisStatus.\n\nConstraintBasisStatus does not apply to VariableIndex constraints. You can infer the basis status of a VariableIndex constraint by looking at the result of VariableBasisStatus.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintFunction","page":"Constraints","title":"MathOptInterface.ConstraintFunction","text":"ConstraintFunction()\n\nA constraint attribute for the AbstractFunction object used to define the constraint.\n\nIt is guaranteed to be equivalent but not necessarily identical to the function provided by the user.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.CanonicalConstraintFunction","page":"Constraints","title":"MathOptInterface.CanonicalConstraintFunction","text":"CanonicalConstraintFunction()\n\nA constraint attribute for a canonical representation of the AbstractFunction object used to define the constraint.\n\nGetting this attribute is guaranteed to return a function that is equivalent but not necessarily identical to the function provided by the user.\n\nBy default, MOI.get(model, MOI.CanonicalConstraintFunction(), ci) fallbacks to MOI.Utilities.canonical(MOI.get(model, MOI.ConstraintFunction(), ci)). However, if model knows that the constraint function is canonical then it can implement a specialized method that directly return the function without calling Utilities.canonical. Therefore, the value returned cannot be assumed to be a copy of the function stored in model. Moreover, Utilities.Model checks with Utilities.is_canonical whether the function stored internally is already canonical and if it's the case, then it returns the function stored internally instead of a copy.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.ConstraintSet","page":"Constraints","title":"MathOptInterface.ConstraintSet","text":"ConstraintSet()\n\nA constraint attribute for the AbstractSet object used to define the constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.BasisStatusCode","page":"Constraints","title":"MathOptInterface.BasisStatusCode","text":"BasisStatusCode\n\nAn Enum of possible values for the ConstraintBasisStatus and VariableBasisStatus attributes, explaining the status of a given element with respect to an optimal solution basis.\n\nNotes\n\nNONBASIC_AT_LOWER and NONBASIC_AT_UPPER should be used only for\n\nconstraints with the Interval set. In this case, they are necessary to distinguish which side of the constraint is active. One-sided constraints (for example, LessThan and GreaterThan) should use NONBASIC instead of the NONBASIC_AT_* values. This restriction does not apply to VariableBasisStatus, which should return NONBASIC_AT_* regardless of whether the alternative bound exists.\n\nIn linear programs, SUPER_BASIC occurs when a variable with no bounds is not\n\nin the basis.\n\nValues\n\nPossible values are:\n\nBASIC: element is in the basis\nNONBASIC: element is not in the basis\nNONBASIC_AT_LOWER: element is not in the basis and is at its lower bound\nNONBASIC_AT_UPPER: element is not in the basis and is at its upper bound\nSUPER_BASIC: element is not in the basis but is also not at one of its bounds\n\n\n\n\n\n","category":"type"},{"location":"reference/constraints/#MathOptInterface.BASIC","page":"Constraints","title":"MathOptInterface.BASIC","text":"BASIC::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nBASIC: element is in the basis\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.NONBASIC","page":"Constraints","title":"MathOptInterface.NONBASIC","text":"NONBASIC::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nNONBASIC: element is not in the basis\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.NONBASIC_AT_LOWER","page":"Constraints","title":"MathOptInterface.NONBASIC_AT_LOWER","text":"NONBASIC_AT_LOWER::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nNONBASIC_AT_LOWER: element is not in the basis and is at its lower bound\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.NONBASIC_AT_UPPER","page":"Constraints","title":"MathOptInterface.NONBASIC_AT_UPPER","text":"NONBASIC_AT_UPPER::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nNONBASIC_AT_UPPER: element is not in the basis and is at its upper bound\n\n\n\n\n\n","category":"constant"},{"location":"reference/constraints/#MathOptInterface.SUPER_BASIC","page":"Constraints","title":"MathOptInterface.SUPER_BASIC","text":"SUPER_BASIC::BasisStatusCode\n\nAn instance of the BasisStatusCode enum.\n\nSUPER_BASIC: element is not in the basis but is also not at one of its bounds\n\n\n\n\n\n","category":"constant"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/implementing/#Implementing-a-solver-interface","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"This guide outlines the basic steps to implement an interface to MathOptInterface for a new solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"danger: Danger\nImplementing an interface to MathOptInterface for a new solver is a lot of work. Before starting, we recommend that you join the Developer chatroom and explain a little bit about the solver you are wrapping. If you have questions that are not answered by this guide, please ask them in the Developer chatroom so we can improve this guide.","category":"page"},{"location":"tutorials/implementing/#A-note-on-the-API","page":"Implementing a solver interface","title":"A note on the API","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The API of MathOptInterface is large and varied. In order to support the diversity of solvers and use-cases, we make heavy use of duck-typing. That is, solvers are not expected to implement the full API, nor is there a well-defined minimal subset of what must be implemented. Instead, you should implement the API as necessary to make the solver function as you require.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The main reason for using duck-typing is that solvers work in different ways and target different use-cases.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Some solvers support incremental problem construction, support modification after a solve, and have native support for things like variable names.\nOther solvers are \"one-shot\" solvers that require all of the problem data to construct and solve the problem in a single function call. They do not support modification or things like variable names.\nOther \"solvers\" are not solvers at all, but things like file readers. These may only support functions like read_from_file, and may not even support the ability to add variables or constraints directly.\nFinally, some \"solvers\" are layers which take a problem as input, transform it according to some rules, and pass the transformed problem to an inner solver.","category":"page"},{"location":"tutorials/implementing/#Preliminaries","page":"Implementing a solver interface","title":"Preliminaries","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Before starting on your wrapper, you should do some background research and make the solver accessible via Julia.","category":"page"},{"location":"tutorials/implementing/#Decide-if-MathOptInterface-is-right-for-you","page":"Implementing a solver interface","title":"Decide if MathOptInterface is right for you","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The first step in writing a wrapper is to decide whether implementing an interface is the right thing to do.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MathOptInterface is an abstraction layer for unifying constrained mathematical optimization solvers. If your solver doesn't fit in the category, for example, it implements a derivative-free algorithm for unconstrained objective functions, MathOptInterface may not be the right tool for the job.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nIf you're not sure whether you should write an interface, ask in the Developer chatroom.","category":"page"},{"location":"tutorials/implementing/#Find-a-similar-solver-already-wrapped","page":"Implementing a solver interface","title":"Find a similar solver already wrapped","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The next step is to find (if possible) a similar solver that is already wrapped. Although not strictly necessary, this will be a good place to look for inspiration when implementing your wrapper.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The JuMP documentation has a good list of solvers, along with the problem classes they support.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nIf you're not sure which solver is most similar, ask in the Developer chatroom.","category":"page"},{"location":"tutorials/implementing/#Create-a-low-level-interface","page":"Implementing a solver interface","title":"Create a low-level interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Before writing a MathOptInterface wrapper, you first need to be able to call the solver from Julia.","category":"page"},{"location":"tutorials/implementing/#Wrapping-solvers-written-in-Julia","page":"Implementing a solver interface","title":"Wrapping solvers written in Julia","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver is written in Julia, there's nothing to do here. Go to the next section.","category":"page"},{"location":"tutorials/implementing/#Wrapping-solvers-written-in-C","page":"Implementing a solver interface","title":"Wrapping solvers written in C","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Julia is well suited to wrapping solvers written in C.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nThis is not true for C++. If you have a solver written in C++, first write a C interface, then wrap the C interface.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Before writing a MathOptInterface wrapper, there are a few extra steps.","category":"page"},{"location":"tutorials/implementing/#Create-a-JLL","page":"Implementing a solver interface","title":"Create a JLL","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If the C code is publicly available under an open source license, create a JLL package via Yggdrasil. The easiest way to do this is to copy an existing solver. Good examples to follow are the COIN-OR solvers.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nBuilding the solver via Yggdrasil is non-trivial. Please ask the Developer chatroom for help.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If the code is commercial or not publicly available, the user will need to manually install the solver. See Gurobi.jl or CPLEX.jl for examples of how to structure this.","category":"page"},{"location":"tutorials/implementing/#implement_clang","page":"Implementing a solver interface","title":"Use Clang.jl to wrap the C API","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The next step is to use Clang.jl to automatically wrap the C API. The easiest way to do this is to follow an example. Good examples to follow are Cbc.jl and HiGHS.jl.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Sometimes, you will need to make manual modifications to the resulting files.","category":"page"},{"location":"tutorials/implementing/#Solvers-written-in-other-languages","page":"Implementing a solver interface","title":"Solvers written in other languages","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Ask the Developer chatroom for advice. You may be able to use one of the JuliaInterop packages to call out to the solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example, SeDuMi.jl uses MATLAB.jl to call the SeDuMi solver written in MATLAB.","category":"page"},{"location":"tutorials/implementing/#Structuring-the-package","page":"Implementing a solver interface","title":"Structuring the package","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Structure your wrapper as a Julia package. Consult the Julia documentation if you haven't done this before.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MOI solver interfaces may be in the same package as the solver itself (either the C wrapper if the solver is accessible through C, or the Julia code if the solver is written in Julia, for example), or in a separate package which depends on the solver package.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"note: Note\nThe JuMP core contributors request that you do not use \"JuMP\" in the name of your package without prior consent.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Your package should have the following structure:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"/.github\n /workflows\n ci.yml\n format_check.yml\n TagBot.yml\n/gen\n gen.jl # Code to wrap the C API\n/src\n NewSolver.jl\n /gen\n libnewsolver_api.jl\n libnewsolver_common.jl\n /MOI_wrapper\n MOI_wrapper.jl\n other_files.jl\n/test\n runtests.jl\n /MOI_wrapper\n MOI_wrapper.jl\n.gitignore\n.JuliaFormatter.toml\nREADME.md\nLICENSE.md\nProject.toml","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The /.github folder contains the scripts for GitHub actions. The easiest way to write these is to copy the ones from an existing solver.\nThe /gen and /src/gen folders are only needed if you are wrapping a solver written in C.\nThe /src/MOI_wrapper folder contains the Julia code for the MOI wrapper.\nThe /test folder contains code for testing your package. See Setup tests for more information.\nThe .JuliaFormatter.toml and .github/workflows/format_check.yml enforce code formatting using JuliaFormatter.jl. Check existing solvers or JuMP.jl for details.","category":"page"},{"location":"tutorials/implementing/#Documentation","page":"Implementing a solver interface","title":"Documentation","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Your package must include documentation explaining how to use the package. The easiest approach is to include documentation in your README.md. A more involved option is to use Documenter.jl.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Examples of packages with README-based documentation include:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Cbc.jl\nHiGHS.jl\nSCS.jl","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Examples of packages with Documenter-based documentation include:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Alpine.jl\nCOSMO.jl\nJuniper.jl","category":"page"},{"location":"tutorials/implementing/#Setup-tests","page":"Implementing a solver interface","title":"Setup tests","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The best way to implement an interface to MathOptInterface is via test-driven development.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The MOI.Test submodule contains a large test suite to help check that you have implemented things correctly.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Follow the guide How to test a solver to set up the tests for your package.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nRun the tests frequently when developing. However, at the start there is going to be a lot of errors. Start by excluding large classes of tests (for example, exclude = [\"test_basic_\", \"test_model_\"], implement any missing methods until the tests pass, then remove an exclusion and repeat.","category":"page"},{"location":"tutorials/implementing/#Initial-code","page":"Implementing a solver interface","title":"Initial code","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"By this point, you should have a package setup with tests, formatting, and access to the underlying solver. Now it's time to start writing the wrapper.","category":"page"},{"location":"tutorials/implementing/#The-Optimizer-object","page":"Implementing a solver interface","title":"The Optimizer object","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The first object to create is a subtype of AbstractOptimizer. This type is going to store everything related to the problem.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"By convention, these optimizers should not be exported and should be named PackageName.Optimizer.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"import MathOptInterface as MOI\n\nstruct Optimizer <: MOI.AbstractOptimizer\n # Fields go here\nend","category":"page"},{"location":"tutorials/implementing/#Optimizer-objects-for-C-solvers","page":"Implementing a solver interface","title":"Optimizer objects for C solvers","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nThis section is important if you wrap a solver written in C.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Wrapping a solver written in C will require the use of pointers, and for you to manually free the solver's memory when the Optimizer is garbage collected by Julia.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Never pass a pointer directly to a Julia ccall function.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Instead, store the pointer as a field in your Optimizer, and implement Base.cconvert and Base.unsafe_convert. Then you can pass Optimizer to any ccall function that expects the pointer.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In addition, make sure you implement a finalizer for each model you create.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If newsolver_createProblem() is the low-level function that creates the problem pointer in C, and newsolver_freeProblem(::Ptr{Cvoid}) is the low-level function that frees memory associated with the pointer, your Optimizer() function should look like this:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"struct Optimizer <: MOI.AbstractOptimizer\n ptr::Ptr{Cvoid}\n\n function Optimizer()\n ptr = newsolver_createProblem()\n model = Optimizer(ptr)\n finalizer(model) do m\n newsolver_freeProblem(m)\n return\n end\n return model\n end\nend\n\nBase.cconvert(::Type{Ptr{Cvoid}}, model::Optimizer) = model\nBase.unsafe_convert(::Type{Ptr{Cvoid}}, model::Optimizer) = model.ptr","category":"page"},{"location":"tutorials/implementing/#Implement-methods-for-Optimizer","page":"Implementing a solver interface","title":"Implement methods for Optimizer","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"All Optimizers must implement the following methods:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"empty!\nis_empty","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Other methods, detailed below, are optional or depend on how you implement the interface.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nFor this and all future methods, read the docstrings to understand what each method does, what it expects as input, and what it produces as output. If it isn't clear, let us know and we will improve the docstrings. It is also very helpful to look at an existing wrapper for a similar solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"You should also implement Base.show(::IO, ::Optimizer) to print a nice string when someone prints your model. For example","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function Base.show(io::IO, model::Optimizer)\n return print(io, \"NewSolver with the pointer $(model.ptr)\")\nend","category":"page"},{"location":"tutorials/implementing/#Implement-attributes","page":"Implementing a solver interface","title":"Implement attributes","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MathOptInterface uses attributes to manage different aspects of the problem.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For each attribute","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"get gets the current value of the attribute\nset sets a new value of the attribute. Not all attributes can be set. For example, the user can't modify the SolverName.\nsupports returns a Bool indicating whether the solver supports the attribute.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nUse attribute_value_type to check the value expected by a given attribute. You should make sure that your get function correctly infers to this type (or a subtype of it).","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Each column in the table indicates whether you need to implement the particular method for each attribute.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nSolverName Yes No No\nSolverVersion Yes No No\nRawSolver Yes No No\nName Yes Yes Yes\nSilent Yes Yes Yes\nTimeLimitSec Yes Yes Yes\nObjectiveLimit Yes Yes Yes\nSolutionLimit Yes Yes Yes\nRawOptimizerAttribute Yes Yes Yes\nNumberOfThreads Yes Yes Yes\nAbsoluteGapTolerance Yes Yes Yes\nRelativeGapTolerance Yes Yes Yes","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.get(model::Optimizer, ::MOI.Silent)\n return # true if MOI.Silent is set\nend\n\nfunction MOI.set(model::Optimizer, ::MOI.Silent, v::Bool)\n if v\n # Set a parameter to turn off printing\n else\n # Restore the default printing\n end\n return\nend\n\nMOI.supports(::Optimizer, ::MOI.Silent) = true","category":"page"},{"location":"tutorials/implementing/#Define-supports_constraint","page":"Implementing a solver interface","title":"Define supports_constraint","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The next step is to define which constraints and objective functions you plan to support.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For each function-set constraint pair, define supports_constraint:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.supports_constraint(\n ::Optimizer,\n ::Type{MOI.VariableIndex},\n ::Type{MOI.ZeroOne},\n)\n return true\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"To make this easier, you may want to use Unions:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.supports_constraint(\n ::Optimizer,\n ::Type{MOI.VariableIndex},\n ::Type{<:Union{MOI.LessThan,MOI.GreaterThan,MOI.EqualTo}},\n)\n return true\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nOnly support a constraint if your solver has native support for it.","category":"page"},{"location":"tutorials/implementing/#The-big-decision:-incremental-modification?","page":"Implementing a solver interface","title":"The big decision: incremental modification?","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Now you need to decide whether to support incremental modification or not.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Incremental modification means that the user can add variables and constraints one-by-one without needing to rebuild the entire problem, and they can modify the problem data after an optimize! call. Supporting incremental modification means implementing functions like add_variable and add_constraint.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"The alternative is to accept the problem data in a single optimize! or copy_to function call. Because these functions see all of the data at once, it can typically call a more efficient function to load data into the underlying solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Good examples of solvers supporting incremental modification are MILP solvers like GLPK.jl and Gurobi.jl. Examples of non-incremental solvers are AmplNLWriter.jl and SCS.jl","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"It is possible for a solver to implement both approaches, but you should probably start with one for simplicity.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nOnly support incremental modification if your solver has native support for it.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In general, supporting incremental modification is more work, and it usually requires some extra book-keeping. However, it provides a more efficient interface to the solver if the problem is going to be resolved multiple times with small modifications. Moreover, once you've implemented incremental modification, it's usually not much extra work to add a copy_to interface. The converse is not true.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nIf this is your first time writing an interface, start with the one-shot optimize!.","category":"page"},{"location":"tutorials/implementing/#The-non-incremental-interface","page":"Implementing a solver interface","title":"The non-incremental interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"There are two ways to implement the non-incremental interface. The first uses a two-argument version of optimize!, the second implements copy_to followed by the one-argument version of optimize!.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver does not support modification, and requires all data to solve the problem in a single function call, you should implement the \"one-shot\" optimize!.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"optimize!(::ModelLike, ::ModelLike)","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver separates data loading and the actual optimization into separate steps, implement the copy_to interface.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"copy_to(::ModelLike, ::ModelLike)\noptimize!(::ModelLike)","category":"page"},{"location":"tutorials/implementing/#The-incremental-interface","page":"Implementing a solver interface","title":"The incremental interface","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nWriting this interface is a lot of work. The easiest way is to consult the source code of a similar solver.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"To implement the incremental interface, implement the following functions:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"add_variable\nadd_variables\nadd_constraint\nadd_constraints\nis_valid\ndelete\noptimize!(::ModelLike)","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nSolvers do not have to support AbstractScalarFunction in GreaterThan, LessThan, EqualTo, or Interval with a nonzero constant in the function. Throw ScalarFunctionConstantNotZero if the function constant is not zero.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In addition, you should implement the following model attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nListOfModelAttributesSet Yes No No\nObjectiveFunctionType Yes No No\nObjectiveFunction Yes Yes Yes\nObjectiveSense Yes Yes Yes\nName Yes Yes Yes","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Variable-related attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nListOfVariableAttributesSet Yes No No\nListOfVariablesWithAttributeSet Yes No No\nNumberOfVariables Yes No No\nListOfVariableIndices Yes No No","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Constraint-related attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nListOfConstraintAttributesSet Yes No No\nListOfConstraintsWithAttributeSet Yes No No\nNumberOfConstraints Yes No No\nListOfConstraintTypesPresent Yes No No\nConstraintFunction Yes Yes No\nConstraintSet Yes Yes No","category":"page"},{"location":"tutorials/implementing/#Modifications","page":"Implementing a solver interface","title":"Modifications","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver supports modifying data in-place, implement modify for the following AbstractModifications:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ScalarConstantChange\nScalarCoefficientChange\nScalarQuadraticCoefficientChange\nVectorConstantChange\nMultirowChange","category":"page"},{"location":"tutorials/implementing/#Variables-constrained-on-creation","page":"Implementing a solver interface","title":"Variables constrained on creation","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Some solvers require variables be associated with a set when they are created. This conflicts with the incremental modification approach, since you cannot first add a free variable and then constrain it to the set.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If this is the case, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"add_constrained_variable\nadd_constrained_variables\nsupports_add_constrained_variables","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"By default, MathOptInterface assumes solvers support free variables. If your solver does not support free variables, define:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MOI.supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false","category":"page"},{"location":"tutorials/implementing/#Incremental-and-copy_to","page":"Implementing a solver interface","title":"Incremental and copy_to","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If you implement the incremental interface, you have the option of also implementing copy_to.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If you don't want to implement copy_to, for example, because the solver has no API for building the problem in a single function call, define the following fallback:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MOI.supports_incremental_interface(::Optimizer) = true\n\nfunction MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)\n return MOI.Utilities.default_copy_to(dest, src)\nend","category":"page"},{"location":"tutorials/implementing/#implement_names","page":"Implementing a solver interface","title":"Names","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Regardless of which interface you implement, you have the option of implementing the Name attribute for variables and constraints:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Attribute get set supports\nVariableName Yes Yes Yes\nConstraintName Yes Yes Yes","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If you implement names, you must also implement the following three methods:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"function MOI.get(model::Optimizer, ::Type{MOI.VariableIndex}, name::String)\n return # The variable named `name`.\nend\n\nfunction MOI.get(model::Optimizer, ::Type{MOI.ConstraintIndex}, name::String)\n return # The constraint any type named `name`.\nend\n\nfunction MOI.get(\n model::Optimizer,\n ::Type{MOI.ConstraintIndex{F,S}},\n name::String,\n) where {F,S}\n return # The constraint of type F-in-S named `name`.\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"These methods have the following rules:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If there is no variable or constraint with the name, return nothing\nIf there is a single variable or constraint with that name, return the variable or constraint\nIf there are multiple variables or constraints with the name, throw an error.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"warning: Warning\nYou should not implement ConstraintName for VariableIndex constraints. If you implement ConstraintName for other constraints, you can add the following two methods to disable ConstraintName for VariableIndex constraints.function MOI.supports(\n ::Optimizer,\n ::MOI.ConstraintName,\n ::Type{<:MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet}},\n)\n return throw(MOI.VariableIndexConstraintNameError())\nend\nfunction MOI.set(\n ::Optimizer,\n ::MOI.ConstraintName,\n ::MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet},\n ::String,\n)\n return throw(MOI.VariableIndexConstraintNameError())\nend","category":"page"},{"location":"tutorials/implementing/#Solutions","page":"Implementing a solver interface","title":"Solutions","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Implement optimize! to solve the model:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"optimize!","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"All Optimizers must implement the following attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"DualStatus\nPrimalStatus\nRawStatusString\nResultCount\nTerminationStatus","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"info: Info\nYou only need to implement get for solution attributes. Don't implement set or supports.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"note: Note\nSolver wrappers should document how the low-level statuses map to the MOI statuses. Statuses like NEARLY_FEASIBLE_POINT and INFEASIBLE_POINT, are designed to be used when the solver explicitly indicates that relaxed tolerances are satisfied or the returned point is infeasible, respectively.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"You should also implement the following attributes:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ObjectiveValue\nSolveTimeSec\nVariablePrimal","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"tip: Tip\nAttributes like VariablePrimal and ObjectiveValue are indexed by the result count. Use MOI.check_result_index_bounds(model, attr) to throw an error if the attribute is not available.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver returns dual solutions, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ConstraintDual\nDualObjectiveValue","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For integer solvers, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ObjectiveBound\nRelativeGap","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If applicable, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"SimplexIterations\nBarrierIterations\nNodeCount","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver uses the Simplex method, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"ConstraintBasisStatus","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"If your solver accepts primal or dual warm-starts, implement:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"VariablePrimalStart\nConstraintDualStart","category":"page"},{"location":"tutorials/implementing/#Other-tips","page":"Implementing a solver interface","title":"Other tips","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Here are some other points to be aware of when writing your wrapper.","category":"page"},{"location":"tutorials/implementing/#Unsupported-constraints-at-runtime","page":"Implementing a solver interface","title":"Unsupported constraints at runtime","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In some cases, your solver may support a particular type of constraint (for example, quadratic constraints), but only if the data meets some condition (for example, it is convex).","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"In this case, declare that you support the constraint, and throw AddConstraintNotAllowed.","category":"page"},{"location":"tutorials/implementing/#Dealing-with-multiple-variable-bounds","page":"Implementing a solver interface","title":"Dealing with multiple variable bounds","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"MathOptInterface uses VariableIndex constraints to represent variable bounds. Defining multiple variable bounds on a single variable is not allowed.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Throw LowerBoundAlreadySet or UpperBoundAlreadySet if the user adds a constraint that results in multiple bounds.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Only throw if the constraints conflict. It is okay to add VariableIndex-in-GreaterThan and then VariableIndex-in-LessThan, but not VariableIndex-in-Interval and then VariableIndex-in-LessThan,","category":"page"},{"location":"tutorials/implementing/#Expect-duplicate-coefficients","page":"Implementing a solver interface","title":"Expect duplicate coefficients","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Solvers must expect that functions such as ScalarAffineFunction and VectorQuadraticFunction may contain duplicate coefficients.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example, ScalarAffineFunction([ScalarAffineTerm(x, 1), ScalarAffineTerm(x, 1)], 0.0).","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Use Utilities.canonical to return a new function with the duplicate coefficients aggregated together.","category":"page"},{"location":"tutorials/implementing/#Don't-modify-user-data","page":"Implementing a solver interface","title":"Don't modify user-data","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"All data passed to the solver must be copied immediately to internal data structures. Solvers may not modify any input vectors and must assume that input vectors will not be modified by users in the future.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"This applies, for example, to the terms vector in ScalarAffineFunction. Vectors returned to the user, for example, via ObjectiveFunction or ConstraintFunction attributes, must not be modified by the solver afterwards. The in-place version of get! can be used by users to avoid extra copies in this case.","category":"page"},{"location":"tutorials/implementing/#Column-Generation","page":"Implementing a solver interface","title":"Column Generation","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"There is no special interface for column generation. If the solver has a special API for setting coefficients in existing constraints when adding a new variable, it is possible to queue modifications and new variables and then call the solver's API once all of the new coefficients are known.","category":"page"},{"location":"tutorials/implementing/#Solver-specific-attributes","page":"Implementing a solver interface","title":"Solver-specific attributes","text":"","category":"section"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"You don't need to restrict yourself to the attributes defined in the MathOptInterface.jl package.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Solver-specific attributes should be specified by creating an appropriate subtype of AbstractModelAttribute, AbstractOptimizerAttribute, AbstractVariableAttribute, or AbstractConstraintAttribute.","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"For example, Gurobi.jl adds attributes for multiobjective optimization by defining:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"struct NumberOfObjectives <: MOI.AbstractModelAttribute end\n\nfunction MOI.set(model::Optimizer, ::NumberOfObjectives, n::Integer)\n # Code to set NumberOfObjectives\n return\nend\n\nfunction MOI.get(model::Optimizer, ::NumberOfObjectives)\n n = # Code to get NumberOfObjectives\n return n\nend","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"Then, the user can write:","category":"page"},{"location":"tutorials/implementing/","page":"Implementing a solver interface","title":"Implementing a solver interface","text":"model = Gurobi.Optimizer()\nMOI.set(model, Gurobi.NumberofObjectives(), 3)","category":"page"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Nonlinear/reference/#NonlinearAPI","page":"API Reference","title":"Nonlinear Modeling","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"More information can be found in the Nonlinear section of the manual.","category":"page"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear\nNonlinear.Model","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear","page":"API Reference","title":"MathOptInterface.Nonlinear","text":"Nonlinear\n\nwarning: Warning\nThe Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.\n\n\n\n\n\n","category":"module"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Model","page":"API Reference","title":"MathOptInterface.Nonlinear.Model","text":"Model()\n\nThe core datastructure for representing a nonlinear optimization problem.\n\nIt has the following fields:\n\nobjective::Union{Nothing,Expression} : holds the nonlinear objective function, if one exists, otherwise nothing.\nexpressions::Vector{Expression} : a vector of expressions in the model.\nconstraints::OrderedDict{ConstraintIndex,Constraint} : a map from ConstraintIndex to the corresponding Constraint. An OrderedDict is used instead of a Vector to support constraint deletion.\nparameters::Vector{Float64} : holds the current values of the parameters.\noperators::OperatorRegistry : stores the operators used in the model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_expressions","page":"API Reference","title":"Expressions","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.ExpressionIndex\nNonlinear.add_expression","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ExpressionIndex","page":"API Reference","title":"MathOptInterface.Nonlinear.ExpressionIndex","text":"ExpressionIndex\n\nAn index to a nonlinear expression that is returned by add_expression.\n\nGiven data::Model and ex::ExpressionIndex, use data[ex] to retrieve the corresponding Expression.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.add_expression","page":"API Reference","title":"MathOptInterface.Nonlinear.add_expression","text":"add_expression(model::Model, expr)::ExpressionIndex\n\nParse expr into a Expression and add to model. Returns an ExpressionIndex that can be interpolated into other input expressions.\n\nexpr must be a type that is supported by parse_expression.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nex = add_expression(model, :($x^2 + 1))\nset_objective(model, :(sqrt($ex)))\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_parameters","page":"API Reference","title":"Parameters","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.ParameterIndex\nNonlinear.add_parameter","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ParameterIndex","page":"API Reference","title":"MathOptInterface.Nonlinear.ParameterIndex","text":"ParameterIndex\n\nAn index to a nonlinear parameter that is returned by add_parameter. Given data::Model and p::ParameterIndex, use data[p] to retrieve the current value of the parameter and data[p] = value to set a new value.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.add_parameter","page":"API Reference","title":"MathOptInterface.Nonlinear.add_parameter","text":"add_parameter(model::Model, value::Float64)::ParameterIndex\n\nAdd a new parameter to model with the default value value. Returns a ParameterIndex that can be interpolated into other input expressions and used to modify the value of the parameter.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\np = add_parameter(model, 1.2)\nc = add_constraint(model, :($x^2 - $p), MOI.LessThan(0.0))\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_objectives","page":"API Reference","title":"Objectives","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.set_objective","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.set_objective","page":"API Reference","title":"MathOptInterface.Nonlinear.set_objective","text":"set_objective(model::Model, obj)::Nothing\n\nParse obj into a Expression and set as the objective function of model.\n\nobj must be a type that is supported by parse_expression.\n\nTo remove the objective, pass nothing.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nset_objective(model, :($x^2 + 1))\nset_objective(model, x)\nset_objective(model, nothing)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_constraints","page":"API Reference","title":"Constraints","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.ConstraintIndex\nNonlinear.add_constraint\nNonlinear.delete","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ConstraintIndex","page":"API Reference","title":"MathOptInterface.Nonlinear.ConstraintIndex","text":"ConstraintIndex\n\nAn index to a nonlinear constraint that is returned by add_constraint.\n\nGiven data::Model and c::ConstraintIndex, use data[c] to retrieve the corresponding Constraint.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.add_constraint","page":"API Reference","title":"MathOptInterface.Nonlinear.add_constraint","text":"add_constraint(\n model::Model,\n func,\n set::Union{\n MOI.GreaterThan{Float64},\n MOI.LessThan{Float64},\n MOI.Interval{Float64},\n MOI.EqualTo{Float64},\n },\n)\n\nParse func and set into a Constraint and add to model. Returns a ConstraintIndex that can be used to delete the constraint or query solution information.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nc = add_constraint(model, :($x^2), MOI.LessThan(1.0))\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.delete","page":"API Reference","title":"MathOptInterface.Nonlinear.delete","text":"delete(model::Model, c::ConstraintIndex)::Nothing\n\nDelete the constraint index c from model.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nc = add_constraint(model, :($x^2), MOI.LessThan(1.0))\ndelete(model, c)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#nonlinear_api_operators","page":"API Reference","title":"User-defined operators","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.OperatorRegistry\nNonlinear.DEFAULT_UNIVARIATE_OPERATORS\nNonlinear.DEFAULT_MULTIVARIATE_OPERATORS\nNonlinear.register_operator\nNonlinear.register_operator_if_needed\nNonlinear.assert_registered\nNonlinear.check_return_type\nNonlinear.eval_univariate_function\nNonlinear.eval_univariate_gradient\nNonlinear.eval_univariate_hessian\nNonlinear.eval_multivariate_function\nNonlinear.eval_multivariate_gradient\nNonlinear.eval_multivariate_hessian\nNonlinear.eval_logic_function\nNonlinear.eval_comparison_function","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.OperatorRegistry","page":"API Reference","title":"MathOptInterface.Nonlinear.OperatorRegistry","text":"OperatorRegistry()\n\nCreate a new OperatorRegistry to store and evaluate univariate and multivariate operators.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS","page":"API Reference","title":"MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS","text":"DEFAULT_UNIVARIATE_OPERATORS\n\nThe list of univariate operators that are supported by default.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS\n72-element Vector{Symbol}:\n :+\n :-\n :abs\n :sqrt\n :cbrt\n :abs2\n :inv\n :log\n :log10\n :log2\n ⋮\n :airybi\n :airyaiprime\n :airybiprime\n :besselj0\n :besselj1\n :bessely0\n :bessely1\n :erfcx\n :dawson\n\n\n\n\n\n","category":"constant"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS","page":"API Reference","title":"MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS","text":"DEFAULT_MULTIVARIATE_OPERATORS\n\nThe list of multivariate operators that are supported by default.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS\n9-element Vector{Symbol}:\n :+\n :-\n :*\n :^\n :/\n :ifelse\n :atan\n :min\n :max\n\n\n\n\n\n","category":"constant"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.register_operator","page":"API Reference","title":"MathOptInterface.Nonlinear.register_operator","text":"register_operator(\n model::Model,\n op::Symbol,\n nargs::Int,\n f::Function,\n [∇f::Function],\n [∇²f::Function],\n)\n\nRegister the user-defined operator op with nargs input arguments in model.\n\nUnivariate functions\n\nf(x::T)::T must be a function that takes a single input argument x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.\n∇f(x::T)::T is a function that takes a single input argument x and returns the first derivative of f with respect to x. If ∇²f is not provided, ∇f must support any Real input type T.\n∇²f(x::T)::T is a function that takes a single input argument x and returns the second derivative of f with respect to x.\n\nMultivariate functions\n\nf(x::T...)::T must be a function that takes a nargs input arguments x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.\n∇f(g::AbstractVector{T}, x::T...)::T is a function that takes a cache vector g of length length(x), and fills each element g[i] with the partial derivative of f with respect to x[i].\n∇²f(H::AbstractMatrix, x::T...)::T is a function that takes a matrix H and fills the lower-triangular components H[i, j] with the Hessian of f with respect to x[i] and x[j] for i >= j.\n\nNotes for multivariate Hessians\n\nH has size(H) == (length(x), length(x)), but you must not access elements H[i, j] for i > j.\nH is dense, but you do not need to fill structural zeros.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.register_operator_if_needed","page":"API Reference","title":"MathOptInterface.Nonlinear.register_operator_if_needed","text":"register_operator_if_needed(\n registry::OperatorRegistry,\n op::Symbol,\n nargs::Int,\n f::Function;\n)\n\nSimilar to register_operator, but this function warns if the function is not registered, and skips silently if it already is.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.assert_registered","page":"API Reference","title":"MathOptInterface.Nonlinear.assert_registered","text":"assert_registered(registry::OperatorRegistry, op::Symbol, nargs::Int)\n\nThrow an error if op is not registered in registry with nargs arguments.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.check_return_type","page":"API Reference","title":"MathOptInterface.Nonlinear.check_return_type","text":"check_return_type(::Type{T}, ret::S) where {T,S}\n\nOverload this method for new types S to throw an informative error if a user-defined function returns the type S instead of T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_univariate_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_univariate_function","text":"eval_univariate_function(\n registry::OperatorRegistry,\n op::Symbol,\n x::T,\n) where {T}\n\nEvaluate the operator op(x)::T, where op is a univariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_univariate_gradient","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_univariate_gradient","text":"eval_univariate_gradient(\n registry::OperatorRegistry,\n op::Symbol,\n x::T,\n) where {T}\n\nEvaluate the first-derivative of the operator op(x)::T, where op is a univariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_univariate_hessian","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_univariate_hessian","text":"eval_univariate_hessian(\n registry::OperatorRegistry,\n op::Symbol,\n x::T,\n) where {T}\n\nEvaluate the second-derivative of the operator op(x)::T, where op is a univariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_multivariate_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_multivariate_function","text":"eval_multivariate_function(\n registry::OperatorRegistry,\n op::Symbol,\n x::AbstractVector{T},\n) where {T}\n\nEvaluate the operator op(x)::T, where op is a multivariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_multivariate_gradient","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_multivariate_gradient","text":"eval_multivariate_gradient(\n registry::OperatorRegistry,\n op::Symbol,\n g::AbstractVector{T},\n x::AbstractVector{T},\n) where {T}\n\nEvaluate the gradient of operator g .= ∇op(x), where op is a multivariate function in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_multivariate_hessian","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_multivariate_hessian","text":"eval_multivariate_hessian(\n registry::OperatorRegistry,\n op::Symbol,\n H::AbstractMatrix,\n x::AbstractVector{T},\n) where {T}\n\nEvaluate the Hessian of operator ∇²op(x), where op is a multivariate function in registry.\n\nThe Hessian is stored in the lower-triangular part of the matrix H.\n\nnote: Note\nImplementations of the Hessian operators will not fill structural zeros. Therefore, before calling this function you should pre-populate the matrix H with 0.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_logic_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_logic_function","text":"eval_logic_function(\n registry::OperatorRegistry,\n op::Symbol,\n lhs::T,\n rhs::T,\n)::Bool where {T}\n\nEvaluate (lhs op rhs)::Bool, where op is a logic operator in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.eval_comparison_function","page":"API Reference","title":"MathOptInterface.Nonlinear.eval_comparison_function","text":"eval_comparison_function(\n registry::OperatorRegistry,\n op::Symbol,\n lhs::T,\n rhs::T,\n)::Bool where {T}\n\nEvaluate (lhs op rhs)::Bool, where op is a comparison operator in registry.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#Automatic-differentiation-backends","page":"API Reference","title":"Automatic-differentiation backends","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.Evaluator\nNonlinear.AbstractAutomaticDifferentiation\nNonlinear.ExprGraphOnly\nNonlinear.SparseReverseMode","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Evaluator","page":"API Reference","title":"MathOptInterface.Nonlinear.Evaluator","text":"Evaluator(\n model::Model,\n backend::AbstractAutomaticDifferentiation,\n ordered_variables::Vector{MOI.VariableIndex},\n)\n\nCreate Evaluator, a subtype of MOI.AbstractNLPEvaluator, from Model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.AbstractAutomaticDifferentiation","page":"API Reference","title":"MathOptInterface.Nonlinear.AbstractAutomaticDifferentiation","text":"AbstractAutomaticDifferentiation\n\nAn abstract type for extending Evaluator.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ExprGraphOnly","page":"API Reference","title":"MathOptInterface.Nonlinear.ExprGraphOnly","text":"ExprGraphOnly() <: AbstractAutomaticDifferentiation\n\nThe default implementation of AbstractAutomaticDifferentiation. The only supported feature is :ExprGraph.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.SparseReverseMode","page":"API Reference","title":"MathOptInterface.Nonlinear.SparseReverseMode","text":"SparseReverseMode() <: AbstractAutomaticDifferentiation\n\nAn implementation of AbstractAutomaticDifferentiation that uses sparse reverse-mode automatic differentiation to compute derivatives. Supports all features in the MOI nonlinear interface.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#Data-structure","page":"API Reference","title":"Data-structure","text":"","category":"section"},{"location":"submodules/Nonlinear/reference/","page":"API Reference","title":"API Reference","text":"Nonlinear.Node\nNonlinear.NodeType\nNonlinear.Expression\nNonlinear.Constraint\nNonlinear.adjacency_matrix\nNonlinear.parse_expression\nNonlinear.convert_to_expr\nNonlinear.ordinal_index","category":"page"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Node","page":"API Reference","title":"MathOptInterface.Nonlinear.Node","text":"struct Node\n type::NodeType\n index::Int\n parent::Int\nend\n\nA single node in a nonlinear expression tree. Used by Expression.\n\nSee the MathOptInterface documentation for information on how the nodes and values form an expression tree.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.NodeType","page":"API Reference","title":"MathOptInterface.Nonlinear.NodeType","text":"NodeType\n\nAn enum describing the possible node types. Each Node has a .index field, which should be interpreted as follows:\n\nNODE_CALL_MULTIVARIATE: the index into operators.multivariate_operators\nNODE_CALL_UNIVARIATE: the index into operators.univariate_operators\nNODE_LOGIC: the index into operators.logic_operators\nNODE_COMPARISON: the index into operators.comparison_operators\nNODE_MOI_VARIABLE: the value of MOI.VariableIndex(index) in the user's space of the model.\nNODE_VARIABLE: the 1-based index of the internal vector\nNODE_VALUE: the index into the .values field of Expression\nNODE_PARAMETER: the index into data.parameters\nNODE_SUBEXPRESSION: the index into data.expressions\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Expression","page":"API Reference","title":"MathOptInterface.Nonlinear.Expression","text":"struct Expression\n nodes::Vector{Node}\n values::Vector{Float64}\nend\n\nThe core type that represents a nonlinear expression. See the MathOptInterface documentation for information on how the nodes and values form an expression tree.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.Constraint","page":"API Reference","title":"MathOptInterface.Nonlinear.Constraint","text":"struct Constraint\n expression::Expression\n set::Union{\n MOI.LessThan{Float64},\n MOI.GreaterThan{Float64},\n MOI.EqualTo{Float64},\n MOI.Interval{Float64},\n }\nend\n\nA type to hold information relating to the nonlinear constraint f(x) in S, where f(x) is defined by .expression, and S is .set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.adjacency_matrix","page":"API Reference","title":"MathOptInterface.Nonlinear.adjacency_matrix","text":"adjacency_matrix(nodes::Vector{Node})\n\nCompute the sparse adjacency matrix describing the parent-child relationships in nodes.\n\nThe element (i, j) is true if there is an edge from node[j] to node[i]. Since we get a column-oriented matrix, this gives us a fast way to look up the edges leaving any node (that is, the children).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.parse_expression","page":"API Reference","title":"MathOptInterface.Nonlinear.parse_expression","text":"parse_expression(data::Model, input)::Expression\n\nParse input into a Expression.\n\n\n\n\n\nparse_expression(\n data::Model,\n expr::Expression,\n input::Any,\n parent_index::Int,\n)::Expression\n\nParse input into a Expression, and add it to expr as a child of expr.nodes[parent_index]. Existing subexpressions and parameters are stored in data.\n\nYou can extend parsing support to new types of objects by overloading this method with a different type on input::Any.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.convert_to_expr","page":"API Reference","title":"MathOptInterface.Nonlinear.convert_to_expr","text":"convert_to_expr(data::Model, expr::Expression)\n\nConvert the Expression expr into a Julia Expr.\n\nsubexpressions are represented by a ExpressionIndex object.\nparameters are represented by a ParameterIndex object.\nvariables are represented by an MOI.VariableIndex object.\n\n\n\n\n\nconvert_to_expr(\n evaluator::Evaluator,\n expr::Expression;\n moi_output_format::Bool,\n)\n\nConvert the Expression expr into a Julia Expr.\n\nIf moi_output_format = true:\n\nsubexpressions will be converted to Julia Expr and substituted into the output expression.\nthe current value of each parameter will be interpolated into the expression\nvariables will be represented in the form x[MOI.VariableIndex(i)]\n\nIf moi_output_format = false:\n\nsubexpressions will be represented by a ExpressionIndex object.\nparameters will be represented by a ParameterIndex object.\nvariables will be represented by an MOI.VariableIndex object.\n\nwarning: Warning\nTo use moi_output_format = true, you must have first called MOI.initialize with :ExprGraph as a requested feature.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Nonlinear/reference/#MathOptInterface.Nonlinear.ordinal_index","page":"API Reference","title":"MathOptInterface.Nonlinear.ordinal_index","text":"ordinal_index(evaluator::Evaluator, c::ConstraintIndex)::Int\n\nReturn the 1-indexed value of the constraint index c in evaluator.\n\nExamples\n\nmodel = Model()\nx = MOI.VariableIndex(1)\nc1 = add_constraint(model, :($x^2), MOI.LessThan(1.0))\nc2 = add_constraint(model, :($x^2), MOI.LessThan(1.0))\nevaluator = Evaluator(model)\nMOI.initialize(evaluator, Symbol[])\nordinal_index(evaluator, c2) # Returns 2\ndelete(model, c1)\nevaluator = Evaluator(model)\nMOI.initialize(evaluator, Symbol[])\nordinal_index(model, c2) # Returns 1\n\n\n\n\n\n","category":"function"},{"location":"manual/models/","page":"Models","title":"Models","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/models/#Models","page":"Models","title":"Models","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"The most significant part of MOI is the definition of the model API that is used to specify an instance of an optimization problem (for example, by adding variables and constraints). Objects that implement the model API must inherit from the ModelLike abstract type.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Notably missing from the model API is the method to solve an optimization problem. ModelLike objects may store an instance (for example, in memory or backed by a file format) without being linked to a particular solver. In addition to the model API, MOI defines AbstractOptimizer and provides methods to solve the model and interact with solutions. See the Solutions section for more details.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"info: Info\nThroughout the rest of the manual, model is used as a generic ModelLike, and optimizer is used as a generic AbstractOptimizer.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"tip: Tip\nMOI does not export functions, but for brevity we often omit qualifying names with the MOI module. Best practice is to haveimport MathOptInterface as MOIand prefix all MOI methods with MOI. in user code. If a name is also available in base Julia, we always explicitly use the module prefix, for example, with MOI.get.","category":"page"},{"location":"manual/models/#Attributes","page":"Models","title":"Attributes","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"Attributes are properties of the model that can be queried and modified. These include constants such as the number of variables in a model NumberOfVariables), and properties of variables and constraints such as the name of a variable (VariableName).","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"There are four types of attributes:","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Model attributes (subtypes of AbstractModelAttribute) refer to properties of a model.\nOptimizer attributes (subtypes of AbstractOptimizerAttribute) refer to properties of an optimizer.\nConstraint attributes (subtypes of AbstractConstraintAttribute) refer to properties of an individual constraint.\nVariable attributes (subtypes of AbstractVariableAttribute) refer to properties of an individual variable.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Some attributes are values that can be queried by the user but not modified, while other attributes can be modified by the user.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"All interactions with attributes occur through the get and set functions.","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"Consult the docstrings of each attribute for information on what it represents.","category":"page"},{"location":"manual/models/#ModelLike-API","page":"Models","title":"ModelLike API","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"The following attributes are available:","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"ListOfConstraintAttributesSet\nListOfConstraintIndices\nListOfConstraintTypesPresent\nListOfConstraintsWithAttributeSet\nListOfModelAttributesSet\nListOfVariableAttributesSet\nListOfVariableIndices\nListOfVariablesWithAttributeSet\nNumberOfConstraints\nNumberOfVariables\nName\nObjectiveFunction\nObjectiveFunctionType\nObjectiveSense","category":"page"},{"location":"manual/models/#AbstractOptimizer-API","page":"Models","title":"AbstractOptimizer API","text":"","category":"section"},{"location":"manual/models/","page":"Models","title":"Models","text":"The following attributes are available:","category":"page"},{"location":"manual/models/","page":"Models","title":"Models","text":"DualStatus\nPrimalStatus\nRawStatusString\nResultCount\nTerminationStatus\nBarrierIterations\nDualObjectiveValue\nNodeCount\nNumberOfThreads\nObjectiveBound\nObjectiveValue\nRelativeGap\nRawOptimizerAttribute\nRawSolver\nSilent\nSimplexIterations\nSolverName\nSolverVersion\nSolveTimeSec\nTimeLimitSec\nObjectiveLimit\nSolutionLimit\nAutomaticDifferentiationBackend","category":"page"},{"location":"tutorials/mathprogbase/#Transitioning-from-MathProgBase","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"MathOptInterface is a replacement for MathProgBase.jl. However, it is not a direct replacement.","category":"page"},{"location":"tutorials/mathprogbase/#Transitioning-a-solver-interface","page":"Transitioning from MathProgBase","title":"Transitioning a solver interface","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"MathOptInterface is more extensive than MathProgBase which may make its implementation seem daunting at first. There are however numerous utilities in MathOptInterface that the simplify implementation process.","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"For more information, read Implementing a solver interface.","category":"page"},{"location":"tutorials/mathprogbase/#Transitioning-the-high-level-functions","page":"Transitioning from MathProgBase","title":"Transitioning the high-level functions","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"MathOptInterface doesn't provide replacements for the high-level interfaces in MathProgBase. We recommend you use JuMP as a modeling interface instead.","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"tip: Tip\nIf you haven't used JuMP before, start with the tutorial Getting started with JuMP","category":"page"},{"location":"tutorials/mathprogbase/#linprog","page":"Transitioning from MathProgBase","title":"linprog","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"Here is one way of transitioning from linprog:","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"using JuMP\n\nfunction linprog(c, A, sense, b, l, u, solver)\n N = length(c)\n model = Model(solver)\n @variable(model, l[i] <= x[i=1:N] <= u[i])\n @objective(model, Min, c' * x)\n eq_rows, ge_rows, le_rows = sense .== '=', sense .== '>', sense .== '<'\n @constraint(model, A[eq_rows, :] * x .== b[eq_rows])\n @constraint(model, A[ge_rows, :] * x .>= b[ge_rows])\n @constraint(model, A[le_rows, :] * x .<= b[le_rows])\n optimize!(model)\n return (\n status = termination_status(model),\n objval = objective_value(model),\n sol = value.(x)\n )\nend","category":"page"},{"location":"tutorials/mathprogbase/#mixintprog","page":"Transitioning from MathProgBase","title":"mixintprog","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"Here is one way of transitioning from mixintprog:","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"using JuMP\n\nfunction mixintprog(c, A, rowlb, rowub, vartypes, lb, ub, solver)\n N = length(c)\n model = Model(solver)\n @variable(model, lb[i] <= x[i=1:N] <= ub[i])\n for i in 1:N\n if vartypes[i] == :Bin\n set_binary(x[i])\n elseif vartypes[i] == :Int\n set_integer(x[i])\n end\n end\n @objective(model, Min, c' * x)\n @constraint(model, rowlb .<= A * x .<= rowub)\n optimize!(model)\n return (\n status = termination_status(model),\n objval = objective_value(model),\n sol = value.(x)\n )\nend","category":"page"},{"location":"tutorials/mathprogbase/#quadprog","page":"Transitioning from MathProgBase","title":"quadprog","text":"","category":"section"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"Here is one way of transitioning from quadprog:","category":"page"},{"location":"tutorials/mathprogbase/","page":"Transitioning from MathProgBase","title":"Transitioning from MathProgBase","text":"using JuMP\n\nfunction quadprog(c, Q, A, rowlb, rowub, lb, ub, solver)\n N = length(c)\n model = Model(solver)\n @variable(model, lb[i] <= x[i=1:N] <= ub[i])\n @objective(model, Min, c' * x + 0.5 * x' * Q * x)\n @constraint(model, rowlb .<= A * x .<= rowub)\n optimize!(model)\n return (\n status = termination_status(model),\n objval = objective_value(model),\n sol = value.(x)\n )\nend","category":"page"},{"location":"submodules/Test/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Test/reference/#test_reference","page":"API Reference","title":"The Test submodule","text":"","category":"section"},{"location":"submodules/Test/reference/","page":"API Reference","title":"API Reference","text":"Functions to help test implementations of MOI. See The Test submodule for more details.","category":"page"},{"location":"submodules/Test/reference/","page":"API Reference","title":"API Reference","text":"Test.Config\nTest.runtests\nTest.setup_test\nTest.version_added\nTest.@requires\nTest.RequirementUnmet","category":"page"},{"location":"submodules/Test/reference/#MathOptInterface.Test.Config","page":"API Reference","title":"MathOptInterface.Test.Config","text":"Config(\n ::Type{T} = Float64;\n atol::Real = Base.rtoldefault(T),\n rtol::Real = Base.rtoldefault(T),\n optimal_status::MOI.TerminationStatusCode = MOI.OPTIMAL,\n infeasible_status::MOI.TerminationStatusCode = MOI.INFEASIBLE,\n exclude::Vector{Any} = Any[],\n) where {T}\n\nReturn an object that is used to configure various tests.\n\nConfiguration arguments\n\natol::Real = Base.rtoldefault(T): Control the absolute tolerance used when comparing solutions.\nrtol::Real = Base.rtoldefault(T): Control the relative tolerance used when comparing solutions.\noptimal_status = MOI.OPTIMAL: Set to MOI.LOCALLY_SOLVED if the solver cannot prove global optimality.\ninfeasible_status = MOI.INFEASIBLE: Set to MOI.LOCALLY_INFEASIBLE if the solver cannot prove global infeasibility.\nexclude = Vector{Any}: Pass attributes or functions to exclude to skip parts of tests that require certain functionality. Common arguments include:\nMOI.delete to skip deletion-related tests\nMOI.optimize! to skip optimize-related tests\nMOI.ConstraintDual to skip dual-related tests\nMOI.VariableName to skip setting variable names\nMOI.ConstraintName to skip setting constraint names\n\nExamples\n\nFor a nonlinear solver that finds local optima and does not support finding dual variables or constraint names:\n\nConfig(\n Float64;\n optimal_status = MOI.LOCALLY_SOLVED,\n exclude = Any[\n MOI.ConstraintDual,\n MOI.VariableName,\n MOI.ConstraintName,\n MOI.delete,\n ],\n)\n\n\n\n\n\n","category":"type"},{"location":"submodules/Test/reference/#MathOptInterface.Test.runtests","page":"API Reference","title":"MathOptInterface.Test.runtests","text":"runtests(\n model::MOI.ModelLike,\n config::Config;\n include::Vector{Union{String,Regex}} = String[],\n exclude::Vector{Union{String,Regex}} = String[],\n warn_unsupported::Bool = false,\n exclude_tests_after::VersionNumber = v\"999.0.0\",\n verbose::Bool = false,\n)\n\nRun all tests in MathOptInterface.Test on model.\n\nConfiguration arguments\n\nconfig is a Test.Config object that can be used to modify the behavior of tests.\nIf include is not empty, only run tests if an element from include occursin the name of the test.\nIf exclude is not empty, skip tests if an element from exclude occursin the name of the test.\nexclude takes priority over include.\nIf warn_unsupported is false, runtests will silently skip tests that fail with a MOI.NotAllowedError, MOI.UnsupportedError, or RequirementUnmet error. (The latter is thrown when an @requires statement returns false.) When warn_unsupported is true, a warning will be printed. For most cases the default behavior, false, is what you want, since these tests likely test functionality that is not supported by model. However, it can be useful to run warn_unsupported = true to check you are not skipping tests due to a missing supports_constraint method or equivalent.\nexclude_tests_after is a version number that excludes any tests to MOI added after that version number. This is useful for solvers who can declare a fixed set of tests, and not cause their tests to break if a new patch of MOI is released with a new test.\nverbose is a Bool that controls whether the name of the test is printed before executing it. This can be helpful when debugging.\n\nSee also: setup_test.\n\nExample\n\nconfig = MathOptInterface.Test.Config()\nMathOptInterface.Test.runtests(\n model,\n config;\n include = [\"test_linear_\", r\"^test_model_Name$\"],\n exclude = [\"VariablePrimalStart\"],\n warn_unsupported = true,\n verbose = true,\n exclude_tests_after = v\"0.10.5\",\n)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/reference/#MathOptInterface.Test.setup_test","page":"API Reference","title":"MathOptInterface.Test.setup_test","text":"setup_test(::typeof(f), model::MOI.ModelLike, config::Config)\n\nOverload this method to modify model before running the test function f on model with config. You can also modify the fields in config (for example, to loosen the default tolerances).\n\nThis function should either return nothing, or return a function which, when called with zero arguments, undoes the setup to return the model to its previous state. You do not need to undo any modifications to config.\n\nThis function is most useful when writing new tests of the tests for MOI, but it can also be used to set test-specific tolerances, etc.\n\nSee also: runtests\n\nExample\n\nfunction MOI.Test.setup_test(\n ::typeof(MOI.Test.test_linear_VariablePrimalStart_partial),\n mock::MOIU.MockOptimizer,\n ::MOI.Test.Config,\n)\n MOIU.set_mock_optimize!(\n mock,\n (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 0.0]),\n )\n mock.eval_variable_constraint_dual = false\n\n function reset_function()\n mock.eval_variable_constraint_dual = true\n return\n end\n return reset_function\nend\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/reference/#MathOptInterface.Test.version_added","page":"API Reference","title":"MathOptInterface.Test.version_added","text":"version_added(::typeof(function_name))\n\nReturns the version of MOI in which the test function_name was added.\n\nThis method should be implemented for all new tests.\n\nSee the exclude_tests_after keyword of runtests for more details.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/reference/#MathOptInterface.Test.@requires","page":"API Reference","title":"MathOptInterface.Test.@requires","text":"@requires(x)\n\nCheck that the condition x is true. Otherwise, throw an RequirementUnmet error to indicate that the model does not support something required by the test function.\n\nExamples\n\n@requires MOI.supports(model, MOI.Silent())\n@test MOI.get(model, MOI.Silent())\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Test/reference/#MathOptInterface.Test.RequirementUnmet","page":"API Reference","title":"MathOptInterface.Test.RequirementUnmet","text":"RequirementUnmet(msg::String) <: Exception\n\nAn error for throwing in tests to indicate that the model does not support some requirement expected by the test function.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Benchmarks/overview/#The-Benchmarks-submodule","page":"Overview","title":"The Benchmarks submodule","text":"","category":"section"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"To aid the development of efficient solver wrappers, MathOptInterface provides benchmarking capability. Benchmarking a wrapper follows a two-step process.","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"First, prior to making changes, create a baseline for the benchmark results on a given benchmark suite as follows:","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"using SolverPackage # Replace with your choice of solver.\nimport MathOptInterface as MOI\n\nsuite = MOI.Benchmarks.suite() do\n SolverPackage.Optimizer()\nend\n\nMOI.Benchmarks.create_baseline(\n suite, \"current\"; directory = \"/tmp\", verbose = true\n)","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"Use the exclude argument to Benchmarks.suite to exclude benchmarks that the solver doesn't support.","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"Second, after making changes to the package, re-run the benchmark suite and compare to the prior saved results:","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"using SolverPackage\nimport MathOptInterface as MOI\n\nsuite = MOI.Benchmarks.suite() do\n SolverPackage.Optimizer()\nend\n\nMOI.Benchmarks.compare_against_baseline(\n suite, \"current\"; directory = \"/tmp\", verbose = true\n)","category":"page"},{"location":"submodules/Benchmarks/overview/","page":"Overview","title":"Overview","text":"This comparison will create a report detailing improvements and regressions.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/FileFormats/overview/#The-FileFormats-submodule","page":"Overview","title":"The FileFormats submodule","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The FileFormats module provides functions for reading and writing MOI models using write_to_file and read_from_file.","category":"page"},{"location":"submodules/FileFormats/overview/#Supported-file-types","page":"Overview","title":"Supported file types","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"You must read and write files to a FileFormats.Model object. Specific the file-type by passing a FileFormats.FileFormat enum. For example:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The Conic Benchmark Format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)\nA Conic Benchmark Format (CBF) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The LP file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_LP)\nA .LP-file model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The MathOptFormat file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)\nA MathOptFormat Model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The MPS file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)\nA Mathematical Programming System (MPS) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The NL file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_NL)\nAn AMPL (.nl) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The REW file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_REW)\nA Mathematical Programming System (MPS) model","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Note that the REW format is identical to the MPS file format, except that all names are replaced with generic identifiers.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"The SDPA file format","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_SDPA)\nA SemiDefinite Programming Algorithm Format (SDPA) model","category":"page"},{"location":"submodules/FileFormats/overview/#Write-to-file","page":"Overview","title":"Write to file","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"To write a model src to a MathOptFormat file, use:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> MOI.add_variable(src)\nMOI.VariableIndex(1)\n\njulia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)\nA MathOptFormat Model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap with 1 entry:\n MOI.VariableIndex(1) => MOI.VariableIndex(1)\n\njulia> MOI.write_to_file(dest, \"file.mof.json\")\n\njulia> print(read(\"file.mof.json\", String))\n{\n \"name\": \"MathOptFormat Model\",\n \"version\": {\n \"major\": 1,\n \"minor\": 7\n },\n \"variables\": [\n {\n \"name\": \"x1\"\n }\n ],\n \"objective\": {\n \"sense\": \"feasibility\"\n },\n \"constraints\": []\n}","category":"page"},{"location":"submodules/FileFormats/overview/#Read-from-file","page":"Overview","title":"Read from file","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"To read a MathOptFormat file, use:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)\nA MathOptFormat Model\n\njulia> MOI.read_from_file(dest, \"file.mof.json\")\n\njulia> MOI.get(dest, MOI.ListOfVariableIndices())\n1-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n\njulia> rm(\"file.mof.json\") # Clean up after ourselves.","category":"page"},{"location":"submodules/FileFormats/overview/#Detecting-the-file-type-automatically","page":"Overview","title":"Detecting the file-type automatically","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Instead of the format keyword, you can also use the filename keyword argument to FileFormats.Model. This will attempt to automatically guess the format from the file extension. For example:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> dest = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap()\n\njulia> MOI.write_to_file(dest, \"file.cbf.gz\")\n\njulia> src_2 = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> dest = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap()\n\njulia> MOI.write_to_file(dest, \"file.cbf.gz\")\n\njulia> src_2 = MOI.FileFormats.Model(filename = \"file.cbf.gz\")\nA Conic Benchmark Format (CBF) model\n\njulia> MOI.read_from_file(src_2, \"file.cbf.gz\")\n\njulia> rm(\"file.cbf.gz\") # Clean up after ourselves.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Note how the compression format (GZip) is also automatically detected from the filename.","category":"page"},{"location":"submodules/FileFormats/overview/#Unsupported-constraints","page":"Overview","title":"Unsupported constraints","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"In some cases src may contain constraints that are not supported by the file format (for example, the CBF format supports integer variables but not binary). If so, copy src to a bridged model using Bridges.full_bridge_optimizer:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"src = MOI.Utilities.Model{Float64}()\nx = MOI.add_variable(model)\nMOI.add_constraint(model, x, MOI.ZeroOne())\ndest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)\nbridged = MOI.Bridges.full_bridge_optimizer(dest, Float64)\nMOI.copy_to(bridged, src)\nMOI.write_to_file(dest, \"my_model.cbf\")","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"note: Note\nEven after bridging, it may still not be possible to write the model to file because of unsupported constraints (for example, PSD variables in the LP file format).","category":"page"},{"location":"submodules/FileFormats/overview/#Read-and-write-to-io","page":"Overview","title":"Read and write to io","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"In addition to write_to_file and read_from_file, you can read and write directly from IO streams using Base.write and Base.read!:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> src = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)\nA Mathematical Programming System (MPS) model\n\njulia> MOI.copy_to(dest, src)\nMathOptInterface.Utilities.IndexMap()\n\njulia> io = IOBuffer();\n\njulia> write(io, dest)\n\njulia> seekstart(io);\n\njulia> src_2 = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)\nA Mathematical Programming System (MPS) model\n\njulia> read!(io, src_2);","category":"page"},{"location":"submodules/FileFormats/overview/#ScalarNonlinearFunction","page":"Overview","title":"ScalarNonlinearFunction","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"By default, reading a .nl or .mof.json that contains nonlinear expressions will create an NLPBlock.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"To instead read nonlinear expressions as ScalarNonlinearFunction, pass the use_nlp_block = false keyword argument to the Model constructor:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.FileFormats.Model(;\n format = MOI.FileFormats.FORMAT_MOF,\n use_nlp_block = false,\n )\nA MathOptFormat Model\n\njulia> model = MOI.FileFormats.Model(;\n format = MOI.FileFormats.FORMAT_NL,\n use_nlp_block = false,\n )\nAn AMPL (.nl) model","category":"page"},{"location":"submodules/FileFormats/overview/#Validating-MOF-files","page":"Overview","title":"Validating MOF files","text":"","category":"section"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"MathOptFormat files are governed by a schema. Use JSONSchema.jl to check if a .mof.json file satisfies the schema.","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"First, construct the schema object as follows:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> import JSON, JSONSchema\n\njulia> schema = JSONSchema.Schema(JSON.parsefile(MOI.FileFormats.MOF.SCHEMA_PATH))\nA JSONSchema","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Then, check if a model file is valid using isvalid:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> good_model = JSON.parse(\"\"\"\n {\n \"version\": {\n \"major\": 1,\n \"minor\": 5\n },\n \"variables\": [{\"name\": \"x\"}],\n \"objective\": {\"sense\": \"feasibility\"},\n \"constraints\": []\n }\n \"\"\");\n\njulia> isvalid(schema, good_model)\ntrue","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"If we construct an invalid file, for example by mis-typing name as NaMe, the validation fails:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> bad_model = JSON.parse(\"\"\"\n {\n \"version\": {\n \"major\": 1,\n \"minor\": 5\n },\n \"variables\": [{\"NaMe\": \"x\"}],\n \"objective\": {\"sense\": \"feasibility\"},\n \"constraints\": []\n }\n \"\"\");\n\njulia> isvalid(schema, bad_model)\nfalse","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"Use JSONSchema.validate to obtain more insight into why the validation failed:","category":"page"},{"location":"submodules/FileFormats/overview/","page":"Overview","title":"Overview","text":"julia> JSONSchema.validate(schema, bad_model)\nValidation failed:\npath: [variables][1]\ninstance: Dict{String, Any}(\"NaMe\" => \"x\")\nschema key: required\nschema value: Any[\"name\"]","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/example/#Solving-a-problem-using-MathOptInterface","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"In this tutorial we demonstrate how to use MathOptInterface to solve the binary-constrained knapsack problem:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"beginaligned\nmax c^top x \nst w^top x le C \n x_i in 01quad forall i=1ldotsn\nendaligned","category":"page"},{"location":"tutorials/example/#Required-packages","page":"Solving a problem using MathOptInterface","title":"Required packages","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"Load the MathOptInterface module and define the shorthand MOI:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"import MathOptInterface as MOI","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"As an optimizer, we choose GLPK:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"using GLPK\noptimizer = GLPK.Optimizer()","category":"page"},{"location":"tutorials/example/#Define-the-data","page":"Solving a problem using MathOptInterface","title":"Define the data","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"We first define the constants of the problem:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> c = [1.0, 2.0, 3.0]\n3-element Vector{Float64}:\n 1.0\n 2.0\n 3.0\n\njulia> w = [0.3, 0.5, 1.0]\n3-element Vector{Float64}:\n 0.3\n 0.5\n 1.0\n\njulia> C = 3.2\n3.2","category":"page"},{"location":"tutorials/example/#Add-the-variables","page":"Solving a problem using MathOptInterface","title":"Add the variables","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> x = MOI.add_variables(optimizer, length(c));","category":"page"},{"location":"tutorials/example/#set_objective_example","page":"Solving a problem using MathOptInterface","title":"Set the objective","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.set(\n optimizer,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0),\n );\n\njulia> MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"tip: Tip\nMOI.ScalarAffineTerm.(c, x) is a shortcut for [MOI.ScalarAffineTerm(c[i], x[i]) for i = 1:3]. This is Julia's broadcast syntax in action, and is used quite often throughout MOI.","category":"page"},{"location":"tutorials/example/#Add-the-constraints","page":"Solving a problem using MathOptInterface","title":"Add the constraints","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"We add the knapsack constraint and integrality constraints:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.add_constraint(\n optimizer,\n MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(w, x), 0.0),\n MOI.LessThan(C),\n );","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"Add integrality constraints:","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> for x_i in x\n MOI.add_constraint(optimizer, x_i, MOI.ZeroOne())\n end","category":"page"},{"location":"tutorials/example/#Optimize-the-model","page":"Solving a problem using MathOptInterface","title":"Optimize the model","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.optimize!(optimizer)","category":"page"},{"location":"tutorials/example/#Understand-why-the-solver-stopped","page":"Solving a problem using MathOptInterface","title":"Understand why the solver stopped","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"The first thing to check after optimization is why the solver stopped, for example, did it stop because of a time limit or did it stop because it found the optimal solution?","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.TerminationStatus())\nOPTIMAL::TerminationStatusCode = 1","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"Looks like we found an optimal solution.","category":"page"},{"location":"tutorials/example/#Understand-what-solution-was-returned","page":"Solving a problem using MathOptInterface","title":"Understand what solution was returned","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.ResultCount())\n1\n\njulia> MOI.get(optimizer, MOI.PrimalStatus())\nFEASIBLE_POINT::ResultStatusCode = 1\n\njulia> MOI.get(optimizer, MOI.DualStatus())\nNO_SOLUTION::ResultStatusCode = 0","category":"page"},{"location":"tutorials/example/#Query-the-objective","page":"Solving a problem using MathOptInterface","title":"Query the objective","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"What is its objective value?","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.ObjectiveValue())\n6.0","category":"page"},{"location":"tutorials/example/#Query-the-primal-solution","page":"Solving a problem using MathOptInterface","title":"Query the primal solution","text":"","category":"section"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"And what is the value of the variables x?","category":"page"},{"location":"tutorials/example/","page":"Solving a problem using MathOptInterface","title":"Solving a problem using MathOptInterface","text":"julia> MOI.get(optimizer, MOI.VariablePrimal(), x)\n3-element Vector{Float64}:\n 1.0\n 1.0\n 1.0","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Utilities/reference/#Utilities.Model","page":"API Reference","title":"Utilities.Model","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.Model","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.Model","page":"API Reference","title":"MathOptInterface.Utilities.Model","text":"MOI.Utilities.Model{T}() where {T}\n\nAn implementation of ModelLike that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.\n\nExamples\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Utilities.UniversalFallback","page":"API Reference","title":"Utilities.UniversalFallback","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.UniversalFallback","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.UniversalFallback","page":"API Reference","title":"MathOptInterface.Utilities.UniversalFallback","text":"UniversalFallback\n\nThe UniversalFallback can be applied on a MOI.ModelLike model to create the model UniversalFallback(model) supporting any constraint and attribute. This allows to have a specialized implementation in model for performance critical constraints and attributes while still supporting other attributes with a small performance penalty. Note that model is unaware of constraints and attributes stored by UniversalFallback so this is not appropriate if model is an optimizer (for this reason, MOI.optimize! has not been implemented). In that case, optimizer bridges should be used instead.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Utilities.@model","page":"API Reference","title":"Utilities.@model","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.@model\nUtilities.GenericModel\nUtilities.GenericOptimizer","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@model","page":"API Reference","title":"MathOptInterface.Utilities.@model","text":"macro model(\n model_name,\n scalar_sets,\n typed_scalar_sets,\n vector_sets,\n typed_vector_sets,\n scalar_functions,\n typed_scalar_functions,\n vector_functions,\n typed_vector_functions,\n is_optimizer = false\n)\n\nCreates a type model_name implementing the MOI model interface and supporting all combinations of the provided functions and sets.\n\nEach typed_ scalar/vector sets/functions argument is a tuple of types. A type is \"typed\" if it has a coefficient {T} as the first type parameter.\n\nTuple syntax\n\nTo give no set/function, write (). To give one set or function X, write (X,).\n\nis_optimizer\n\nIf is_optimizer = true, the resulting struct is a of GenericOptimizer, which is a subtype of MOI.AbstractOptimizer, otherwise, it is a GenericModel, which is a subtype of MOI.ModelLike.\n\nVariableIndex\n\nThe function MOI.VariableIndex must not be given in scalar_functions.\nThe model supports MOI.VariableIndex-in-S constraints where S is MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval, MOI.Integer, MOI.ZeroOne, MOI.Semicontinuous or MOI.Semiinteger.\nThe sets supported with MOI.VariableIndex cannot be controlled from the macro; use UniversalFallback to support more sets.\n\nExamples\n\nThe model describing a linear program would be:\n\n@model(\n LPModel, # model_name\n (), # untyped scalar sets\n (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), # typed scalar sets\n (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives), # untyped vector sets\n (), # typed vector sets\n (), # untyped scalar functions\n (MOI.ScalarAffineFunction,), # typed scalar functions\n (MOI.VectorOfVariables,), # untyped vector functions\n (MOI.VectorAffineFunction,), # typed vector functions\n false, # is_optimizer\n)\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.GenericModel","page":"API Reference","title":"MathOptInterface.Utilities.GenericModel","text":"mutable struct GenericModel{T,O,V,C} <: AbstractModelLike{T}\n\nImplements a model supporting coefficients of type T and:\n\nAn objective function stored in .objective::O\nVariables and VariableIndex constraints stored in .variable_bounds::V\nF-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C\n\nAll interactions take place via the MOI interface, so the types O, V, and C must implement the API as needed for their functionality.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.GenericOptimizer","page":"API Reference","title":"MathOptInterface.Utilities.GenericOptimizer","text":"mutable struct GenericOptimizer{T,O,V,C} <: AbstractOptimizer{T}\n\nImplements a model supporting coefficients of type T and:\n\nAn objective function stored in .objective::O\nVariables and VariableIndex constraints stored in .variable_bounds::V\nF-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C\n\nAll interactions take place via the MOI interface, so the types O, V, and C must implement the API as needed for their functionality.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.objective","page":"API Reference","title":".objective","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.ObjectiveContainer","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ObjectiveContainer","page":"API Reference","title":"MathOptInterface.Utilities.ObjectiveContainer","text":"ObjectiveContainer{T}\n\nA helper struct to simplify the handling of objective functions in Utilities.Model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.variables","page":"API Reference","title":".variables","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.VariablesContainer\nUtilities.FreeVariables","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.VariablesContainer","page":"API Reference","title":"MathOptInterface.Utilities.VariablesContainer","text":"struct VariablesContainer{T} <: AbstractVectorBounds\n set_mask::Vector{UInt16}\n lower::Vector{T}\n upper::Vector{T}\nend\n\nA struct for storing variables and VariableIndex-related constraints. Used in MOI.Utilities.Model by default.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.FreeVariables","page":"API Reference","title":"MathOptInterface.Utilities.FreeVariables","text":"mutable struct FreeVariables <: MOI.ModelLike\n n::Int64\n FreeVariables() = new(0)\nend\n\nA struct for storing free variables that can be used as the variables field of GenericModel or GenericModel. It represents a model that does not support any constraint nor objective function.\n\nExample\n\nThe following model type represents a conic model in geometric form. As opposed to VariablesContainer, FreeVariables does not support constraint bounds so they are bridged into an affine constraint in the MOI.Nonnegatives cone as expected for the geometric conic form.\n\njulia> MOI.Utilities.@product_of_sets(\n Cones,\n MOI.Zeros,\n MOI.Nonnegatives,\n MOI.SecondOrderCone,\n MOI.PositiveSemidefiniteConeTriangle,\n);\n\njulia> const ConicModel{T} = MOI.Utilities.GenericOptimizer{\n T,\n MOI.Utilities.ObjectiveContainer{T},\n MOI.Utilities.FreeVariables,\n MOI.Utilities.MatrixOfConstraints{\n T,\n MOI.Utilities.MutableSparseMatrixCSC{\n T,\n Int,\n MOI.Utilities.OneBasedIndexing,\n },\n Vector{T},\n Cones{T},\n },\n};\n\njulia> model = MOI.instantiate(ConicModel{Float64}, with_bridge_type=Float64);\n\njulia> x = MOI.add_variable(model)\nMathOptInterface.VariableIndex(1)\n\njulia> c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)\n\njulia> MOI.Bridges.is_bridged(model, c)\ntrue\n\njulia> bridge = MOI.Bridges.bridge(model, c)\nMathOptInterface.Bridges.Constraint.VectorizeBridge{Float64, MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives, MathOptInterface.VariableIndex}(MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1), 1.0)\n\njulia> bridge.vector_constraint\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.Bridges.is_bridged(model, bridge.vector_constraint)\nfalse\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.constraints","page":"API Reference","title":".constraints","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.VectorOfConstraints\nUtilities.StructOfConstraints\nUtilities.@struct_of_constraints_by_function_types\nUtilities.@struct_of_constraints_by_set_types\nUtilities.struct_of_constraint_code","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.VectorOfConstraints","page":"API Reference","title":"MathOptInterface.Utilities.VectorOfConstraints","text":"mutable struct VectorOfConstraints{\n F<:MOI.AbstractFunction,\n S<:MOI.AbstractSet,\n} <: MOI.ModelLike\n constraints::CleverDicts.CleverDict{\n MOI.ConstraintIndex{F,S},\n Tuple{F,S},\n typeof(CleverDicts.key_to_index),\n typeof(CleverDicts.index_to_key),\n }\nend\n\nA struct storing F-in-S constraints as a mapping between the constraint indices to the corresponding tuple of function and set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.StructOfConstraints","page":"API Reference","title":"MathOptInterface.Utilities.StructOfConstraints","text":"abstract type StructOfConstraints <: MOI.ModelLike end\n\nA struct storing a subfields other structs storing constraints of different types.\n\nSee Utilities.@struct_of_constraints_by_function_types and Utilities.@struct_of_constraints_by_set_types.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@struct_of_constraints_by_function_types","page":"API Reference","title":"MathOptInterface.Utilities.@struct_of_constraints_by_function_types","text":"Utilities.@struct_of_constraints_by_function_types(name, func_types...)\n\nGiven a vector of n function types (F1, F2,..., Fn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of function type Fi.\n\nThe expression Fi can also be a union in which case any constraint for which the function type is in the union is stored in the field with type Ci.\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@struct_of_constraints_by_set_types","page":"API Reference","title":"MathOptInterface.Utilities.@struct_of_constraints_by_set_types","text":"Utilities.@struct_of_constraints_by_set_types(name, func_types...)\n\nGiven a vector of n set types (S1, S2,..., Sn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of set type Si. The expression Si can also be a union in which case any constraint for which the set type is in the union is stored in the field with type Ci. This can be useful if Ci is a MatrixOfConstraints in order to concatenate the coefficients of constraints of several different set types in the same matrix.\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.struct_of_constraint_code","page":"API Reference","title":"MathOptInterface.Utilities.struct_of_constraint_code","text":"struct_of_constraint_code(struct_name, types, field_types = nothing)\n\nGiven a vector of n Union{SymbolFun,_UnionSymbolFS{SymbolFun}} or Union{SymbolSet,_UnionSymbolFS{SymbolSet}} in types, defines a subtype of StructOfConstraints of name name and which type parameters {T, F1, F2, ..., Fn} if field_types is nothing and a {T} otherwise. It contains n field where the ith field has type Ci if field_types is nothing and type field_types[i] otherwise. If types is vector of Union{SymbolFun,_UnionSymbolFS{SymbolFun}} (resp. Union{SymbolSet,_UnionSymbolFS{SymbolSet}}) then the constraints of that function (resp. set) type are stored in the corresponding field.\n\nThis function is used by the macros @model, @struct_of_constraints_by_function_types and @struct_of_constraints_by_set_types.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Caching-optimizer","page":"API Reference","title":"Caching optimizer","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.CachingOptimizer\nUtilities.attach_optimizer\nUtilities.reset_optimizer\nUtilities.drop_optimizer\nUtilities.state\nUtilities.mode","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.CachingOptimizer","page":"API Reference","title":"MathOptInterface.Utilities.CachingOptimizer","text":"CachingOptimizer\n\nCachingOptimizer is an intermediate layer that stores a cache of the model and links it with an optimizer. It supports incremental model construction and modification even when the optimizer doesn't.\n\nConstructors\n\n CachingOptimizer(cache::MOI.ModelLike, optimizer::AbstractOptimizer)\n\nCreates a CachingOptimizer in AUTOMATIC mode, with the optimizer optimizer.\n\nThe type of the optimizer returned is CachingOptimizer{typeof(optimizer), typeof(cache)} so it does not support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.\n\n CachingOptimizer(cache::MOI.ModelLike, mode::CachingOptimizerMode)\n\nCreates a CachingOptimizer in the NO_OPTIMIZER state and mode mode.\n\nThe type of the optimizer returned is CachingOptimizer{MOI.AbstractOptimizer,typeof(cache)} so it does support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.\n\nAbout the type\n\nStates\n\nA CachingOptimizer may be in one of three possible states (CachingOptimizerState):\n\nNO_OPTIMIZER: The CachingOptimizer does not have any optimizer.\nEMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer. The optimizer is not synchronized with the cached model.\nATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model.\n\nModes\n\nA CachingOptimizer has two modes of operation (CachingOptimizerMode):\n\nMANUAL: The only methods that change the state of the CachingOptimizer are Utilities.reset_optimizer, Utilities.drop_optimizer, and Utilities.attach_optimizer. Attempting to perform an operation in the incorrect state results in an error.\nAUTOMATIC: The CachingOptimizer changes its state when necessary. For example, optimize! will automatically call attach_optimizer (an optimizer must have been previously set). Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.attach_optimizer","page":"API Reference","title":"MathOptInterface.Utilities.attach_optimizer","text":"attach_optimizer(model::CachingOptimizer)\n\nAttaches the optimizer to model, copying all model data into it. Can be called only from the EMPTY_OPTIMIZER state. If the copy succeeds, the CachingOptimizer will be in state ATTACHED_OPTIMIZER after the call, otherwise an error is thrown; see MOI.copy_to for more details on which errors can be thrown.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.reset_optimizer","page":"API Reference","title":"MathOptInterface.Utilities.reset_optimizer","text":"reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)\n\nSets or resets m to have the given empty optimizer optimizer.\n\nCan be called from any state. An assertion error will be thrown if optimizer is not empty.\n\nThe CachingOptimizer m will be in state EMPTY_OPTIMIZER after the call.\n\n\n\n\n\nreset_optimizer(m::CachingOptimizer)\n\nDetaches and empties the current optimizer. Can be called from ATTACHED_OPTIMIZER or EMPTY_OPTIMIZER state. The CachingOptimizer will be in state EMPTY_OPTIMIZER after the call.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.drop_optimizer","page":"API Reference","title":"MathOptInterface.Utilities.drop_optimizer","text":"drop_optimizer(m::CachingOptimizer)\n\nDrops the optimizer, if one is present. Can be called from any state. The CachingOptimizer will be in state NO_OPTIMIZER after the call.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.state","page":"API Reference","title":"MathOptInterface.Utilities.state","text":"state(m::CachingOptimizer)::CachingOptimizerState\n\nReturns the state of the CachingOptimizer m. See Utilities.CachingOptimizer.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.mode","page":"API Reference","title":"MathOptInterface.Utilities.mode","text":"mode(m::CachingOptimizer)::CachingOptimizerMode\n\nReturns the operating mode of the CachingOptimizer m. See Utilities.CachingOptimizer.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Mock-optimizer","page":"API Reference","title":"Mock optimizer","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.MockOptimizer","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MockOptimizer","page":"API Reference","title":"MathOptInterface.Utilities.MockOptimizer","text":"MockOptimizer\n\nMockOptimizer is a fake optimizer especially useful for testing. Its main feature is that it can store the values that should be returned for each attribute.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#Printing","page":"API Reference","title":"Printing","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.latex_formulation","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.latex_formulation","page":"API Reference","title":"MathOptInterface.Utilities.latex_formulation","text":"latex_formulation(model::MOI.ModelLike; kwargs...)\n\nWrap model in a type so that it can be pretty-printed as text/latex in a notebook like IJulia, or in Documenter.\n\nTo render the model, end the cell with latex_formulation(model), or call display(latex_formulation(model)) in to force the display of the model from inside a function.\n\nPossible keyword arguments are:\n\nsimplify_coefficients : Simplify coefficients if possible by omitting them or removing trailing zeros.\ndefault_name : The name given to variables with an empty name.\nprint_types : Print the MOI type of each function and set for clarity.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Copy-utilities","page":"API Reference","title":"Copy utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.default_copy_to\nUtilities.IndexMap\nUtilities.identity_index_map\nUtilities.ModelFilter\nUtilities.loadfromstring!","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.default_copy_to","page":"API Reference","title":"MathOptInterface.Utilities.default_copy_to","text":"default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike)\n\nA default implementation of MOI.copy_to(dest, src) for models that implement the incremental interface, that is, MOI.supports_incremental_interface returns true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.IndexMap","page":"API Reference","title":"MathOptInterface.Utilities.IndexMap","text":"IndexMap()\n\nThe dictionary-like object returned by MOI.copy_to.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.identity_index_map","page":"API Reference","title":"MathOptInterface.Utilities.identity_index_map","text":"identity_index_map(model::MOI.ModelLike)\n\nReturn an IndexMap that maps all variable and constraint indices of model to themselves.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ModelFilter","page":"API Reference","title":"MathOptInterface.Utilities.ModelFilter","text":"ModelFilter(filter::Function, model::MOI.ModelLike)\n\nA layer to filter out various components of model.\n\nThe filter function takes a single argument, which is each element from the list returned by the attributes below. It returns true if the element should be visible in the filtered model and false otherwise.\n\nThe components that are filtered are:\n\nEntire constraint types via:\nMOI.ListOfConstraintTypesPresent\nIndividual constraints via:\nMOI.ListOfConstraintIndices{F,S}\nSpecific attributes via:\nMOI.ListOfModelAttributesSet\nMOI.ListOfConstraintAttributesSet\nMOI.ListOfVariableAttributesSet\n\nwarning: Warning\nThe list of attributes filtered may change in a future release. You should write functions that are generic and not limited to the five types listed above. Thus, you should probably define a fallback filter(::Any) = true.\n\nSee below for examples of how this works.\n\nnote: Note\nThis layer has a limited scope. It is intended by be used in conjunction with MOI.copy_to.\n\nExample: copy model excluding integer constraints\n\nUse the do syntax to provide a single function.\n\nfiltered_src = MOI.Utilities.ModelFilter(src) do item\n return item != (MOI.VariableIndex, MOI.Integer)\nend\nMOI.copy_to(dest, filtered_src)\n\nExample: copy model excluding names\n\nUse type dispatch to simplify the implementation:\n\nmy_filter(::Any) = true # Note the generic fallback\nmy_filter(::MOI.VariableName) = false\nmy_filter(::MOI.ConstraintName) = false\nfiltered_src = MOI.Utilities.ModelFilter(my_filter, src)\nMOI.copy_to(dest, filtered_src)\n\nExample: copy irreducible infeasible subsystem\n\nmy_filter(::Any) = true # Note the generic fallback\nfunction my_filter(ci::MOI.ConstraintIndex)\n status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)\n return status != MOI.NOT_IN_CONFLICT\nend\nfiltered_src = MOI.Utilities.ModelFilter(my_filter, src)\nMOI.copy_to(dest, filtered_src)\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.loadfromstring!","page":"API Reference","title":"MathOptInterface.Utilities.loadfromstring!","text":"loadfromstring!(model, s)\n\nA utility function to aid writing tests.\n\nwarning: Warning\nThis function is not intended for widespread use. It is mainly used as a tool to simplify writing tests in MathOptInterface. Do not use it as an exchange format for storing or transmitting problem instances. Use the FileFormats submodule instead.\n\nExample\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> MOI.Utilities.loadfromstring!(model, \"\"\"\n variables: x, y, z\n constrainedvariable: [a, b, c] in Nonnegatives(3)\n minobjective::Float64: 2x + 3y\n con1: x + y <= 1.0\n con2: [x, y] in Nonnegatives(2)\n x >= 0.0\n \"\"\")\n\nNotes\n\nSpecial labels are:\n\nvariables\nminobjective\nmaxobjectives\n\nEverything else denotes a constraint with a name.\n\nAppend ::T to use an element type of T when parsing the function.\n\nDo not name VariableIndex constraints.\n\nExceptions\n\nx - y does NOT currently parse. Instead, write x + -1.0 * y.\nx^2 does NOT currently parse. Instead, write x * x.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Penalty-relaxation","page":"API Reference","title":"Penalty relaxation","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.PenaltyRelaxation\nUtilities.ScalarPenaltyRelaxation","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.PenaltyRelaxation","page":"API Reference","title":"MathOptInterface.Utilities.PenaltyRelaxation","text":"PenaltyRelaxation(\n penalties = Dict{MOI.ConstraintIndex,Float64}();\n default::Union{Nothing,T} = 1.0,\n)\n\nA problem modifier that, when passed to MOI.modify, destructively modifies the model in-place to create a penalized relaxation of the constraints.\n\nwarning: Warning\nThis is a destructive routine that modifies the model in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.\n\nReformulation\n\nSee Utilities.ScalarPenaltyRelaxation for details of the reformulation.\n\nFor each constraint ci, the penalty passed to Utilities.ScalarPenaltyRelaxation is get(penalties, ci, default). If the value is nothing, because ci does not exist in penalties and default = nothing, then the constraint is skipped.\n\nReturn value\n\nMOI.modify(model, PenaltyRelaxation()) returns a Dict{MOI.ConstraintIndex,MOI.ScalarAffineFunction} that maps each constraint index to the corresponding y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of these functions to compute the violation of each constraint.\n\nRelax a subset of constraints\n\nTo relax a subset of constraints, pass a penalties dictionary and set default = nothing.\n\nSupported constraint types\n\nThe penalty relaxation is currently limited to modifying MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction constraints in the linear sets MOI.LessThan, MOI.GreaterThan, MOI.EqualTo and MOI.Interval.\n\nIt does not include variable bound or integrality constraints, because these cannot be modified in-place.\n\nTo modify variable bounds, rewrite them as linear constraints.\n\nExamples\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(default = 2.0));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> map[c] isa MOI.ScalarAffineFunction{Float64}\ntrue\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 3.0)));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 3.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> map[c] isa MOI.ScalarAffineFunction{Float64}\ntrue\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ScalarPenaltyRelaxation","page":"API Reference","title":"MathOptInterface.Utilities.ScalarPenaltyRelaxation","text":"ScalarPenaltyRelaxation(penalty::T) where {T}\n\nA problem modifier that, when passed to MOI.modify, destructively modifies the constraint in-place to create a penalized relaxation of the constraint.\n\nwarning: Warning\nThis is a destructive routine that modifies the constraint in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.\n\nReformulation\n\nThe penalty relaxation modifies constraints of the form f(x) in S into f(x) + y - z in S, where y z ge 0, and then it introduces a penalty term into the objective of a times (y + z) (if minimizing, else -a), where a is penalty\n\nWhen S is MOI.LessThan or MOI.GreaterThan, we omit y or z respectively as a performance optimization.\n\nReturn value\n\nMOI.modify(model, ci, ScalarPenaltyRelaxation(penalty)) returns y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of this function to compute the violation of the constraint.\n\nExamples\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> f isa MOI.ScalarAffineFunction{Float64}\ntrue\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MatrixOfConstraints","page":"API Reference","title":"MatrixOfConstraints","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.MatrixOfConstraints","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MatrixOfConstraints","page":"API Reference","title":"MathOptInterface.Utilities.MatrixOfConstraints","text":"mutable struct MatrixOfConstraints{T,AT,BT,ST} <: MOI.ModelLike\n coefficients::AT\n constants::BT\n sets::ST\n caches::Vector{Any}\n are_indices_mapped::Vector{BitSet}\n final_touch::Bool\nend\n\nRepresent ScalarAffineFunction and VectorAffinefunction constraints in a matrix form where the linear coefficients of the functions are stored in the coefficients field, the constants of the functions or sets are stored in the constants field. Additional information about the sets are stored in the sets field.\n\nThis model can only be used as the constraints field of a MOI.Utilities.AbstractModel.\n\nWhen the constraints are added, they are stored in the caches field. They are only loaded in the coefficients and constants fields once MOI.Utilities.final_touch is called. For this reason, MatrixOfConstraints should not be used by an incremental interface. Use MOI.copy_to instead.\n\nThe constraints can be added in two different ways:\n\nWith add_constraint, in which case a canonicalized copy of the function is stored in caches.\nWith pass_nonvariable_constraints, in which case the functions and sets are stored themselves in caches without mapping the variable indices. The corresponding index in caches is added in are_indices_mapped. This avoids doing a copy of the function in case the getter of CanonicalConstraintFunction does not make a copy for the source model, for example, this is the case of VectorOfConstraints.\n\nWe illustrate this with an example. Suppose a model is copied from a src::MOI.Utilities.Model to a bridged model with a MatrixOfConstraints. For all the types that are not bridged, the constraints will be copied with pass_nonvariable_constraints. Hence the functions stored in caches are exactly the same as the ones stored in src. This is ok since this is only during the copy_to operation during which src cannot be modified. On the other hand, for the types that are bridged, the functions added may contain duplicates even if the functions did not contain duplicates in src so duplicates are removed with MOI.Utilities.canonical.\n\nInterface\n\nThe .coefficients::AT type must implement:\n\nAT()\nMOI.empty(::AT)!\nMOI.Utilities.add_column\nMOI.Utilities.set_number_of_rows\nMOI.Utilities.allocate_terms\nMOI.Utilities.load_terms\nMOI.Utilities.final_touch\n\nThe .constants::BT type must implement:\n\nBT()\nBase.empty!(::BT)\nBase.resize(::BT)\nMOI.Utilities.load_constants\nMOI.Utilities.function_constants\nMOI.Utilities.set_from_constants\n\nThe .sets::ST type must implement:\n\nST()\nMOI.is_empty(::ST)\nMOI.empty(::ST)\nMOI.dimension(::ST)\nMOI.is_valid(::ST, ::MOI.ConstraintIndex)\nMOI.get(::ST, ::MOI.ListOfConstraintTypesPresent)\nMOI.get(::ST, ::MOI.NumberOfConstraints)\nMOI.get(::ST, ::MOI.ListOfConstraintIndices)\nMOI.Utilities.set_types\nMOI.Utilities.set_index\nMOI.Utilities.add_set\nMOI.Utilities.rows\nMOI.Utilities.final_touch\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.coefficients","page":"API Reference","title":".coefficients","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.add_column\nUtilities.allocate_terms\nUtilities.set_number_of_rows\nUtilities.load_terms\nUtilities.final_touch\nUtilities.extract_function","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.add_column","page":"API Reference","title":"MathOptInterface.Utilities.add_column","text":"add_column(coefficients)::Nothing\n\nTell coefficients to pre-allocate datastructures as needed to store one column.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.allocate_terms","page":"API Reference","title":"MathOptInterface.Utilities.allocate_terms","text":"allocate_terms(coefficients, index_map, func)::Nothing\n\nTell coefficients that the terms of the function func where the variable indices are mapped with index_map will be loaded with load_terms.\n\nThe function func must be canonicalized before calling allocate_terms. See is_canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_number_of_rows","page":"API Reference","title":"MathOptInterface.Utilities.set_number_of_rows","text":"set_number_of_rows(coefficients, n)::Nothing\n\nTell coefficients to pre-allocate datastructures as needed to store n rows.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.load_terms","page":"API Reference","title":"MathOptInterface.Utilities.load_terms","text":"load_terms(coefficients, index_map, func, offset)::Nothing\n\nLoads the terms of func to coefficients, mapping the variable indices with index_map.\n\nThe ith dimension of func is loaded at the (offset + i)th row of coefficients.\n\nThe function must be allocated first with allocate_terms.\n\nThe function func must be canonicalized, see is_canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.final_touch","page":"API Reference","title":"MathOptInterface.Utilities.final_touch","text":"final_touch(coefficients)::Nothing\n\nInforms the coefficients that all functions have been added with load_terms. No more modification is allowed unless MOI.empty! is called.\n\nfinal_touch(sets)::Nothing\n\nInforms the sets that all functions have been added with add_set. No more modification is allowed unless MOI.empty! is called.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.extract_function","page":"API Reference","title":"MathOptInterface.Utilities.extract_function","text":"extract_function(coefficients, row::Integer, constant::T) where {T}\n\nReturn the MOI.ScalarAffineFunction{T} function corresponding to row row in coefficients.\n\nextract_function(\n coefficients,\n rows::UnitRange,\n constants::Vector{T},\n) where{T}\n\nReturn the MOI.VectorAffineFunction{T} function corresponding to rows rows in coefficients.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.MutableSparseMatrixCSC\nUtilities.AbstractIndexing\nUtilities.ZeroBasedIndexing\nUtilities.OneBasedIndexing","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MutableSparseMatrixCSC","page":"API Reference","title":"MathOptInterface.Utilities.MutableSparseMatrixCSC","text":"mutable struct MutableSparseMatrixCSC{Tv,Ti<:Integer,I<:AbstractIndexing}\n indexing::I\n m::Int\n n::Int\n colptr::Vector{Ti}\n rowval::Vector{Ti}\n nzval::Vector{Tv}\n nz_added::Vector{Ti}\nend\n\nMatrix type loading sparse matrices in the Compressed Sparse Column format. The indexing used is indexing, see AbstractIndexing. The other fields have the same meaning than for SparseArrays.SparseMatrixCSC except that the indexing is different unless indexing is OneBasedIndexing. In addition, nz_added is used to cache the number of non-zero terms that have been added to each column due to the incremental nature of load_terms.\n\nThe matrix is loaded in 5 steps:\n\nMOI.empty! is called.\nMOI.Utilities.add_column and MOI.Utilities.allocate_terms are called in any order.\nMOI.Utilities.set_number_of_rows is called.\nMOI.Utilities.load_terms is called for each affine function.\nMOI.Utilities.final_touch is called.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.AbstractIndexing","page":"API Reference","title":"MathOptInterface.Utilities.AbstractIndexing","text":"abstract type AbstractIndexing end\n\nIndexing to be used for storing the row and column indices of MutableSparseMatrixCSC. See ZeroBasedIndexing and OneBasedIndexing.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ZeroBasedIndexing","page":"API Reference","title":"MathOptInterface.Utilities.ZeroBasedIndexing","text":"struct ZeroBasedIndexing <: AbstractIndexing end\n\nZero-based indexing: the ith row or column has index i - 1. This is useful when the vectors of row and column indices need to be communicated to a library using zero-based indexing such as C libraries.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.OneBasedIndexing","page":"API Reference","title":"MathOptInterface.Utilities.OneBasedIndexing","text":"struct ZeroBasedIndexing <: AbstractIndexing end\n\nOne-based indexing: the ith row or column has index i. This enables an allocation-free conversion of MutableSparseMatrixCSC to SparseArrays.SparseMatrixCSC.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.constants","page":"API Reference","title":".constants","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.load_constants\nUtilities.function_constants\nUtilities.set_from_constants\nUtilities.modify_constants","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.load_constants","page":"API Reference","title":"MathOptInterface.Utilities.load_constants","text":"load_constants(constants, offset, func_or_set)::Nothing\n\nThis function loads the constants of func_or_set in constants at an offset of offset. Where offset is the sum of the dimensions of the constraints already loaded. The storage should be preallocated with resize! before calling this function.\n\nThis function should be implemented to be usable as storage of constants for MatrixOfConstraints.\n\nThe constants are loaded in three steps:\n\nBase.empty! is called.\nBase.resize! is called with the sum of the dimensions of all constraints.\nMOI.Utilities.load_constants is called for each function for vector constraint or set for scalar constraint.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.function_constants","page":"API Reference","title":"MathOptInterface.Utilities.function_constants","text":"function_constants(constants, rows)\n\nThis function returns the function constants that were loaded with load_constants at the rows rows.\n\nThis function should be implemented to be usable as storage of constants for MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_from_constants","page":"API Reference","title":"MathOptInterface.Utilities.set_from_constants","text":"set_from_constants(constants, S::Type, rows)::S\n\nThis function returns an instance of the set S for which the constants where loaded with load_constants at the rows rows.\n\nThis function should be implemented to be usable as storage of constants for MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.modify_constants","page":"API Reference","title":"MathOptInterface.Utilities.modify_constants","text":"modify_constants(constants, row::Integer, new_constant::T) where {T}\nmodify_constants(\n constants,\n rows::AbstractVector{<:Integer},\n new_constants::AbstractVector{T},\n) where {T}\n\nModify constants in-place to store new_constant in the row row, or rows rows.\n\nThis function must be implemented to enable MOI.ScalarConstantChange and MOI.VectorConstantChange for MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.Hyperrectangle","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.Hyperrectangle","page":"API Reference","title":"MathOptInterface.Utilities.Hyperrectangle","text":"struct Hyperrectangle{T} <: AbstractVectorBounds\n lower::Vector{T}\n upper::Vector{T}\nend\n\nA struct for the .constants field in MatrixOfConstraints.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#.sets","page":"API Reference","title":".sets","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.set_index\nUtilities.set_types\nUtilities.add_set\nUtilities.rows\nUtilities.num_rows\nUtilities.set_with_dimension","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_index","page":"API Reference","title":"MathOptInterface.Utilities.set_index","text":"set_index(sets, ::Type{S})::Union{Int,Nothing} where {S<:MOI.AbstractSet}\n\nReturn an integer corresponding to the index of the set type in the list given by set_types.\n\nIf S is not part of the list, return nothing.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_types","page":"API Reference","title":"MathOptInterface.Utilities.set_types","text":"set_types(sets)::Vector{Type}\n\nReturn the list of the types of the sets allowed in sets.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.add_set","page":"API Reference","title":"MathOptInterface.Utilities.add_set","text":"add_set(sets, i)::Int64\n\nAdd a scalar set of type index i.\n\nadd_set(sets, i, dim)::Int64\n\nAdd a vector set of type index i and dimension dim.\n\nBoth methods return a unique Int64 of the set that can be used to reference this set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.rows","page":"API Reference","title":"MathOptInterface.Utilities.rows","text":"rows(sets, ci::MOI.ConstraintIndex)::Union{Int,UnitRange{Int}}\n\nReturn the rows in 1:MOI.dimension(sets) corresponding to the set of id ci.value.\n\nFor scalar sets, this returns an Int. For vector sets, this returns an UnitRange{Int}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.num_rows","page":"API Reference","title":"MathOptInterface.Utilities.num_rows","text":"num_rows(sets::OrderedProductOfSets, ::Type{S}) where {S}\n\nReturn the number of rows corresponding to a set of type S. That is, it is the sum of the dimensions of the sets of type S.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_with_dimension","page":"API Reference","title":"MathOptInterface.Utilities.set_with_dimension","text":"set_with_dimension(::Type{S}, dim) where {S<:MOI.AbstractVectorSet}\n\nReturns the instance of S of MOI.dimension dim. This needs to be implemented for sets of type S to be useable with MatrixOfConstraints.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.ProductOfSets\nUtilities.MixOfScalarSets\nUtilities.@mix_of_scalar_sets\nUtilities.OrderedProductOfSets\nUtilities.@product_of_sets","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ProductOfSets","page":"API Reference","title":"MathOptInterface.Utilities.ProductOfSets","text":"abstract type ProductOfSets{T} end\n\nRepresents a cartesian product of sets of given types.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.MixOfScalarSets","page":"API Reference","title":"MathOptInterface.Utilities.MixOfScalarSets","text":"abstract type MixOfScalarSets{T} <: ProductOfSets{T} end\n\nProduct of scalar sets in the order the constraints are added, mixing the constraints of different types.\n\nUse @mix_of_scalar_sets to generate a new subtype.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@mix_of_scalar_sets","page":"API Reference","title":"MathOptInterface.Utilities.@mix_of_scalar_sets","text":"@mix_of_scalar_sets(name, set_types...)\n\nGenerate a new MixOfScalarSets subtype.\n\nExample\n\n@mix_of_scalar_sets(\n MixedIntegerLinearProgramSets,\n MOI.GreaterThan{T},\n MOI.LessThan{T},\n MOI.EqualTo{T},\n MOI.Integer,\n)\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.OrderedProductOfSets","page":"API Reference","title":"MathOptInterface.Utilities.OrderedProductOfSets","text":"abstract type OrderedProductOfSets{T} <: ProductOfSets{T} end\n\nProduct of sets in the order the constraints are added, grouping the constraints of the same types contiguously.\n\nUse @product_of_sets to generate new subtypes.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.@product_of_sets","page":"API Reference","title":"MathOptInterface.Utilities.@product_of_sets","text":"@product_of_sets(name, set_types...)\n\nGenerate a new OrderedProductOfSets subtype.\n\nExample\n\n@product_of_sets(\n LinearOrthants,\n MOI.Zeros,\n MOI.Nonnegatives,\n MOI.Nonpositives,\n MOI.ZeroOne,\n)\n\n\n\n\n\n","category":"macro"},{"location":"submodules/Utilities/reference/#Fallbacks","page":"API Reference","title":"Fallbacks","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.get_fallback","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.get_fallback","page":"API Reference","title":"MathOptInterface.Utilities.get_fallback","text":"get_fallback(model::MOI.ModelLike, ::MOI.ObjectiveValue)\n\nCompute the objective function value using the VariablePrimal results and the ObjectiveFunction value.\n\n\n\n\n\nget_fallback(\n model::MOI.ModelLike,\n ::MOI.DualObjectiveValue,\n ::Type{T},\n)::T where {T}\n\nCompute the dual objective value of type T using the ConstraintDual results and the ConstraintFunction and ConstraintSet values.\n\nNote that the nonlinear part of the model is ignored.\n\n\n\n\n\nget_fallback(\n model::MOI.ModelLike,\n ::MOI.ConstraintPrimal,\n constraint_index::MOI.ConstraintIndex,\n)\n\nCompute the value of the function of the constraint of index constraint_index using the VariablePrimal results and the ConstraintFunction values.\n\n\n\n\n\nget_fallback(\n model::MOI.ModelLike,\n attr::MOI.ConstraintDual,\n ci::MOI.ConstraintIndex{Union{MOI.VariableIndex,MOI.VectorOfVariables}},\n ::Type{T} = Float64,\n) where {T}\n\nCompute the dual of the constraint of index ci using the ConstraintDual of other constraints and the ConstraintFunction values.\n\nThrows an error if some constraints are quadratic or if there is one another MOI.VariableIndex-in-S or MOI.VectorOfVariables-in-S constraint with one of the variables in the function of the constraint ci.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Function-utilities","page":"API Reference","title":"Function utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are available for functions:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.eval_variables\nUtilities.map_indices\nUtilities.substitute_variables\nUtilities.filter_variables\nUtilities.remove_variable\nUtilities.all_coefficients\nUtilities.unsafe_add\nUtilities.isapprox_zero\nUtilities.modify_function\nUtilities.zero_with_output_dimension","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.eval_variables","page":"API Reference","title":"MathOptInterface.Utilities.eval_variables","text":"eval_variables(value_fn::Function, f::MOI.AbstractFunction)\n\nReturns the value of function f if each variable index vi is evaluated as value_fn(vi).\n\nNote that value_fn must return a Number. See substitute_variables for a similar function where value_fn returns an MOI.AbstractScalarFunction.\n\nwarning: Warning\nThe two-argument version of eval_variables is deprecated and may be removed in MOI v2.0.0. Use the three-argument method eval_variables(::Function, ::MOI.ModelLike, ::MOI.AbstractFunction) instead.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.map_indices","page":"API Reference","title":"MathOptInterface.Utilities.map_indices","text":"map_indices(index_map::Function, attr::MOI.AnyAttribute, x::X)::X where {X}\n\nSubstitute any MOI.VariableIndex (resp. MOI.ConstraintIndex) in x by the MOI.VariableIndex (resp. MOI.ConstraintIndex) of the same type given by index_map(x).\n\nWhen to implement this method for new types X\n\nThis function is used by implementations of MOI.copy_to on constraint functions, attribute values and submittable values. If you define a new attribute whose values x::X contain variable or constraint indices, you must also implement this function.\n\n\n\n\n\nmap_indices(\n variable_map::AbstractDict{T,T},\n x::X,\n)::X where {T<:MOI.Index,X}\n\nShortcut for map_indices(vi -> variable_map[vi], x).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.substitute_variables","page":"API Reference","title":"MathOptInterface.Utilities.substitute_variables","text":"substitute_variables(variable_map::Function, x)\n\nSubstitute any MOI.VariableIndex in x by variable_map(x). The variable_map function returns either MOI.VariableIndex or MOI.ScalarAffineFunction, see eval_variables for a similar function where variable_map returns a number.\n\nThis function is used by bridge optimizers on constraint functions, attribute values and submittable values when at least one variable bridge is used hence it needs to be implemented for custom types that are meant to be used as attribute or submittable value.\n\nnote: Note\nWhen implementing a new method, don't use substitute_variables(::Function, because Julia will not specialize on it. Use instead substitute_variables(::F, ...) where {F<:Function}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.filter_variables","page":"API Reference","title":"MathOptInterface.Utilities.filter_variables","text":"filter_variables(keep::Function, f::AbstractFunction)\n\nReturn a new function f with the variable vi such that !keep(vi) removed.\n\nWARNING: Don't define filter_variables(::Function, ...) because Julia will not specialize on this. Define instead filter_variables(::F, ...) where {F<:Function}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.remove_variable","page":"API Reference","title":"MathOptInterface.Utilities.remove_variable","text":"remove_variable(f::AbstractFunction, vi::VariableIndex)\n\nReturn a new function f with the variable vi removed.\n\n\n\n\n\nremove_variable(\n f::MOI.AbstractFunction,\n s::MOI.AbstractSet,\n vi::MOI.VariableIndex,\n)\n\nReturn a tuple (g, t) representing the constraint f-in-s with the variable vi removed. That is, the terms containing the variable vi in the function f are removed and the dimension of the set s is updated if needed (for example, when f is a VectorOfVariables with vi being one of the variables).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.all_coefficients","page":"API Reference","title":"MathOptInterface.Utilities.all_coefficients","text":"all_coefficients(p::Function, f::MOI.AbstractFunction)\n\nDetermine whether predicate p returns true for all coefficients of f, returning false as soon as the first coefficient of f for which p returns false is encountered (short-circuiting). Similar to all.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.unsafe_add","page":"API Reference","title":"MathOptInterface.Utilities.unsafe_add","text":"unsafe_add(t1::MOI.ScalarAffineTerm, t2::MOI.ScalarAffineTerm)\n\nSums the coefficients of t1 and t2 and returns an output MOI.ScalarAffineTerm. It is unsafe because it uses the variable of t1 as the variable of the output without checking that it is equal to that of t2.\n\n\n\n\n\nunsafe_add(t1::MOI.ScalarQuadraticTerm, t2::MOI.ScalarQuadraticTerm)\n\nSums the coefficients of t1 and t2 and returns an output MOI.ScalarQuadraticTerm. It is unsafe because it uses the variable's of t1 as the variable's of the output without checking that they are the same (up to permutation) to those of t2.\n\n\n\n\n\nunsafe_add(t1::MOI.VectorAffineTerm, t2::MOI.VectorAffineTerm)\n\nSums the coefficients of t1 and t2 and returns an output MOI.VectorAffineTerm. It is unsafe because it uses the output_index and variable of t1 as the output_index and variable of the output term without checking that they are equal to those of t2.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.isapprox_zero","page":"API Reference","title":"MathOptInterface.Utilities.isapprox_zero","text":"isapprox_zero(f::MOI.AbstractFunction, tol)\n\nReturn a Bool indicating whether the function f is approximately zero using tol as a tolerance.\n\nImportant note\n\nThis function assumes that f does not contain any duplicate terms, you might want to first call canonical if that is not guaranteed. For instance, given\n\nf = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1, -1], [x, x]), 0)\n\nthen isapprox_zero(f) is false but isapprox_zero(MOIU.canonical(f)) is true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.modify_function","page":"API Reference","title":"MathOptInterface.Utilities.modify_function","text":"modify_function(f::AbstractFunction, change::AbstractFunctionModification)\n\nReturn a copy of the function f, modified according to change.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.zero_with_output_dimension","page":"API Reference","title":"MathOptInterface.Utilities.zero_with_output_dimension","text":"zero_with_output_dimension(::Type{T}, output_dimension::Integer) where {T}\n\nCreate an instance of type T with the output dimension output_dimension.\n\nThis is mostly useful in Bridges, when code needs to be agnostic to the type of vector-valued function that is passed in.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following functions can be used to canonicalize a function:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.is_canonical\nUtilities.canonical\nUtilities.canonicalize!","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.is_canonical","page":"API Reference","title":"MathOptInterface.Utilities.is_canonical","text":"is_canonical(f::Union{ScalarAffineFunction, VectorAffineFunction})\n\nReturns a Bool indicating whether the function is in canonical form. See canonical.\n\n\n\n\n\nis_canonical(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})\n\nReturns a Bool indicating whether the function is in canonical form. See canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.canonical","page":"API Reference","title":"MathOptInterface.Utilities.canonical","text":"canonical(f::MOI.AbstractFunction)\n\nReturns the function in a canonical form, that is,\n\nA term appear only once.\nThe coefficients are nonzero.\nThe terms appear in increasing order of variable where there the order of the variables is the order of their value.\nFor a AbstractVectorFunction, the terms are sorted in ascending order of output index.\n\nThe output of canonical can be assumed to be a copy of f, even for VectorOfVariables.\n\nExamples\n\nIf x (resp. y, z) is VariableIndex(1) (resp. 2, 3). The canonical representation of ScalarAffineFunction([y, x, z, x, z], [2, 1, 3, -2, -3], 5) is ScalarAffineFunction([x, y], [-1, 2], 5).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.canonicalize!","page":"API Reference","title":"MathOptInterface.Utilities.canonicalize!","text":"canonicalize!(f::Union{ScalarAffineFunction, VectorAffineFunction})\n\nConvert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.\n\n\n\n\n\ncanonicalize!(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})\n\nConvert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following functions can be used to manipulate functions with basic algebra:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.scalar_type\nUtilities.scalarize\nUtilities.eachscalar\nUtilities.promote_operation\nUtilities.operate\nUtilities.operate!\nUtilities.operate_output_index!\nUtilities.vectorize","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.scalar_type","page":"API Reference","title":"MathOptInterface.Utilities.scalar_type","text":"scalar_type(F::Type{<:MOI.AbstractVectorFunction})\n\nType of functions obtained by indexing objects obtained by calling eachscalar on functions of type F.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.scalarize","page":"API Reference","title":"MathOptInterface.Utilities.scalarize","text":"scalarize(func::MOI.VectorOfVariables, ignore_constants::Bool = false)\n\nReturns a vector of scalar functions making up the vector function in the form of a Vector{MOI.SingleVariable}.\n\nSee also eachscalar.\n\n\n\n\n\nscalarize(func::MOI.VectorAffineFunction{T}, ignore_constants::Bool = false)\n\nReturns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarAffineFunction{T}}.\n\nSee also eachscalar.\n\n\n\n\n\nscalarize(func::MOI.VectorQuadraticFunction{T}, ignore_constants::Bool = false)\n\nReturns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarQuadraticFunction{T}}.\n\nSee also eachscalar.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.eachscalar","page":"API Reference","title":"MathOptInterface.Utilities.eachscalar","text":"eachscalar(f::MOI.AbstractVectorFunction)\n\nReturns an iterator for the scalar components of the vector function.\n\nSee also scalarize.\n\n\n\n\n\neachscalar(f::MOI.AbstractVector)\n\nReturns an iterator for the scalar components of the vector.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.promote_operation","page":"API Reference","title":"MathOptInterface.Utilities.promote_operation","text":"promote_operation(\n op::Function,\n ::Type{T},\n ArgsTypes::Type{<:Union{T,AbstractVector{T},MOI.AbstractFunction}}...,\n) where {T<:Number}\n\nCompute the return type of the call operate(op, T, args...), where the types of the arguments args are ArgsTypes.\n\nOne assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.\n\nThere are six methods for which we implement Utilities.promote_operation:\n\n+ a. promote_operation(::typeof(+), ::Type{T}, ::Type{F1}, ::Type{F2})\n- a. promote_operation(::typeof(-), ::Type{T}, ::Type{F}) b. promote_operation(::typeof(-), ::Type{T}, ::Type{F1}, ::Type{F2})\n* a. promote_operation(::typeof(*), ::Type{T}, ::Type{T}, ::Type{F}) b. promote_operation(::typeof(*), ::Type{T}, ::Type{F}, ::Type{T}) c. promote_operation(::typeof(*), ::Type{T}, ::Type{F1}, ::Type{F2}) where F1 and F2 are VariableIndex or ScalarAffineFunction d. promote_operation(::typeof(*), ::Type{T}, ::Type{<:Diagonal{T}}, ::Type{F}\n/ a. promote_operation(::typeof(/), ::Type{T}, ::Type{F}, ::Type{T})\nvcat a. promote_operation(::typeof(vcat), ::Type{T}, ::Type{F}...)\nimag a. promote_operation(::typeof(imag), ::Type{T}, ::Type{F}) where F is VariableIndex or VectorOfVariables\n\nIn each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:\n\n::T\n::VariableIndex\n::ScalarAffineFunction{T}\n::ScalarQuadraticFunction{T}\n::ScalarNonlinearFunction\n::AbstractVector{T}\n::VectorOfVariables\n::VectorAffineFunction{T}\n::VectorQuadraticFunction{T}\n::VectorNonlinearFunction\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.operate","page":"API Reference","title":"MathOptInterface.Utilities.operate","text":"operate(\n op::Function,\n ::Type{T},\n args::Union{T,MOI.AbstractFunction}...,\n)::MOI.AbstractFunction where {T<:Number}\n\nReturns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.\n\nNo argument can be modified.\n\nMethods\n\n+ a. operate(::typeof(+), ::Type{T}, ::F1) b. operate(::typeof(+), ::Type{T}, ::F1, ::F2) c. operate(::typeof(+), ::Type{T}, ::F1...)\n- a. operate(::typeof(-), ::Type{T}, ::F) b. operate(::typeof(-), ::Type{T}, ::F1, ::F2)\n* a. operate(::typeof(*), ::Type{T}, ::T, ::F) b. operate(::typeof(*), ::Type{T}, ::F, ::T) c. operate(::typeof(*), ::Type{T}, ::F1, ::F2) where F1 and F2 are VariableIndex or ScalarAffineFunction d. operate(::typeof(*), ::Type{T}, ::Diagonal{T}, ::F)\n/ a. operate(::typeof(/), ::Type{T}, ::F, ::T)\nvcat a. operate(::typeof(vcat), ::Type{T}, ::F...)\nimag a. operate(::typeof(imag), ::Type{T}, ::F) where F is VariableIndex or VectorOfVariables\n\nOne assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.\n\nIn each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:\n\n::T\n::VariableIndex\n::ScalarAffineFunction{T}\n::ScalarQuadraticFunction{T}\n::ScalarNonlinearFunction\n::AbstractVector{T}\n::VectorOfVariables\n::VectorAffineFunction{T}\n::VectorQuadraticFunction{T}\n::VectorNonlinearFunction\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.operate!","page":"API Reference","title":"MathOptInterface.Utilities.operate!","text":"operate!(\n op::Function,\n ::Type{T},\n args::Union{T,MOI.AbstractFunction}...,\n)::MOI.AbstractFunction where {T<:Number}\n\nReturns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.\n\nThe first argument may be modified, in which case the return value is identical to the first argument. For operations which cannot be implemented in-place, this function returns a new object.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.operate_output_index!","page":"API Reference","title":"MathOptInterface.Utilities.operate_output_index!","text":"operate_output_index!(\n op::Union{typeof(+),typeof(-)},\n ::Type{T},\n output_index::Integer,\n f::Union{AbstractVector{T},MOI.AbstractVectorFunction}\n g::Union{T,MOI.AbstractScalarFunction}...\n) where {T<:Number}\n\nReturn an MOI.AbstractVectorFunction in which the scalar function in row output_index is the result of op(f[output_index], g).\n\nThe functions at output index different to output_index are the same as the functions at the same output index in func. The first argument may be modified.\n\nMethods\n\n+ a. operate_output_index!(+, ::Type{T}, ::Int, ::VectorF, ::ScalarF)\n- a. operate_output_index!(-, ::Type{T}, ::Int, ::VectorF, ::ScalarF)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.vectorize","page":"API Reference","title":"MathOptInterface.Utilities.vectorize","text":"vectorize(x::AbstractVector{<:Number})\n\nReturns x.\n\n\n\n\n\nvectorize(x::AbstractVector{MOI.VariableIndex})\n\nReturns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.\n\n\n\n\n\nvectorize(funcs::AbstractVector{MOI.ScalarAffineFunction{T}}) where T\n\nReturns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.\n\n\n\n\n\nvectorize(funcs::AbstractVector{MOI.ScalarQuadraticFunction{T}}) where T\n\nReturns the vector of scalar quadratic functions in the form of a MOI.VectorQuadraticFunction{T}.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Constraint-utilities","page":"API Reference","title":"Constraint utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are available for moving the function constant to the set for scalar constraints:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.shift_constant\nUtilities.supports_shift_constant\nUtilities.normalize_and_add_constraint\nUtilities.normalize_constant","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.shift_constant","page":"API Reference","title":"MathOptInterface.Utilities.shift_constant","text":"shift_constant(set::MOI.AbstractScalarSet, offset)\n\nReturns a new scalar set new_set such that func-in-set is equivalent to func + offset-in-new_set.\n\nOnly define this function if it makes sense to.\n\nUse supports_shift_constant to check if the set supports shifting:\n\nif supports_shift_constant(typeof(old_set))\n new_set = shift_constant(old_set, offset)\n f.constant = 0\n add_constraint(model, f, new_set)\nelse\n add_constraint(model, f, old_set)\nend\n\nSee also supports_shift_constant.\n\nExamples\n\nThe call shift_constant(MOI.Interval(-2, 3), 1) is equal to MOI.Interval(-1, 4).\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.supports_shift_constant","page":"API Reference","title":"MathOptInterface.Utilities.supports_shift_constant","text":"supports_shift_constant(::Type{S}) where {S<:MOI.AbstractSet}\n\nReturn true if shift_constant is defined for set S.\n\nSee also shift_constant.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.normalize_and_add_constraint","page":"API Reference","title":"MathOptInterface.Utilities.normalize_and_add_constraint","text":"normalize_and_add_constraint(\n model::MOI.ModelLike,\n func::MOI.AbstractScalarFunction,\n set::MOI.AbstractScalarSet;\n allow_modify_function::Bool = false,\n)\n\nAdds the scalar constraint obtained by moving the constant term in func to the set in model. If allow_modify_function is true then the function func can be modified.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.normalize_constant","page":"API Reference","title":"MathOptInterface.Utilities.normalize_constant","text":"normalize_constant(\n func::MOI.AbstractScalarFunction,\n set::MOI.AbstractScalarSet;\n allow_modify_function::Bool = false,\n)\n\nReturn the func-in-set constraint in normalized form. That is, if func is MOI.ScalarQuadraticFunction or MOI.ScalarAffineFunction, the constant is moved to the set. If allow_modify_function is true then the function func can be modified.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utility identifies those constraints imposing bounds on a given variable, and returns those bound values:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.get_bounds","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.get_bounds","page":"API Reference","title":"MathOptInterface.Utilities.get_bounds","text":"get_bounds(model::MOI.ModelLike, ::Type{T}, x::MOI.VariableIndex)\n\nReturn a tuple (lb, ub) of type Tuple{T, T}, where lb and ub are lower and upper bounds, respectively, imposed on x in model.\n\n\n\n\n\nget_bounds(\n model::MOI.ModelLike,\n bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},\n f::MOI.ScalarAffineFunction{T},\n) where {T} --> Union{Nothing,NTuple{2,T}}\n\nReturn the lower and upper bound of f as a tuple. If the domain is not bounded, return nothing.\n\n\n\n\n\nget_bounds(\n model::MOI.ModelLike,\n bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},\n x::MOI.VariableIndex,\n) where {T} --> Union{Nothing,NTuple{2,T}}\n\nReturn the lower and upper bound of x as a tuple. If the domain is not bounded, return nothing.\n\nSimilar to get_bounds(::MOI.ModelLike, ::Type{T}, ::MOI.VariableIndex), except that the second argument is a cache which maps variables to their bounds and avoids repeated lookups.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are useful when working with symmetric matrix cones.","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.is_diagonal_vectorized_index\nUtilities.side_dimension_for_vectorized_dimension","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.is_diagonal_vectorized_index","page":"API Reference","title":"MathOptInterface.Utilities.is_diagonal_vectorized_index","text":"is_diagonal_vectorized_index(index::Base.Integer)\n\nReturn whether index is the index of a diagonal element in a MOI.AbstractSymmetricMatrixSetTriangle set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.side_dimension_for_vectorized_dimension","page":"API Reference","title":"MathOptInterface.Utilities.side_dimension_for_vectorized_dimension","text":"side_dimension_for_vectorized_dimension(n::Integer)\n\nReturn the dimension d such that MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(d)) is n.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#Set-utilities","page":"API Reference","title":"Set utilities","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"The following utilities are available for sets:","category":"page"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.AbstractDistance\nUtilities.ProjectionUpperBoundDistance\nUtilities.distance_to_set\nUtilities.set_dot","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.AbstractDistance","page":"API Reference","title":"MathOptInterface.Utilities.AbstractDistance","text":"abstract type AbstractDistance end\n\nAn abstract type used to enable dispatch of Utilities.distance_to_set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.ProjectionUpperBoundDistance","page":"API Reference","title":"MathOptInterface.Utilities.ProjectionUpperBoundDistance","text":"ProjectionUpperBoundDistance() <: AbstractDistance\n\nAn upper bound on the minimum distance between point and the closest feasible point in set.\n\nDefinition of distance\n\nThe minimum distance is computed as:\n\nd(x mathcalK) = min_y in mathcalK x - y \n\nwhere x is point and mathcalK is set. The norm is computed as:\n\nx = sqrtf(x x mathcalK)\n\nwhere f is Utilities.set_dot.\n\nIn the default case, where the set does not have a specialized method for Utilities.set_dot, the norm is equivalent to the Euclidean norm x = sqrtsum x_i^2.\n\nWhy an upper bound?\n\nIn most cases, distance_to_set should return the smallest upper bound, but it may return a larger value if the smallest upper bound is expensive to compute.\n\nFor example, given an epigraph from of a conic set, (t x) f(x) le t, it may be simpler to return delta such that f(x) le t + delta, rather than computing the nearest projection onto the set.\n\nIf the distance is not the smallest upper bound, the docstring of the appropriate distance_to_set method must describe the way that the distance is computed.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.distance_to_set","page":"API Reference","title":"MathOptInterface.Utilities.distance_to_set","text":"distance_to_set(\n [d::AbstractDistance = ProjectionUpperBoundDistance()],]\n point::T,\n set::MOI.AbstractScalarSet,\n) where {T}\n\ndistance_to_set(\n [d::AbstractDistance = ProjectionUpperBoundDistance(),]\n point::AbstractVector{T},\n set::MOI.AbstractVectorSet,\n) where {T}\n\nCompute the distance between point and set using the distance metric d. If point is in the set set, this function must return zero(T).\n\nIf d is omitted, the default distance is Utilities.ProjectionUpperBoundDistance.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RotatedSecondOrderCone)\n\nLet (t, u, y...) = x. Return the 2-norm of the vector d such that in x + d, u is projected to 1 if u <= 0, and t is increased such that x + d belongs to the set.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.ExponentialCone)\n\nLet (u, v, w) = x. If v > 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.\n\nIf v <= 0 return the 2-norm of the vector d such that x + d = (u, 1, z) where z satisfies the constraints.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualExponentialCone)\n\nLet (u, v, w) = x. If u < 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.\n\nIf u >= 0 return the 2-norm of the vector d such that x + d = (u, -1, z) where z satisfies the constraints.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.GeometricMeanCone)\n\nLet (t, y...) = x. If all y are non-negative, return the epigraph distance d such that (t + d, y...) belongs to the set.\n\nIf any y are strictly negative, return the 2-norm of the vector d that projects negative y elements to 0 and t to ℝ₋.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.PowerCone)\n\nLet (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.\n\nIf a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualPowerCone)\n\nLet (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.\n\nIf a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormOneCone)\n\nLet (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormInfinityCone)\n\nLet (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RelativeEntropyCone)\n\nLet (u, v..., w...) = x. If v and w are strictly positive, return the epigraph distance required to increase u such that the constraint is satisfied.\n\nIf any elements in v or w are non-positive, return the 2-norm of the vector d such that in the vector x + d: any non-positive elements in v and w are projected to 1, and u is projected such that the epigraph constraint holds.\n\n\n\n\n\ndistance_to_set(::ProjectionUpperBoundDistance, x, set::MOI.NormCone)\n\nLet (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.set_dot","page":"API Reference","title":"MathOptInterface.Utilities.set_dot","text":"set_dot(x::AbstractVector, y::AbstractVector, set::AbstractVectorSet)\n\nReturn the scalar product between a vector x of the set set and a vector y of the dual of the set s.\n\n\n\n\n\nset_dot(x, y, set::AbstractScalarSet)\n\nReturn the scalar product between a number x of the set set and a number y of the dual of the set s.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#DoubleDicts","page":"API Reference","title":"DoubleDicts","text":"","category":"section"},{"location":"submodules/Utilities/reference/","page":"API Reference","title":"API Reference","text":"Utilities.DoubleDicts.DoubleDict\nUtilities.DoubleDicts.DoubleDictInner\nUtilities.DoubleDicts.IndexDoubleDict\nUtilities.DoubleDicts.IndexDoubleDictInner\nUtilities.DoubleDicts.outer_keys\nUtilities.DoubleDicts.nonempty_outer_keys","category":"page"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.DoubleDict","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.DoubleDict","text":"DoubleDict{V}\n\nAn optimized dictionary to map MOI.ConstraintIndex to values of type V.\n\nWorks as a AbstractDict{MOI.ConstraintIndex,V} with minimal differences.\n\nIf V is also a MOI.ConstraintIndex, use IndexDoubleDict.\n\nNote that MOI.ConstraintIndex is not a concrete type, opposed to MOI.ConstraintIndex{MOI.VariableIndex, MOI.Integers}, which is a concrete type.\n\nWhen looping through multiple keys of the same Function-in-Set type, use\n\ninner = dict[F, S]\n\nto return a type-stable DoubleDictInner.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.DoubleDictInner","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.DoubleDictInner","text":"DoubleDictInner{F,S,V}\n\nA type stable inner dictionary of DoubleDict.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.IndexDoubleDict","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.IndexDoubleDict","text":"IndexDoubleDict\n\nA specialized version of [DoubleDict] in which the values are of type MOI.ConstraintIndex\n\nWhen looping through multiple keys of the same Function-in-Set type, use\n\ninner = dict[F, S]\n\nto return a type-stable IndexDoubleDictInner.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.IndexDoubleDictInner","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.IndexDoubleDictInner","text":"IndexDoubleDictInner{F,S}\n\nA type stable inner dictionary of IndexDoubleDict.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.outer_keys","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.outer_keys","text":"outer_keys(d::AbstractDoubleDict)\n\nReturn an iterator over the outer keys of the AbstractDoubleDict d. Each outer key is a Tuple{Type,Type} so that a double loop can be easily used:\n\nfor (F, S) in DoubleDicts.outer_keys(dict)\n for (k, v) in dict[F, S]\n # ...\n end\nend\n\nFor performance, it is recommended that the inner loop lies in a separate function to guarantee type-stability. Some outer keys (F, S) might lead to an empty dict[F, S]. If you want only nonempty dict[F, S], use nonempty_outer_keys.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Utilities/reference/#MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keys","page":"API Reference","title":"MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keys","text":"nonempty_outer_keys(d::AbstractDoubleDict)\n\nReturn a vector of outer keys of the AbstractDoubleDict d.\n\nOnly outer keys that have a nonempty set of inner keys will be returned.\n\nEach outer key is a Tuple{Type,Type} so that a double loop can be easily used\n\nfor (F, S) in DoubleDicts.nonempty_outer_keys(dict)\n for (k, v) in dict[F, S]\n # ...\n end\nend\nFor performance, it is recommended that the inner loop lies in a separate\nfunction to guarantee type-stability.\n\nIf you want an iterator of all current outer keys, use [`outer_keys`](@ref).\n\n\n\n\n\n","category":"function"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"background/infeasibility_certificates/#Infeasibility-certificates","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"When given a conic problem that is infeasible or unbounded, some solvers can produce a certificate of infeasibility. This page explains what a certificate of infeasibility is, and the related conventions that MathOptInterface adopts.","category":"page"},{"location":"background/infeasibility_certificates/#Conic-duality","page":"Infeasibility certificates","title":"Conic duality","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"MathOptInterface uses conic duality to define infeasibility certificates. A full explanation is given in the section Duality, but here is a brief overview.","category":"page"},{"location":"background/infeasibility_certificates/#Minimization-problems","page":"Infeasibility certificates","title":"Minimization problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"For a minimization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n min_x in mathbbR^n a_0^top x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and the dual is a maximization problem in standard conic form:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n max_y_1 ldots y_m -sum_i=1^m b_i^top y_i + b_0\n\n textst a_0 - sum_i=1^m A_i^top y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"where each mathcalC_i is a closed convex cone and mathcalC_i^* is its dual cone.","category":"page"},{"location":"background/infeasibility_certificates/#Maximization-problems","page":"Infeasibility certificates","title":"Maximization problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"For a maximization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n max_x in mathbbR^n a_0^top x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and the dual is a minimization problem in standard conic form:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n min_y_1 ldots y_m sum_i=1^m b_i^top y_i + b_0\n\n textst a_0 + sum_i=1^m A_i^top y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/#Unbounded-problems","page":"Infeasibility certificates","title":"Unbounded problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A problem is unbounded if and only if:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"there exists a feasible primal solution\nthe dual is infeasible.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A feasible primal solution—if one exists—can be obtained by setting ObjectiveSense to FEASIBILITY_SENSE before optimizing. Therefore, most solvers stop after they prove the dual is infeasible via a certificate of dual infeasibility, but before they have found a feasible primal solution. This is also the reason that MathOptInterface defines the DUAL_INFEASIBLE status instead of UNBOUNDED.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A certificate of dual infeasibility is an improving ray of the primal problem. That is, there exists some vector d such that for all eta 0:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A_i (x + eta d) + b_i in mathcalC_i i = 1 ldots m","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and (for minimization problems):","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"a_0^top (x + eta d) + b_0 a_0^top x + b_0","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"for any feasible point x. The latter simplifies to a_0^top d 0. For maximization problems, the inequality is reversed, so that a_0^top d 0.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"If the solver has found a certificate of dual infeasibility:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"TerminationStatus must be DUAL_INFEASIBLE\nPrimalStatus must be INFEASIBILITY_CERTIFICATE\nVariablePrimal must be the corresponding value of d\nConstraintPrimal must be the corresponding value of A_i d\nObjectiveValue must be the value a_0^top d. Note that this is the value of the objective function at d, ignoring the constant b_0.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"note: Note\nThe choice of whether to scale the ray d to have magnitude 1 is left to the solver.","category":"page"},{"location":"background/infeasibility_certificates/#Infeasible-problems","page":"Infeasibility certificates","title":"Infeasible problems","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"A certificate of primal infeasibility is an improving ray of the dual problem. However, because infeasibility is independent of the objective function, we first homogenize the primal problem by removing its objective.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"For a minimization problem, a dual improving ray is some vector d such that for all eta 0:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\n-sum_i=1^m A_i^top (y_i + eta d_i) = 0 \n(y_i + eta d_i) in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"and:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"-sum_i=1^m b_i^top (y_i + eta d_i) -sum_i=1^m b_i^top y_i","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"for any feasible dual solution y. The latter simplifies to -sum_i=1^m b_i^top d_i 0. For a maximization problem, the inequality is sum_i=1^m b_i^top d_i 0. (Note that these are the same inequality, modulo a - sign.)","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"If the solver has found a certificate of primal infeasibility:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"TerminationStatus must be INFEASIBLE\nDualStatus must be INFEASIBILITY_CERTIFICATE\nConstraintDual must be the corresponding value of d\nDualObjectiveValue must be the value -sum_i=1^m b_i^top d_i for minimization problems and sum_i=1^m b_i^top d_i for maximization problems.","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"note: Note\nThe choice of whether to scale the ray d to have magnitude 1 is left to the solver.","category":"page"},{"location":"background/infeasibility_certificates/#Infeasibility-certificates-of-variable-bounds","page":"Infeasibility certificates","title":"Infeasibility certificates of variable bounds","text":"","category":"section"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"Many linear solvers (for example, Gurobi) do not provide explicit access to the primal infeasibility certificate of a variable bound. However, given a set of linear constraints:","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"beginalign\nl_A le A x le u_A \nl_x le x le u_x\nendalign","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"the primal certificate of the variable bounds can be computed using the primal certificate associated with the affine constraints, d. (Note that d will have one element for each row of the A matrix, and that some or all of the elements in the vectors l_A and u_A may be pm infty. If both l_A and u_A are finite for some row, the corresponding element in `d must be 0.)","category":"page"},{"location":"background/infeasibility_certificates/","page":"Infeasibility certificates","title":"Infeasibility certificates","text":"Given d, compute bard = d^top A. If the bound is finite, a certificate for the lower variable bound of x_i is maxbard_i 0, and a certificate for the upper variable bound is minbard_i 0.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/modification/#Problem-modification","page":"Problem modification","title":"Problem modification","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"In addition to adding and deleting constraints and variables, MathOptInterface supports modifying, in-place, coefficients in the constraints and the objective function of a model.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"These modifications can be grouped into two categories:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"modifications which replace the set of function of a constraint with a new set or function\nmodifications which change, in-place, a component of a function","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"warning: Warning\nSome ModelLike objects do not support problem modification.","category":"page"},{"location":"manual/modification/#Modify-the-set-of-a-constraint","page":"Problem modification","title":"Modify the set of a constraint","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use set and ConstraintSet to modify the set of a constraint by replacing it with a new instance of the same type.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.set(model, MOI.ConstraintSet(), c, MOI.EqualTo(2.0));\n\njulia> MOI.get(model, MOI.ConstraintSet(), c) == MOI.EqualTo(2.0)\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"However, the following will fail as the new set is of a different type to the original set:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan(2.0))\nERROR: [...]","category":"page"},{"location":"manual/modification/#Special-cases:-set-transforms","page":"Problem modification","title":"Special cases: set transforms","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"If our constraint is an affine inequality, then this corresponds to modifying the right-hand side of a constraint in linear programming.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"In some special cases, solvers may support efficiently changing the set of a constraint (for example, from LessThan to GreaterThan). For these cases, MathOptInterface provides the transform method.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"The transform function returns a new constraint index, and the old constraint index (that is, c) is no longer valid.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.LessThan(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}(1)\n\njulia> new_c = MOI.transform(model, c, MOI.GreaterThan(2.0));\n\njulia> MOI.is_valid(model, c)\nfalse\n\njulia> MOI.is_valid(model, new_c)\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"note: Note\ntransform cannot be called with a set of the same type. Use set instead.","category":"page"},{"location":"manual/modification/#Modify-the-function-of-a-constraint","page":"Problem modification","title":"Modify the function of a constraint","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use set and ConstraintFunction to modify the function of a constraint by replacing it with a new instance of the same type.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 1.0);\n\njulia> MOI.set(model, MOI.ConstraintFunction(), c, new_f);\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"However, the following will fail as the new function is of a different type to the original function:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> MOI.set(model, MOI.ConstraintFunction(), c, x)\nERROR: [...]","category":"page"},{"location":"manual/modification/#Modify-constant-term-in-a-scalar-function","page":"Problem modification","title":"Modify constant term in a scalar function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and ScalarConstantChange to modify the constant term in a ScalarAffineFunction or ScalarQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.modify(model, c, MOI.ScalarConstantChange(1.0));\n\njulia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 1.0);\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"ScalarConstantChange can also be used to modify the objective function by passing an instance of ObjectiveFunction:","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> MOI.set(\n model,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n new_f,\n );\n\njulia> MOI.modify(\n model,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n MOI.ScalarConstantChange(-1.0)\n );\n\njulia> MOI.get(\n model,\n MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),\n ) ≈ MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], -1.0)\ntrue","category":"page"},{"location":"manual/modification/#Modify-constant-terms-in-a-vector-function","page":"Problem modification","title":"Modify constant terms in a vector function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and VectorConstantChange to modify the constant vector in a VectorAffineFunction or VectorQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.VectorAffineFunction([\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),\n ],\n [0.0, 0.0],\n ),\n MOI.Nonnegatives(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.modify(model, c, MOI.VectorConstantChange([3.0, 4.0]));\n\njulia> new_f = MOI.VectorAffineFunction(\n [\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),\n ],\n [3.0, 4.0],\n );\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/#Modify-affine-coefficients-in-a-scalar-function","page":"Problem modification","title":"Modify affine coefficients in a scalar function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and ScalarCoefficientChange to modify the affine coefficient of a ScalarAffineFunction or ScalarQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.modify(model, c, MOI.ScalarCoefficientChange(x, 2.0));\n\njulia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 0.0);\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"ScalarCoefficientChange can also be used to modify the objective function by passing an instance of ObjectiveFunction.","category":"page"},{"location":"manual/modification/#Modify-quadratic-coefficients-in-a-scalar-function","page":"Problem modification","title":"Modify quadratic coefficients in a scalar function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and ScalarQuadraticCoefficientChange to modify the quadratic coefficient of a ScalarQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variables(model, 2);\n\njulia> c = MOI.add_constraint(\n model,\n 1.0 * x[1] * x[1] + 2.0 * x[1] * x[2],\n MOI.EqualTo(1.0),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadraticFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)\n\njulia> MOI.modify(\n model,\n c,\n MOI.ScalarQuadraticCoefficientChange(x[1], x[1], 3.0),\n );\n\njulia> MOI.modify(\n model,\n c,\n MOI.ScalarQuadraticCoefficientChange(x[1], x[2], 4.0),\n );\n\njulia> new_f = 1.5 * x[1] * x[1] + 4.0 * x[1] * x[2];\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"ScalarQuadraticCoefficientChange can also be used to modify the objective function by passing an instance of ObjectiveFunction.","category":"page"},{"location":"manual/modification/#Modify-affine-coefficients-in-a-vector-function","page":"Problem modification","title":"Modify affine coefficients in a vector function","text":"","category":"section"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"Use modify and MultirowChange to modify a vector of affine coefficients in a VectorAffineFunction or a VectorQuadraticFunction.","category":"page"},{"location":"manual/modification/","page":"Problem modification","title":"Problem modification","text":"julia> c = MOI.add_constraint(\n model,\n MOI.VectorAffineFunction([\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),\n ],\n [0.0, 0.0],\n ),\n MOI.Nonnegatives(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.modify(model, c, MOI.MultirowChange(x, [(1, 3.0), (2, 4.0)]));\n\njulia> new_f = MOI.VectorAffineFunction(\n [\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(4.0, x)),\n ],\n [0.0, 0.0],\n );\n\njulia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f\ntrue","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/variables/#Variables","page":"Variables","title":"Variables","text":"","category":"section"},{"location":"manual/variables/#Add-a-variable","page":"Variables","title":"Add a variable","text":"","category":"section"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Use add_variable to add a single variable.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"add_variable returns a VariableIndex type, which is used to refer to the added variable in other calls.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Check if a VariableIndex is valid using is_valid.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> MOI.is_valid(model, x)\ntrue","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Use add_variables to add a number of variables.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> y = MOI.add_variables(model, 2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"warning: Warning\nThe integer does not necessarily correspond to the column inside an optimizer.","category":"page"},{"location":"manual/variables/#Delete-a-variable","page":"Variables","title":"Delete a variable","text":"","category":"section"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Delete a variable using delete.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> MOI.delete(model, x)\n\njulia> MOI.is_valid(model, x)\nfalse","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"warning: Warning\nNot all ModelLike models support deleting variables. A DeleteNotAllowed error is thrown if this is not supported.","category":"page"},{"location":"manual/variables/#Variable-attributes","page":"Variables","title":"Variable attributes","text":"","category":"section"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"The following attributes are available for variables:","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"VariableName\nVariablePrimalStart\nVariablePrimal","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"Get and set these attributes using get and set.","category":"page"},{"location":"manual/variables/","page":"Variables","title":"Variables","text":"julia> MOI.set(model, MOI.VariableName(), x, \"var_x\")\n\njulia> MOI.get(model, MOI.VariableName(), x)\n\"var_x\"","category":"page"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/FileFormats/reference/#File-Formats","page":"API Reference","title":"File Formats","text":"","category":"section"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"Functions to help read and write MOI models to/from various file formats. See The FileFormats submodule for more details.","category":"page"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"FileFormats.Model\nFileFormats.FileFormat\nFileFormats.CBF.Model\nFileFormats.LP.Model\nFileFormats.MOF.Model\nFileFormats.MPS.Model\nFileFormats.NL.Model\nFileFormats.SDPA.Model","category":"page"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.Model","page":"API Reference","title":"MathOptInterface.FileFormats.Model","text":"Model(\n ;\n format::FileFormat = FORMAT_AUTOMATIC,\n filename::Union{Nothing, String} = nothing,\n kwargs...\n)\n\nReturn model corresponding to the FileFormat format, or, if format == FORMAT_AUTOMATIC, guess the format from filename.\n\nThe filename argument is only needed if format == FORMAT_AUTOMATIC.\n\nkwargs are passed to the underlying model constructor.\n\n\n\n\n\n","category":"function"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.FileFormat","page":"API Reference","title":"MathOptInterface.FileFormats.FileFormat","text":"FileFormat\n\nList of accepted export formats.\n\nFORMAT_AUTOMATIC: try to detect the file format based on the file name\nFORMAT_CBF: the Conic Benchmark format\nFORMAT_LP: the LP file format\nFORMAT_MOF: the MathOptFormat file format\nFORMAT_MPS: the MPS file format\nFORMAT_NL: the AMPL .nl file format\nFORMAT_REW: the .rew file format, which is MPS with generic names\nFORMAT_SDPA: the SemiDefinite Programming Algorithm format\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.CBF.Model","page":"API Reference","title":"MathOptInterface.FileFormats.CBF.Model","text":"Model()\n\nCreate an empty instance of FileFormats.CBF.Model.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.LP.Model","page":"API Reference","title":"MathOptInterface.FileFormats.LP.Model","text":"Model(; kwargs...)\n\nCreate an empty instance of FileFormats.LP.Model.\n\nKeyword arguments are:\n\nmaximum_length::Int=255: the maximum length for the name of a variable. lp_solve 5.0 allows only 16 characters, while CPLEX 12.5+ allow 255.\nwarn::Bool=false: print a warning when variables or constraints are renamed.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.MOF.Model","page":"API Reference","title":"MathOptInterface.FileFormats.MOF.Model","text":"Model(; kwargs...)\n\nCreate an empty instance of FileFormats.MOF.Model.\n\nKeyword arguments are:\n\nprint_compact::Bool=false: print the JSON file in a compact format without spaces or newlines.\nwarn::Bool=false: print a warning when variables or constraints are renamed\ndifferentiation_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation = MOI.Nonlinear.SparseReverseMode(): automatic differentiation backend to use when reading models with nonlinear constraints and objectives.\nuse_nlp_block::Bool=true: if true parse \"ScalarNonlinearFunction\" into an MOI.NLPBlock. If false, \"ScalarNonlinearFunction\" are parsed as MOI.ScalarNonlinearFunction functions.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.MPS.Model","page":"API Reference","title":"MathOptInterface.FileFormats.MPS.Model","text":"Model(; kwargs...)\n\nCreate an empty instance of FileFormats.MPS.Model.\n\nKeyword arguments are:\n\nwarn::Bool=false: print a warning when variables or constraints are renamed.\nprint_objsense::Bool=false: print the OBJSENSE section when writing\ngeneric_names::Bool=false: strip all names in the model and replace them with the generic names C$i and R$i for the i'th column and row respectively.\nquadratic_format::QuadraticFormat = kQuadraticFormatGurobi: specify the solver-specific extension used when writing the quadratic components of the model. Options are kQuadraticFormatGurobi, kQuadraticFormatCPLEX, and kQuadraticFormatMosek.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.NL.Model","page":"API Reference","title":"MathOptInterface.FileFormats.NL.Model","text":"Model(; use_nlp_block::Bool = true)\n\nCreate a new Optimizer object.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.SDPA.Model","page":"API Reference","title":"MathOptInterface.FileFormats.SDPA.Model","text":"Model(; number_type::Type = Float64)\n\nCreate an empty instance of FileFormats.SDPA.Model{number_type}.\n\nIt is important to be aware that the SDPA file format is interpreted in geometric form and not standard conic form. The standard conic form and geometric conic form are two dual standard forms for semidefinite programs (SDPs). The geometric conic form of an SDP is as follows:\n\nbeginalign\n min_y in mathbbR^m b^T y\n\n textst sum_i=1^m A_i y_i - C in mathbbK\nendalign\n\nwhere mathcalK is a cartesian product of nonnegative orthant and positive semidefinite matrices that align with a block diagonal structure shared with the matrices A_i and C.\n\nIn other words, the geometric conic form contains free variables and affine constraints in either the nonnegative orthant or the positive semidefinite cone. That is, in the MathOptInterface's terminology, MOI.VectorAffineFunction-in-MOI.Nonnegatives and MOI.VectorAffineFunction-in-MOI.PositiveSemidefiniteConeTriangle constraints.\n\nThe corresponding standard conic form of the dual SDP is as follows:\n\nbeginalign\n max_X in mathbbK texttr(CX)\n\n textst texttr(A_iX) = b_i i = 1 ldots m\nendalign\n\nIn other words, the standard conic form contains nonnegative and positive semidefinite variables with equality constraints. That is, in the MathOptInterface's terminology, MOI.VectorOfVariables-in-MOI.Nonnegatives, MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle and MOI.ScalarAffineFunction-in-MOI.EqualTo constraints.\n\nIf a model is in standard conic form, use Dualization.jl to transform it into the geometric conic form before writting it. Otherwise, the nonnegative (resp. positive semidefinite) variables will be bridged into free variables with affine constraints constraining them to belong to the nonnegative orthant (resp. positive semidefinite cone) by the MOI.Bridges.Constraint.VectorFunctionizeBridge. Moreover, equality constraints will be bridged into pairs of affine constraints in the nonnegative orthant by the MOI.Bridges.Constraint.SplitIntervalBridge and then the MOI.Bridges.Constraint.VectorizeBridge.\n\nIf a solver is in standard conic form, use Dualization.jl to transform the model read into standard conic form before copying it to the solver. Otherwise, the free variables will be bridged into pairs of variables in the nonnegative orthant by the MOI.Bridges.Variable.FreeBridge and affine constraints will be bridged into equality constraints by creating a slack variable by the MOI.Bridges.Constraint.VectorSlackBridge.\n\n\n\n\n\n","category":"type"},{"location":"submodules/FileFormats/reference/#Other-helpers","page":"API Reference","title":"Other helpers","text":"","category":"section"},{"location":"submodules/FileFormats/reference/","page":"API Reference","title":"API Reference","text":"FileFormats.NL.SolFileResults","category":"page"},{"location":"submodules/FileFormats/reference/#MathOptInterface.FileFormats.NL.SolFileResults","page":"API Reference","title":"MathOptInterface.FileFormats.NL.SolFileResults","text":"SolFileResults(filename::String, model::Model)\n\nParse the .sol file filename created by solving model and return a SolFileResults struct.\n\nThe returned struct supports the MOI.get API for querying result attributes such as MOI.TerminationStatus, MOI.VariablePrimal, and MOI.ConstraintDual.\n\n\n\n\n\nSolFileResults(\n raw_status::String,\n termination_status::MOI.TerminationStatusCode,\n)\n\nReturn a SolFileResults struct with MOI.RawStatusString set to raw_status, MOI.TerminationStatus set to termination_status, and MOI.PrimalStatus and MOI.DualStatus set to NO_SOLUTION.\n\nAll other attributes are un-set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Benchmarks/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Benchmarks/reference/#Benchmarks","page":"API Reference","title":"Benchmarks","text":"","category":"section"},{"location":"submodules/Benchmarks/reference/","page":"API Reference","title":"API Reference","text":"Functions to help benchmark the performance of solver wrappers. See The Benchmarks submodule for more details.","category":"page"},{"location":"submodules/Benchmarks/reference/","page":"API Reference","title":"API Reference","text":"Benchmarks.suite\nBenchmarks.create_baseline\nBenchmarks.compare_against_baseline","category":"page"},{"location":"submodules/Benchmarks/reference/#MathOptInterface.Benchmarks.suite","page":"API Reference","title":"MathOptInterface.Benchmarks.suite","text":"suite(\n new_model::Function;\n exclude::Vector{Regex} = Regex[]\n)\n\nCreate a suite of benchmarks. new_model should be a function that takes no arguments, and returns a new instance of the optimizer you wish to benchmark.\n\nUse exclude to exclude a subset of benchmarks.\n\nExamples\n\nsuite() do\n GLPK.Optimizer()\nend\nsuite(exclude = [r\"delete\"]) do\n Gurobi.Optimizer(OutputFlag=0)\nend\n\n\n\n\n\n","category":"function"},{"location":"submodules/Benchmarks/reference/#MathOptInterface.Benchmarks.create_baseline","page":"API Reference","title":"MathOptInterface.Benchmarks.create_baseline","text":"create_baseline(suite, name::String; directory::String = \"\"; kwargs...)\n\nRun all benchmarks in suite and save to files called name in directory.\n\nExtra kwargs are based to BenchmarkTools.run.\n\nExamples\n\nmy_suite = suite(() -> GLPK.Optimizer())\ncreate_baseline(my_suite, \"glpk_master\"; directory = \"/tmp\", verbose = true)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Benchmarks/reference/#MathOptInterface.Benchmarks.compare_against_baseline","page":"API Reference","title":"MathOptInterface.Benchmarks.compare_against_baseline","text":"compare_against_baseline(\n suite, name::String; directory::String = \"\",\n report_filename::String = \"report.txt\"\n)\n\nRun all benchmarks in suite and compare against files called name in directory that were created by a call to create_baseline.\n\nA report summarizing the comparison is written to report_filename in directory.\n\nExtra kwargs are based to BenchmarkTools.run.\n\nExamples\n\nmy_suite = suite(() -> GLPK.Optimizer())\ncompare_against_baseline(\n my_suite, \"glpk_master\"; directory = \"/tmp\", verbose = true\n)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Test/overview/#test_module","page":"Overview","title":"The Test submodule","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"The Test submodule provides tools to help solvers implement unit tests in order to ensure they implement the MathOptInterface API correctly, and to check for solver-correctness.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"We use a centralized repository of tests, so that if we find a bug in one solver, instead of adding a test to that particular repository, we add it here so that all solvers can benefit.","category":"page"},{"location":"submodules/Test/overview/#How-to-test-a-solver","page":"Overview","title":"How to test a solver","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"The skeleton below can be used for the wrapper test file of a solver named FooBar.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"# ============================ /test/MOI_wrapper.jl ============================\nmodule TestFooBar\n\nimport FooBar\nusing Test\n\nimport MathOptInterface as MOI\n\nconst OPTIMIZER = MOI.instantiate(\n MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),\n)\n\nconst BRIDGED = MOI.instantiate(\n MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),\n with_bridge_type = Float64,\n)\n\n# See the docstring of MOI.Test.Config for other arguments.\nconst CONFIG = MOI.Test.Config(\n # Modify tolerances as necessary.\n atol = 1e-6,\n rtol = 1e-6,\n # Use MOI.LOCALLY_SOLVED for local solvers.\n optimal_status = MOI.OPTIMAL,\n # Pass attributes or MOI functions to `exclude` to skip tests that\n # rely on this functionality.\n exclude = Any[MOI.VariableName, MOI.delete],\n)\n\n\"\"\"\n runtests()\n\nThis function runs all functions in the this Module starting with `test_`.\n\"\"\"\nfunction runtests()\n for name in names(@__MODULE__; all = true)\n if startswith(\"$(name)\", \"test_\")\n @testset \"$(name)\" begin\n getfield(@__MODULE__, name)()\n end\n end\n end\nend\n\n\"\"\"\n test_runtests()\n\nThis function runs all the tests in MathOptInterface.Test.\n\nPass arguments to `exclude` to skip tests for functionality that is not\nimplemented or that your solver doesn't support.\n\"\"\"\nfunction test_runtests()\n MOI.Test.runtests(\n BRIDGED,\n CONFIG,\n exclude = [\n \"test_attribute_NumberOfThreads\",\n \"test_quadratic_\",\n ],\n # This argument is useful to prevent tests from failing on future\n # releases of MOI that add new tests. Don't let this number get too far\n # behind the current MOI release though. You should periodically check\n # for new tests to fix bugs and implement new features.\n exclude_tests_after = v\"0.10.5\",\n )\n return\nend\n\n\"\"\"\n test_SolverName()\n\nYou can also write new tests for solver-specific functionality. Write each new\ntest as a function with a name beginning with `test_`.\n\"\"\"\nfunction test_SolverName()\n @test MOI.get(FooBar.Optimizer(), MOI.SolverName()) == \"FooBar\"\n return\nend\n\nend # module TestFooBar\n\n# This line at tne end of the file runs all the tests!\nTestFooBar.runtests()","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Then modify your runtests.jl file to include the MOI_wrapper.jl file:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"# ============================ /test/runtests.jl ============================\n\nusing Test\n\n@testset \"MOI\" begin\n include(\"test/MOI_wrapper.jl\")\nend","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"info: Info\nThe optimizer BRIDGED constructed with instantiate automatically bridges constraints that are not supported by OPTIMIZER using the bridges listed in Bridges. It is recommended for an implementation of MOI to only support constraints that are natively supported by the solver and let bridges transform the constraint to the appropriate form. For this reason it is expected that tests may not pass if OPTIMIZER is used instead of BRIDGED.","category":"page"},{"location":"submodules/Test/overview/#How-to-debug-a-failing-test","page":"Overview","title":"How to debug a failing test","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"When writing a solver, it's likely that you will initially fail many tests. Some failures will be bugs, but other failures you may choose to exclude.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"There are two ways to exclude tests:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Exclude tests whose names contain a string using:\nMOI.Test.runtests(\n model,\n config;\n exclude = String[\"test_to_exclude\", \"test_conic_\"],\n)\nThis will exclude tests whose name contains either of the two strings provided.\nExclude tests which rely on specific functionality using:\nMOI.Test.Config(exclude = Any[MOI.VariableName, MOI.optimize!])\nThis will exclude tests which use the MOI.VariableName attribute, or which call MOI.optimize!.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Each test that fails can be independently called as:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"model = FooBar.Optimizer()\nconfig = MOI.Test.Config()\nMOI.empty!(model)\nMOI.Test.test_category_name_that_failed(model, config)","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"You can look-up the source code of the test that failed by searching for it in the src/Test/test_category.jl file.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nEach test function also has a docstring that explains what the test is for. Use ? MOI.Test.test_category_name_that_failed from the REPL to read it.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Periodically, you should re-run excluded tests to see if they now pass. The easiest way to do this is to swap the exclude keyword argument of runtests to include. For example:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"MOI.Test.runtests(\n model,\n config;\n exclude = String[\"test_to_exclude\", \"test_conic_\"],\n)","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"becomes","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"MOI.Test.runtests(\n model,\n config;\n include = String[\"test_to_exclude\", \"test_conic_\"],\n)","category":"page"},{"location":"submodules/Test/overview/#How-to-add-a-test","page":"Overview","title":"How to add a test","text":"","category":"section"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"To detect bugs in solvers, we add new tests to MOI.Test.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"As an example, ECOS errored calling optimize! twice in a row. (See ECOS.jl PR #72.) We could add a test to ECOS.jl, but that would only stop us from re-introducing the bug to ECOS.jl in the future, but it would not catch other solvers in the ecosystem with the same bug. Instead, if we add a test to MOI.Test, then all solvers will also check that they handle a double optimize call.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"For this test, we care about correctness, rather than performance. therefore, we don't expect solvers to efficiently decide that they have already solved the problem, only that calling optimize! twice doesn't throw an error or give the wrong answer.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 1","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Install the MathOptInterface julia package in dev mode:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"julia> ]\n(@v1.6) pkg> dev MathOptInterface","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 2","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"From here on, proceed with making the following changes in the ~/.julia/dev/MathOptInterface folder (or equivalent dev path on your machine).","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 3","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Since the double-optimize error involves solving an optimization problem, add a new test to src/Test/test_solve.jl:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"\"\"\"\n test_unit_optimize!_twice(model::MOI.ModelLike, config::Config)\n\nTest that calling `MOI.optimize!` twice does not error.\n\nThis problem was first detected in ECOS.jl PR#72:\nhttps://github.com/jump-dev/ECOS.jl/pull/72\n\"\"\"\nfunction test_unit_optimize!_twice(\n model::MOI.ModelLike,\n config::Config{T},\n) where {T}\n # Use the `@requires` macro to check conditions that the test function\n # requires to run. Models failing this `@requires` check will silently skip\n # the test.\n @requires MOI.supports_constraint(\n model,\n MOI.VariableIndex,\n MOI.GreaterThan{Float64},\n )\n @requires _supports(config, MOI.optimize!)\n # If needed, you can test that the model is empty at the start of the test.\n # You can assume that this will be the case for tests run via `runtests`.\n # User's calling tests individually need to call `MOI.empty!` themselves.\n @test MOI.is_empty(model)\n # Create a simple model. Try to make this as simple as possible so that the\n # majority of solvers can run the test.\n x = MOI.add_variable(model)\n MOI.add_constraint(model, x, MOI.GreaterThan(one(T)))\n MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n MOI.set(\n model,\n MOI.ObjectiveFunction{MOI.VariableIndex}(),\n x,\n )\n # The main component of the test: does calling `optimize!` twice error?\n MOI.optimize!(model)\n MOI.optimize!(model)\n # Check we have a solution.\n @test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMAL\n # There is a three-argument version of `Base.isapprox` for checking\n # approximate equality based on the tolerances defined in `config`:\n @test isapprox(MOI.get(model, MOI.VariablePrimal(), x), one(T), config)\n # For code-style, these tests should always `return` `nothing`.\n return\nend","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"info: Info\nMake sure the function is agnostic to the number type T; don't assume it is a Float64 capable solver.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"We also need to write a test for the test. Place this function immediately below the test you just wrote in the same file:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"function setup_test(\n ::typeof(test_unit_optimize!_twice),\n model::MOI.Utilities.MockOptimizer,\n ::Config,\n)\n MOI.Utilities.set_mock_optimize!(\n model,\n (mock::MOI.Utilities.MockOptimizer) -> MOIU.mock_optimize!(\n mock,\n MOI.OPTIMAL,\n (MOI.FEASIBLE_POINT, [1.0]),\n ),\n )\n return\nend","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Finally, you also need to implement Test.version_added. If we added this test when the latest released version of MOI was v0.10.5, define:","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"version_added(::typeof(test_unit_optimize!_twice)) = v\"0.10.6\"","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Step 6","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"Commit the changes to git from ~/.julia/dev/MathOptInterface and submit the PR for review.","category":"page"},{"location":"submodules/Test/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nIf you need help writing a test, open an issue on GitHub, or ask the Developer Chatroom.","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/errors/#Errors","page":"Errors","title":"Errors","text":"","category":"section"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"When an MOI call fails on a model, precise errors should be thrown when possible instead of simply calling error with a message. The docstrings for the respective methods describe the errors that the implementation should throw in certain situations. This error-reporting system allows code to distinguish between internal errors (that should be shown to the user) and unsupported operations which may have automatic workarounds.","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"When an invalid index is used in an MOI call, an InvalidIndex is thrown:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"InvalidIndex","category":"page"},{"location":"reference/errors/#MathOptInterface.InvalidIndex","page":"Errors","title":"MathOptInterface.InvalidIndex","text":"struct InvalidIndex{IndexType<:Index} <: Exception\n index::IndexType\nend\n\nAn error indicating that the index index is invalid.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"When an invalid result index is used to retrieve an attribute, a ResultIndexBoundsError is thrown:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"ResultIndexBoundsError\ncheck_result_index_bounds","category":"page"},{"location":"reference/errors/#MathOptInterface.ResultIndexBoundsError","page":"Errors","title":"MathOptInterface.ResultIndexBoundsError","text":"struct ResultIndexBoundsError{AttrType} <: Exception\n attr::AttrType\n result_count::Int\nend\n\nAn error indicating that the requested attribute attr could not be retrieved, because the solver returned too few results compared to what was requested. For instance, the user tries to retrieve VariablePrimal(2) when only one solution is available, or when the model is infeasible and has no solution.\n\nSee also: check_result_index_bounds.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.check_result_index_bounds","page":"Errors","title":"MathOptInterface.check_result_index_bounds","text":"check_result_index_bounds(model::ModelLike, attr)\n\nThis function checks whether enough results are available in the model for the requested attr, using its result_index field. If the model does not have sufficient results to answer the query, it throws a ResultIndexBoundsError.\n\n\n\n\n\n","category":"function"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"As discussed in JuMP mapping, for scalar constraint with a nonzero function constant, a ScalarFunctionConstantNotZero exception may be thrown:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"ScalarFunctionConstantNotZero","category":"page"},{"location":"reference/errors/#MathOptInterface.ScalarFunctionConstantNotZero","page":"Errors","title":"MathOptInterface.ScalarFunctionConstantNotZero","text":"struct ScalarFunctionConstantNotZero{T, F, S} <: Exception\n constant::T\nend\n\nAn error indicating that the constant part of the function in the constraint F-in-S is nonzero.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"Some VariableIndex constraints cannot be combined on the same variable:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"LowerBoundAlreadySet\nUpperBoundAlreadySet","category":"page"},{"location":"reference/errors/#MathOptInterface.LowerBoundAlreadySet","page":"Errors","title":"MathOptInterface.LowerBoundAlreadySet","text":"LowerBoundAlreadySet{S1, S2}\n\nError thrown when setting a VariableIndex-in-S2 when a VariableIndex-in-S1 has already been added and the sets S1, S2 both set a lower bound, that is, they are EqualTo, GreaterThan, Interval, Semicontinuous or Semiinteger.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UpperBoundAlreadySet","page":"Errors","title":"MathOptInterface.UpperBoundAlreadySet","text":"UpperBoundAlreadySet{S1, S2}\n\nError thrown when setting a VariableIndex-in-S2 when a VariableIndex-in-S1 has already been added and the sets S1, S2 both set an upper bound, that is, they are EqualTo, LessThan, Interval, Semicontinuous or Semiinteger.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"As discussed in AbstractCallback, trying to get attributes inside a callback may throw:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"OptimizeInProgress","category":"page"},{"location":"reference/errors/#MathOptInterface.OptimizeInProgress","page":"Errors","title":"MathOptInterface.OptimizeInProgress","text":"struct OptimizeInProgress{AttrType<:AnyAttribute} <: Exception\n attr::AttrType\nend\n\nError thrown from optimizer when MOI.get(optimizer, attr) is called inside an AbstractCallback while it is only defined once optimize! has completed. This can only happen when is_set_by_optimize(attr) is true.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"Trying to submit the wrong type of AbstractSubmittable inside an AbstractCallback (for example, a UserCut inside a LazyConstraintCallback) will throw:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"InvalidCallbackUsage","category":"page"},{"location":"reference/errors/#MathOptInterface.InvalidCallbackUsage","page":"Errors","title":"MathOptInterface.InvalidCallbackUsage","text":"struct InvalidCallbackUsage{C, S} <: Exception\n callback::C\n submittable::S\nend\n\nAn error indicating that submittable cannot be submitted inside callback.\n\nFor example, UserCut cannot be submitted inside LazyConstraintCallback.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"The rest of the errors defined in MOI fall in two categories represented by the following two abstract types:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"UnsupportedError\nNotAllowedError","category":"page"},{"location":"reference/errors/#MathOptInterface.UnsupportedError","page":"Errors","title":"MathOptInterface.UnsupportedError","text":"UnsupportedError <: Exception\n\nAbstract type for error thrown when an element is not supported by the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.NotAllowedError","page":"Errors","title":"MathOptInterface.NotAllowedError","text":"NotAllowedError <: Exception\n\nAbstract type for error thrown when an operation is supported but cannot be applied in the current state of the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"The different UnsupportedError and NotAllowedError are the following errors:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"UnsupportedAttribute\nSetAttributeNotAllowed\nAddVariableNotAllowed\nUnsupportedConstraint\nAddConstraintNotAllowed\nModifyConstraintNotAllowed\nModifyObjectiveNotAllowed\nDeleteNotAllowed\nUnsupportedSubmittable\nSubmitNotAllowed\nUnsupportedNonlinearOperator","category":"page"},{"location":"reference/errors/#MathOptInterface.UnsupportedAttribute","page":"Errors","title":"MathOptInterface.UnsupportedAttribute","text":"struct UnsupportedAttribute{AttrType} <: UnsupportedError\n attr::AttrType\n message::String\nend\n\nAn error indicating that the attribute attr is not supported by the model, that is, that supports returns false.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.SetAttributeNotAllowed","page":"Errors","title":"MathOptInterface.SetAttributeNotAllowed","text":"struct SetAttributeNotAllowed{AttrType} <: NotAllowedError\n attr::AttrType\n message::String\nend\n\nAn error indicating that the attribute attr is supported (see supports) but cannot be set for some reason (see the error string).\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.AddVariableNotAllowed","page":"Errors","title":"MathOptInterface.AddVariableNotAllowed","text":"struct AddVariableNotAllowed <: NotAllowedError\n message::String # Human-friendly explanation why the attribute cannot be set\nend\n\nAn error indicating that variables cannot be added to the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UnsupportedConstraint","page":"Errors","title":"MathOptInterface.UnsupportedConstraint","text":"struct UnsupportedConstraint{F<:AbstractFunction, S<:AbstractSet} <: UnsupportedError\n message::String # Human-friendly explanation why the attribute cannot be set\nend\n\nAn error indicating that constraints of type F-in-S are not supported by the model, that is, that supports_constraint returns false.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.AddConstraintNotAllowed","page":"Errors","title":"MathOptInterface.AddConstraintNotAllowed","text":"struct AddConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet} <: NotAllowedError\n message::String # Human-friendly explanation why the attribute cannot be set\nend\n\nAn error indicating that constraints of type F-in-S are supported (see supports_constraint) but cannot be added.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.ModifyConstraintNotAllowed","page":"Errors","title":"MathOptInterface.ModifyConstraintNotAllowed","text":"struct ModifyConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet,\n C<:AbstractFunctionModification} <: NotAllowedError\n constraint_index::ConstraintIndex{F, S}\n change::C\n message::String\nend\n\nAn error indicating that the constraint modification change cannot be applied to the constraint of index ci.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.ModifyObjectiveNotAllowed","page":"Errors","title":"MathOptInterface.ModifyObjectiveNotAllowed","text":"struct ModifyObjectiveNotAllowed{C<:AbstractFunctionModification} <: NotAllowedError\n change::C\n message::String\nend\n\nAn error indicating that the objective modification change cannot be applied to the objective.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.DeleteNotAllowed","page":"Errors","title":"MathOptInterface.DeleteNotAllowed","text":"struct DeleteNotAllowed{IndexType <: Index} <: NotAllowedError\n index::IndexType\n message::String\nend\n\nAn error indicating that the index index cannot be deleted.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UnsupportedSubmittable","page":"Errors","title":"MathOptInterface.UnsupportedSubmittable","text":"struct UnsupportedSubmittable{SubmitType} <: UnsupportedError\n sub::SubmitType\n message::String\nend\n\nAn error indicating that the submittable sub is not supported by the model, that is, that supports returns false.\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.SubmitNotAllowed","page":"Errors","title":"MathOptInterface.SubmitNotAllowed","text":"struct SubmitNotAllowed{SubmitTyp<:AbstractSubmittable} <: NotAllowedError\n sub::SubmitType\n message::String\nend\n\nAn error indicating that the submittable sub is supported (see supports) but cannot be added for some reason (see the error string).\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/#MathOptInterface.UnsupportedNonlinearOperator","page":"Errors","title":"MathOptInterface.UnsupportedNonlinearOperator","text":"UnsupportedNonlinearOperator(head::Symbol[, message::String]) <: UnsupportedError\n\nAn error thrown by optimizers if they do not support the operator head in a ScalarNonlinearFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> throw(MOI.UnsupportedNonlinearOperator(:black_box))\nERROR: MathOptInterface.UnsupportedNonlinearOperator: The nonlinear operator `:black_box` is not supported by the model.\nStacktrace:\n[...]\n\n\n\n\n\n","category":"type"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"Note that setting the ConstraintFunction of a VariableIndex constraint is not allowed:","category":"page"},{"location":"reference/errors/","page":"Errors","title":"Errors","text":"SettingVariableIndexNotAllowed","category":"page"},{"location":"reference/errors/#MathOptInterface.SettingVariableIndexNotAllowed","page":"Errors","title":"MathOptInterface.SettingVariableIndexNotAllowed","text":"SettingVariableIndexNotAllowed()\n\nError type that should be thrown when the user calls set to change the ConstraintFunction of a VariableIndex constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/","page":"Variables","title":"Variables","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/variables/#Variables","page":"Variables","title":"Variables","text":"","category":"section"},{"location":"reference/variables/#Functions","page":"Variables","title":"Functions","text":"","category":"section"},{"location":"reference/variables/","page":"Variables","title":"Variables","text":"add_variable\nadd_variables\nadd_constrained_variable\nadd_constrained_variables\nsupports_add_constrained_variable\nsupports_add_constrained_variables\nis_valid(::ModelLike,::VariableIndex)\ndelete(::ModelLike, ::VariableIndex)\ndelete(::ModelLike, ::Vector{VariableIndex})","category":"page"},{"location":"reference/variables/#MathOptInterface.add_variable","page":"Variables","title":"MathOptInterface.add_variable","text":"add_variable(model::ModelLike)::VariableIndex\n\nAdd a scalar variable to the model, returning a variable index.\n\nA AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.add_variables","page":"Variables","title":"MathOptInterface.add_variables","text":"add_variables(model::ModelLike, n::Int)::Vector{VariableIndex}\n\nAdd n scalar variables to the model, returning a vector of variable indices.\n\nA AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.add_constrained_variable","page":"Variables","title":"MathOptInterface.add_constrained_variable","text":"add_constrained_variable(\n model::ModelLike,\n set::AbstractScalarSet\n)::Tuple{MOI.VariableIndex,\n MOI.ConstraintIndex{MOI.VariableIndex, typeof(set)}}\n\nAdd to model a scalar variable constrained to belong to set, returning the index of the variable created and the index of the constraint constraining the variable to belong to set.\n\nBy default, this function falls back to creating a free variable with add_variable and then constraining it to belong to set with add_constraint.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.add_constrained_variables","page":"Variables","title":"MathOptInterface.add_constrained_variables","text":"add_constrained_variables(\n model::ModelLike,\n sets::AbstractVector{<:AbstractScalarSet}\n)::Tuple{\n Vector{MOI.VariableIndex},\n Vector{MOI.ConstraintIndex{MOI.VariableIndex,eltype(sets)}},\n}\n\nAdd to model scalar variables constrained to belong to sets, returning the indices of the variables created and the indices of the constraints constraining the variables to belong to each set in sets. That is, if it returns variables and constraints, constraints[i] is the index of the constraint constraining variable[i] to belong to sets[i].\n\nBy default, this function falls back to calling add_constrained_variable on each set.\n\n\n\n\n\nadd_constrained_variables(\n model::ModelLike,\n set::AbstractVectorSet,\n)::Tuple{\n Vector{MOI.VariableIndex},\n MOI.ConstraintIndex{MOI.VectorOfVariables,typeof(set)},\n}\n\nAdd to model a vector of variables constrained to belong to set, returning the indices of the variables created and the index of the constraint constraining the vector of variables to belong to set.\n\nBy default, this function falls back to creating free variables with add_variables and then constraining it to belong to set with add_constraint.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.supports_add_constrained_variable","page":"Variables","title":"MathOptInterface.supports_add_constrained_variable","text":"supports_add_constrained_variable(\n model::ModelLike,\n S::Type{<:AbstractScalarSet}\n)::Bool\n\nReturn a Bool indicating whether model supports constraining a variable to belong to a set of type S either on creation of the variable with add_constrained_variable or after the variable is created with add_constraint.\n\nBy default, this function falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VariableIndex, S) which is the correct definition for most models.\n\nExample\n\nSuppose that a solver supports only two kind of variables: binary variables and continuous variables with a lower bound. If the solver decides not to support VariableIndex-in-Binary and VariableIndex-in-GreaterThan constraints, it only has to implement add_constrained_variable for these two sets which prevents the user to add both a binary constraint and a lower bound on the same variable. Moreover, if the user adds a VariableIndex-in-GreaterThan constraint, implementing this interface (that is, supports_add_constrained_variables) enables the constraint to be transparently bridged into a supported constraint.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.supports_add_constrained_variables","page":"Variables","title":"MathOptInterface.supports_add_constrained_variables","text":"supports_add_constrained_variables(\n model::ModelLike,\n S::Type{<:AbstractVectorSet}\n)::Bool\n\nReturn a Bool indicating whether model supports constraining a vector of variables to belong to a set of type S either on creation of the vector of variables with add_constrained_variables or after the variable is created with add_constraint.\n\nBy default, if S is Reals then this function returns true and otherwise, it falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VectorOfVariables, S) which is the correct definition for most models.\n\nExample\n\nIn the standard conic form (see Duality), the variables are grouped into several cones and the constraints are affine equality constraints. If Reals is not one of the cones supported by the solvers then it needs to implement supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false as free variables are not supported. The solvers should then implement supports_add_constrained_variables(::Optimizer, ::Type{<:SupportedCones}) = true where SupportedCones is the union of all cone types that are supported; it does not have to implement the method supports_constraint(::Type{VectorOfVariables}, Type{<:SupportedCones}) as it should return false and it's the default. This prevents the user to constrain the same variable in two different cones. When a VectorOfVariables-in-S is added, the variables of the vector have already been created so they already belong to given cones. If bridges are enabled, the constraint will therefore be bridged by adding slack variables in S and equality constraints ensuring that the slack variables are equal to the corresponding variables of the given constraint function.\n\nNote that there may also be sets for which !supports_add_constrained_variables(model, S) and supports_constraint(model, MOI.VectorOfVariables, S). For instance, suppose a solver supports positive semidefinite variable constraints and two types of variables: binary variables and nonnegative variables. Then the solver should support adding VectorOfVariables-in-PositiveSemidefiniteConeTriangle constraints, but it should not support creating variables constrained to belong to the PositiveSemidefiniteConeTriangle because the variables in PositiveSemidefiniteConeTriangle should first be created as either binary or non-negative.\n\n\n\n\n\n","category":"function"},{"location":"reference/variables/#MathOptInterface.is_valid-Tuple{MathOptInterface.ModelLike, MathOptInterface.VariableIndex}","page":"Variables","title":"MathOptInterface.is_valid","text":"is_valid(model::ModelLike, index::Index)::Bool\n\nReturn a Bool indicating whether this index refers to a valid object in the model model.\n\n\n\n\n\n","category":"method"},{"location":"reference/variables/#MathOptInterface.delete-Tuple{MathOptInterface.ModelLike, MathOptInterface.VariableIndex}","page":"Variables","title":"MathOptInterface.delete","text":"delete(model::ModelLike, index::Index)\n\nDelete the referenced object from the model. Throw DeleteNotAllowed if if index cannot be deleted.\n\nThe following modifications also take effect if Index is VariableIndex:\n\nIf index used in the objective function, it is removed from the function, that is, it is substituted for zero.\nFor each func-in-set constraint of the model:\nIf func isa VariableIndex and func == index then the constraint is deleted.\nIf func isa VectorOfVariables and index in func.variables then\nif length(func.variables) == 1 is one, the constraint is deleted;\nif length(func.variables) > 1 and supports_dimension_update(set) then then the variable is removed from func and set is replaced by update_dimension(set, MOI.dimension(set) - 1).\nOtherwise, a DeleteNotAllowed error is thrown.\nOtherwise, the variable is removed from func, that is, it is substituted for zero.\n\n\n\n\n\n","category":"method"},{"location":"reference/variables/#MathOptInterface.delete-Tuple{MathOptInterface.ModelLike, Vector{MathOptInterface.VariableIndex}}","page":"Variables","title":"MathOptInterface.delete","text":"delete(model::ModelLike, indices::Vector{R<:Index}) where {R}\n\nDelete the referenced objects in the vector indices from the model. It may be assumed that R is a concrete type. The default fallback sequentially deletes the individual items in indices, although specialized implementations may be more efficient.\n\n\n\n\n\n","category":"method"},{"location":"reference/variables/#Attributes","page":"Variables","title":"Attributes","text":"","category":"section"},{"location":"reference/variables/","page":"Variables","title":"Variables","text":"AbstractVariableAttribute\nVariableName\nVariablePrimalStart\nVariablePrimal\nVariableBasisStatus","category":"page"},{"location":"reference/variables/#MathOptInterface.AbstractVariableAttribute","page":"Variables","title":"MathOptInterface.AbstractVariableAttribute","text":"AbstractVariableAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of variables in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariableName","page":"Variables","title":"MathOptInterface.VariableName","text":"VariableName()\n\nA variable attribute for a string identifying the variable. It is valid for two variables to have the same name; however, variables with duplicate names cannot be looked up using get. It has a default value of \"\" if not set`.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariablePrimalStart","page":"Variables","title":"MathOptInterface.VariablePrimalStart","text":"VariablePrimalStart()\n\nA variable attribute for the initial assignment to some primal variable's value that the optimizer may use to warm-start the solve. May be a number or nothing (unset).\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariablePrimal","page":"Variables","title":"MathOptInterface.VariablePrimal","text":"VariablePrimal(result_index::Int = 1)\n\nA variable attribute for the assignment to some primal variable's value in result result_index. If result_index is omitted, it is 1 by default.\n\nIf the solver does not have a primal value for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariablePrimal attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/variables/#MathOptInterface.VariableBasisStatus","page":"Variables","title":"MathOptInterface.VariableBasisStatus","text":"VariableBasisStatus(result_index::Int = 1)\n\nA variable attribute for the BasisStatusCode of a variable in result result_index, with respect to an available optimal solution basis.\n\nIf the solver does not have a basis statue for the variable because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the VariableBasisStatus attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#List-of-bridges","page":"List of bridges","title":"List of bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"This section describes the Bridges.AbstractBridges that are implemented in MathOptInterface.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#constraint_bridges_ref","page":"List of bridges","title":"Constraint bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"These bridges are subtypes of Bridges.Constraint.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"Bridges.Constraint.GreaterToIntervalBridge\nBridges.Constraint.LessToIntervalBridge\nBridges.Constraint.GreaterToLessBridge\nBridges.Constraint.LessToGreaterBridge\nBridges.Constraint.NonnegToNonposBridge\nBridges.Constraint.NonposToNonnegBridge\nBridges.Constraint.VectorizeBridge\nBridges.Constraint.ScalarizeBridge\nBridges.Constraint.ScalarSlackBridge\nBridges.Constraint.VectorSlackBridge\nBridges.Constraint.ScalarFunctionizeBridge\nBridges.Constraint.VectorFunctionizeBridge\nBridges.Constraint.ToScalarQuadraticBridge\nBridges.Constraint.ToVectorQuadraticBridge\nBridges.Constraint.ToScalarNonlinearBridge\nBridges.Constraint.FunctionConversionBridge\nBridges.Constraint.SplitComplexEqualToBridge\nBridges.Constraint.SplitComplexZerosBridge\nBridges.Constraint.SplitHyperRectangleBridge\nBridges.Constraint.SplitIntervalBridge\nBridges.Constraint.SOCtoRSOCBridge\nBridges.Constraint.RSOCtoSOCBridge\nBridges.Constraint.SOCtoNonConvexQuadBridge\nBridges.Constraint.RSOCtoNonConvexQuadBridge\nBridges.Constraint.QuadtoSOCBridge\nBridges.Constraint.SOCtoPSDBridge\nBridges.Constraint.RSOCtoPSDBridge\nBridges.Constraint.NormInfinityBridge\nBridges.Constraint.NormOneBridge\nBridges.Constraint.NormToPowerBridge\nBridges.Constraint.NormOneConeToNormConeBridge\nBridges.Constraint.SecondOrderConeToNormConeBridge\nBridges.Constraint.NormInfinityConeToNormConeBridge\nBridges.Constraint.GeoMeantoRelEntrBridge\nBridges.Constraint.GeoMeanToPowerBridge\nBridges.Constraint.GeoMeanBridge\nBridges.Constraint.RelativeEntropyBridge\nBridges.Constraint.NormSpectralBridge\nBridges.Constraint.NormNuclearBridge\nBridges.Constraint.SquareBridge\nBridges.Constraint.HermitianToSymmetricPSDBridge\nBridges.Constraint.SetDotScalingBridge\nBridges.Constraint.SetDotInverseScalingBridge\nBridges.Constraint.RootDetBridge\nBridges.Constraint.LogDetBridge\nBridges.Constraint.IndicatorActiveOnFalseBridge\nBridges.Constraint.IndicatorGreaterToLessThanBridge\nBridges.Constraint.IndicatorLessToGreaterThanBridge\nBridges.Constraint.IndicatorSOS1Bridge\nBridges.Constraint.SemiToBinaryBridge\nBridges.Constraint.ZeroOneBridge\nBridges.Constraint.IntegerToZeroOneBridge\nBridges.Constraint.NumberConversionBridge\nBridges.Constraint.AllDifferentToCountDistinctBridge\nBridges.Constraint.ReifiedAllDifferentToCountDistinctBridge\nBridges.Constraint.BinPackingToMILPBridge\nBridges.Constraint.CircuitToMILPBridge\nBridges.Constraint.CountAtLeastToCountBelongsBridge\nBridges.Constraint.CountBelongsToMILPBridge\nBridges.Constraint.CountDistinctToMILPBridge\nBridges.Constraint.ReifiedCountDistinctToMILPBridge\nBridges.Constraint.CountGreaterThanToMILPBridge\nBridges.Constraint.TableToMILPBridge\nBridges.Constraint.SOS1ToMILPBridge\nBridges.Constraint.SOS2ToMILPBridge\nBridges.Constraint.IndicatorToMILPBridge","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GreaterToIntervalBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GreaterToIntervalBridge","text":"GreaterToIntervalBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nGreaterToIntervalBridge implements the following reformulations:\n\nf(x) ge l into f(x) in l infty)\n\nSource node\n\nGreaterToIntervalBridge supports:\n\nF in MOI.GreaterThan{T}\n\nTarget nodes\n\nGreaterToIntervalBridge creates:\n\nF in MOI.Interval{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.LessToIntervalBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.LessToIntervalBridge","text":"LessToIntervalBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nLessToIntervalBridge implements the following reformulations:\n\nf(x) le u into f(x) in (-infty u\n\nSource node\n\nLessToIntervalBridge supports:\n\nF in MOI.LessThan{T}\n\nTarget nodes\n\nLessToIntervalBridge creates:\n\nF in MOI.Interval{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GreaterToLessBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GreaterToLessBridge","text":"GreaterToLessBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nGreaterToLessBridge implements the following reformulation:\n\nf(x) ge l into -f(x) le -l\n\nSource node\n\nGreaterToLessBridge supports:\n\nG in MOI.GreaterThan{T}\n\nTarget nodes\n\nGreaterToLessBridge creates:\n\nF in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.LessToGreaterBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.LessToGreaterBridge","text":"LessToGreaterBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nLessToGreaterBridge implements the following reformulation:\n\nf(x) le u into -f(x) ge -u\n\nSource node\n\nLessToGreaterBridge supports:\n\nG in MOI.LessThan{T}\n\nTarget nodes\n\nLessToGreaterBridge creates:\n\nF in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NonnegToNonposBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NonnegToNonposBridge","text":"NonnegToNonposBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNonnegToNonposBridge implements the following reformulation:\n\nf(x) in mathbbR_+ into -f(x) in mathbbR_-\n\nSource node\n\nNonnegToNonposBridge supports:\n\nG in MOI.Nonnegatives\n\nTarget nodes\n\nNonnegToNonposBridge creates:\n\nF in MOI.Nonpositives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NonposToNonnegBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NonposToNonnegBridge","text":"NonposToNonnegBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNonposToNonnegBridge implements the following reformulation:\n\nf(x) in mathbbR_- into -f(x) in mathbbR_+\n\nSource node\n\nNonposToNonnegBridge supports:\n\nG in MOI.Nonpositives\n\nTarget nodes\n\nNonposToNonnegBridge creates:\n\nF in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.VectorizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.VectorizeBridge","text":"VectorizeBridge{T,F,S,G} <: Bridges.Constraint.AbstractBridge\n\nVectorizeBridge implements the following reformulations:\n\ng(x) ge a into g(x) - a in mathbbR_+\ng(x) le a into g(x) - a in mathbbR_-\ng(x) == a into g(x) - a in 0\n\nwhere T is the coefficient type of g(x) - a.\n\nSource node\n\nVectorizeBridge supports:\n\nG in MOI.GreaterThan{T}\nG in MOI.LessThan{T}\nG in MOI.EqualTo{T}\n\nTarget nodes\n\nVectorizeBridge creates:\n\nF in S, where S is one of MOI.Nonnegatives, MOI.Nonpositives, MOI.Zeros depending on the type of the input set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ScalarizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ScalarizeBridge","text":"ScalarizeBridge{T,F,S}\n\nScalarizeBridge implements the following reformulations:\n\nf(x) - a in mathbbR_+ into f_i(x) ge a_i for all i\nf(x) - a in mathbbR_- into f_i(x) le a_i for all i\nf(x) - a in 0 into f_i(x) == a_i for all i\n\nSource node\n\nScalarizeBridge supports:\n\nG in MOI.Nonnegatives{T}\nG in MOI.Nonpositives{T}\nG in MOI.Zeros{T}\n\nTarget nodes\n\nScalarizeBridge creates:\n\nF in S, where S is one of MOI.GreaterThan{T}, MOI.LessThan{T}, and MOI.EqualTo{T}, depending on the type of the input set.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ScalarSlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ScalarSlackBridge","text":"ScalarSlackBridge{T,F,S} <: Bridges.Constraint.AbstractBridge\n\nScalarSlackBridge implements the following reformulation:\n\nf(x) in S into f(x) - y == 0 and y in S\n\nSource node\n\nScalarSlackBridge supports:\n\nG in S, where G is not MOI.VariableIndex and S is not MOI.EqualTo\n\nTarget nodes\n\nScalarSlackBridge creates:\n\nF in MOI.EqualTo{T}\nMOI.VariableIndex in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.VectorSlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.VectorSlackBridge","text":"VectorSlackBridge{T,F,S} <: Bridges.Constraint.AbstractBridge\n\nVectorSlackBridge implements the following reformulation:\n\nf(x) in S into f(x) - y in 0 and y in S\n\nSource node\n\nVectorSlackBridge supports:\n\nG in S, where G is not MOI.VectorOfVariables and S is not MOI.Zeros\n\nTarget nodes\n\nVectorSlackBridge creates:\n\nF in MOI.Zeros\nMOI.VectorOfVariables in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ScalarFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ScalarFunctionizeBridge","text":"ScalarFunctionizeBridge{T,S} = FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},MOI.VariableIndex,S}\n\nScalarFunctionizeBridge implements the following reformulations:\n\nx in S into 1x + 0 in S\n\nSource node\n\nScalarFunctionizeBridge supports:\n\nMOI.VariableIndex in S\n\nTarget nodes\n\nScalarFunctionizeBridge creates:\n\nMOI.ScalarAffineFunction{T} in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.VectorFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.VectorFunctionizeBridge","text":"VectorFunctionizeBridge{T,S} = FunctionConversionBridge{T,MOI.VectorAffineFunction{T},S}\n\nVectorFunctionizeBridge implements the following reformulations:\n\nx in S into Ix + 0 in S\n\nSource node\n\nVectorFunctionizeBridge supports:\n\nMOI.VectorOfVariables in S\n\nTarget nodes\n\nVectorFunctionizeBridge creates:\n\nMOI.VectorAffineFunction{T} in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ToScalarQuadraticBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ToScalarQuadraticBridge","text":"ToScalarQuadraticBridge{T,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nToScalarQuadraticBridge implements the following reformulation:\n\ng(x) in S into f(x) in S\n\nwhere g is an abstract scalar function and f is a MOI.ScalarQuadraticFunction.\n\nSource node\n\nToScalarQuadraticBridge supports:\n\nG<:AbstractScalarFunction in S\n\nTarget nodes\n\nToScalarQuadraticBridge creates:\n\nMOI.ScalarQuadraticFunction in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ToVectorQuadraticBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ToVectorQuadraticBridge","text":"ToVectorQuadraticBridge{T,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nToVectorQuadraticBridge implements the following reformulation:\n\ng(x) in S into f(x) in S\n\nwhere g is an abstract vector function and f is a MOI.VectorQuadraticFunction.\n\nSource node\n\nToVectorQuadraticBridge supports:\n\nG<:AbstractVectorFunction in S\n\nTarget nodes\n\nToVectorQuadraticBridge creates:\n\nMOI.VectorQuadraticFunction in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ToScalarNonlinearBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ToScalarNonlinearBridge","text":"ToScalarNonlinearBridge{T,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nToScalarNonlinearBridge implements the following reformulation:\n\ng(x) in S into f(x) in S\n\nwhere g is an abstract scalar function and f is a MOI.ScalarNonlinearFunction.\n\nSource node\n\nToScalarNonlinearBridge supports:\n\nG<:AbstractScalarFunction in S\n\nTarget nodes\n\nToScalarNonlinearBridge creates:\n\nMOI.ScalarNonlinearFunction in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.FunctionConversionBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.FunctionConversionBridge","text":"FunctionConversionBridge{T,F,G,S} <: AbstractFunctionConversionBridge{G,S}\n\nFunctionConversionBridge implements the following reformulations:\n\ng(x) in S into f(x) in S\n\nfor these pairs of functions:\n\nMOI.ScalarAffineFunctionto [MOI.ScalarQuadraticFunction`](@ref)\nMOI.ScalarQuadraticFunction to MOI.ScalarNonlinearFunction\nMOI.VectorAffineFunction to MOI.VectorQuadraticFunction\n\nSource node\n\nFunctionConversionBridge supports:\n\nG in S\n\nTarget nodes\n\nFunctionConversionBridge creates:\n\nF in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitComplexEqualToBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitComplexEqualToBridge","text":"SplitComplexEqualToBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSplitComplexEqualToBridge implements the following reformulation:\n\nf(x) + g(x) * im = a + b * im into f(x) = a and g(x) = b\n\nSource node\n\nSplitComplexEqualToBridge supports:\n\nG in MOI.EqualTo{Complex{T}}\n\nwhere G is a function with Complex coefficients.\n\nTarget nodes\n\nSplitComplexEqualToBridge creates:\n\nF in MOI.EqualTo{T}\n\nwhere F is the type of the real/imaginary part of G.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitComplexZerosBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitComplexZerosBridge","text":"SplitComplexZerosBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSplitComplexZerosBridge implements the following reformulation:\n\nf(x) in 0^n into textRe(f(x)) in 0^n and textIm(f(x)) in 0^n\n\nSource node\n\nSplitComplexZerosBridge supports:\n\nG in MOI.Zeros\n\nwhere G is a function with Complex coefficients.\n\nTarget nodes\n\nSplitComplexZerosBridge creates:\n\nF in MOI.Zeros\n\nwhere F is the type of the real/imaginary part of G.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitHyperRectangleBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitHyperRectangleBridge","text":"SplitHyperRectangleBridge{T,G,F} <: Bridges.Constraint.AbstractBridge\n\nSplitHyperRectangleBridge implements the following reformulation:\n\nf(x) in textsfHyperRectangle(l u) to f(x) - l u - f(x) in mathbbR_+.\n\nSource node\n\nSplitHyperRectangleBridge supports:\n\nF in MOI.HyperRectangle\n\nTarget nodes\n\nSplitHyperRectangleBridge creates:\n\nG in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SplitIntervalBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SplitIntervalBridge","text":"SplitIntervalBridge{T,F,S,LS,US} <: Bridges.Constraint.AbstractBridge\n\nSplitIntervalBridge implements the following reformulations:\n\nl le f(x) le u into f(x) ge l and f(x) le u\nf(x) = b into f(x) ge b and f(x) le b\nf(x) in 0 into f(x) in mathbbR_+ and f(x) in mathbbR_-\n\nSource node\n\nSplitIntervalBridge supports:\n\nF in MOI.Interval{T}\nF in MOI.EqualTo{T}\nF in MOI.Zeros\n\nTarget nodes\n\nSplitIntervalBridge creates:\n\nF in MOI.LessThan{T}\nF in MOI.GreaterThan{T}\n\nor\n\nF in MOI.Nonnegatives\nF in MOI.Nonpositives\n\nnote: Note\nIf T<:AbstractFloat and S is MOI.Interval{T} then no lower (resp. upper) bound constraint is created if the lower (resp. upper) bound is typemin(T) (resp. typemax(T)). Similarly, when MOI.ConstraintSet is set, a lower or upper bound constraint may be deleted or created accordingly.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOCtoRSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOCtoRSOCBridge","text":"SOCtoRSOCBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSOCtoRSOCBridge implements the following reformulation:\n\nx_2 le t into (t+x_1)(t-x_1)ge (x_2ldotsx_N)_2^2\n\nAssumptions\n\nSOCtoRSOCBridge assumes that the length of x is at least one.\n\nSource node\n\nSOCtoRSOCBridge supports:\n\nG in MOI.SecondOrderCone\n\nTarget node\n\nSOCtoRSOCBridge creates:\n\nF in MOI.RotatedSecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RSOCtoSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RSOCtoSOCBridge","text":"RSOCtoSOCBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nRSOCtoSOCBridge implements the following reformulation:\n\nx_2^2 le 2tu into fract - usqrt 2 x_2 le fract + usqrt 2\n\nSource node\n\nRSOCtoSOCBridge supports:\n\nG in MOI.RotatedSecondOrderCone\n\nTarget node\n\nRSOCtoSOCBridge creates:\n\nF in MOI.SecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOCtoNonConvexQuadBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOCtoNonConvexQuadBridge","text":"SOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge\n\nSOCtoNonConvexQuadBridge implements the following reformulations:\n\nx_2 le t into sum x^2 - t^2 le 0 and 1t + 0 ge 0\n\nThe MOI.ScalarAffineFunction 1t + 0 is used in case the variable has other bound constraints.\n\nwarning: Warning\nThis transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.\n\nSource node\n\nSOCtoNonConvexQuadBridge supports:\n\nMOI.VectorOfVariables in MOI.SecondOrderCone\n\nTarget nodes\n\nSOCtoNonConvexQuadBridge creates:\n\nMOI.ScalarQuadraticFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RSOCtoNonConvexQuadBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RSOCtoNonConvexQuadBridge","text":"RSOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge\n\nRSOCtoNonConvexQuadBridge implements the following reformulations:\n\nx_2^2 le 2tu into sum x^2 - 2tu le 0, 1t + 0 ge 0, and 1u + 0 ge 0.\n\nThe MOI.ScalarAffineFunctions 1t + 0 and 1u + 0 are used in case the variables have other bound constraints.\n\nwarning: Warning\nThis transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting rotated second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.\n\nSource node\n\nRSOCtoNonConvexQuadBridge supports:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\nTarget nodes\n\nRSOCtoNonConvexQuadBridge creates:\n\nMOI.ScalarQuadraticFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.QuadtoSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.QuadtoSOCBridge","text":"QuadtoSOCBridge{T} <: Bridges.Constraint.AbstractBridge\n\nQuadtoSOCBridge converts quadratic inequalities\n\nfrac12x^T Q x + a^T x le ub\n\ninto MOI.RotatedSecondOrderCone constraints, but it only applies when Q is positive definite.\n\nThis is because, if Q is positive definite, there exists U such that Q = U^T U, and so the inequality can then be rewritten as;\n\nU x_2^2 le 2 (-a^T x + ub)\n\nTherefore, QuadtoSOCBridge implements the following reformulations:\n\nfrac12x^T Q x + a^T x le ub into (1 -a^T x + ub Ux) in RotatedSecondOrderCone where Q = U^T U\nfrac12x^T Q x + a^T x ge lb into (1 a^T x - lb Ux) in RotatedSecondOrderCone where -Q = U^T U\n\nSource node\n\nQuadtoSOCBridge supports:\n\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\nTarget nodes\n\nRelativeEntropyBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.RotatedSecondOrderCone\n\nErrors\n\nThis bridge errors if Q is not positive definite.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOCtoPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOCtoPSDBridge","text":"SOCtoPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nSOCtoPSDBridge implements the following reformulation:\n\nx_2 le t into leftbeginarrayc ct x^top x t mathbfIendarrayrightsucceq 0\n\nwarning: Warning\nThis bridge is not added by default by MOI.Bridges.full_bridge_optimizer because bridging second order cone constraints to semidefinite constraints can be achieved by the SOCtoRSOCBridge followed by the RSOCtoPSDBridge, while creating a smaller semidefinite constraint.\n\nSource node\n\nSOCtoPSDBridge supports:\n\nG in MOI.SecondOrderCone\n\nTarget nodes\n\nSOCtoPSDBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RSOCtoPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RSOCtoPSDBridge","text":"RSOCtoPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nRSOCtoPSDBridge implements the following reformulation:\n\nx_2^2 le 2tcdot u into leftbeginarrayc ct x^top x 2tu mathbfIendarrayrightsucceq 0\n\nSource node\n\nRSOCtoPSDBridge supports:\n\nG in MOI.RotatedSecondOrderCone\n\nTarget nodes\n\nRSOCtoPSDBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormInfinityBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormInfinityBridge","text":"NormInfinityBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNormInfinityBridge implements the following reformulation:\n\nx_infty le t into t - x_i t + x_i in mathbbR_+.\n\nSource node\n\nNormInfinityBridge supports:\n\nG in MOI.NormInfinityCone{T}\n\nTarget nodes\n\nNormInfinityBridge creates:\n\nF in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormOneBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormOneBridge","text":"NormOneBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNormOneBridge implements the following reformulation:\n\nsum x_i le t into t - sum y_i y_i - x_i y_i + x_i in mathbbR_+.\n\nSource node\n\nNormOneBridge supports:\n\nG in MOI.NormOneCone{T}\n\nTarget nodes\n\nNormOneBridge creates:\n\nF in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormToPowerBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormToPowerBridge","text":"NormToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nNormToPowerBridge implements the following reformulation:\n\n(t x) in NormCone(p 1+d) into (r_i t x_i) in PowerCone(1 p) for all i, and sumlimits_i r_i == t.\n\nFor details, see Alizadeh, F., and Goldfarb, D. (2001). \"Second-order cone programming.\" Mathematical Programming, Series B, 95:3-51.\n\nSource node\n\nNormToPowerBridge supports:\n\nF in MOI.NormCone\n\nTarget nodes\n\nNormToPowerBridge creates:\n\nF in MOI.PowerCone{T}\nMOI.ScalarAffineFunction in MOI.EqualTo\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormOneConeToNormConeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormOneConeToNormConeBridge","text":"NormOneConeToNormConeBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nNormOneConeToNormConeBridge implements the following reformulations:\n\n(t x) in NormOneCone(d) into (t x) in NormCone(1 d)\n\nSource node\n\nNormOneConeToNormConeBridge supports:\n\nF in MOI.NormOneCone\n\nTarget nodes\n\nNormOneConeToNormConeBridge creates:\n\nF in MOI.NormCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SecondOrderConeToNormConeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SecondOrderConeToNormConeBridge","text":"SecondOrderConeToNormConeBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nSecondOrderConeToNormConeBridge implements the following reformulations:\n\n(t x) in SecondOrderCone(d) into (t x) in NormCone(2 d)\n\nSource node\n\nSecondOrderConeToNormConeBridge supports:\n\nF in MOI.SecondOrderCone\n\nTarget nodes\n\nSecondOrderConeToNormConeBridge creates:\n\nF in MOI.NormCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormInfinityConeToNormConeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormInfinityConeToNormConeBridge","text":"NormInfinityConeToNormConeBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nNormInfinityConeToNormConeBridge implements the following reformulations:\n\n(t x) in NormInfinityCone(d) into (t x) in NormCone(Inf d)\n\nSource node\n\nNormInfinityConeToNormConeBridge supports:\n\nF in MOI.NormInfinityCone\n\nTarget nodes\n\nNormInfinityConeToNormConeBridge creates:\n\nF in MOI.NormCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GeoMeantoRelEntrBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GeoMeantoRelEntrBridge","text":"GeoMeantoRelEntrBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nGeoMeantoRelEntrBridge implements the following reformulation:\n\n(u w) in GeometricMeanCone into (0 w (u + y)mathbf1)in RelativeEntropyCone and y ge 0\n\nSource node\n\nGeoMeantoRelEntrBridge supports:\n\nH in MOI.GeometricMeanCone\n\nTarget nodes\n\nGeoMeantoRelEntrBridge creates:\n\nG in MOI.RelativeEntropyCone\nF in MOI.Nonnegatives\n\nDerivation\n\nThe derivation of the bridge is as follows:\n\nbeginaligned\n(u w) in GeometricMeanCone iff u le left(prod_i=1^n w_iright)^1n \niff 0 le u + y le left(prod_i=1^n w_iright)^1n y ge 0 \niff 1 le fracleft(prod_i=1^n w_iright)^1nu + y y ge 0 \niff 1 le left(prod_i=1^n fracw_iu + yright)^1n y ge 0 \niff 0 le sum_i=1^n logleft(fracw_iu + yright) y ge 0 \niff 0 ge sum_i=1^n logleft(fracu + yw_iright) y ge 0 \niff 0 ge sum_i=1^n (u + y) logleft(fracu + yw_iright) y ge 0 \niff (0 w (u + y)mathbf1) in RelativeEntropyCone y ge 0 \nendaligned\n\nThis derivation assumes that u + y 0, which is enforced by the relative entropy cone.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GeoMeanToPowerBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GeoMeanToPowerBridge","text":"GeoMeanToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nGeoMeanToPowerBridge implements the following reformulation:\n\n(y x) in GeometricMeanCone(1+d) into (x_1 t y) in PowerCone(1d) and (t x_2 x_d) in GeometricMeanCone(d), which is then recursively expanded into more PowerCone constraints.\n\nSource node\n\nGeoMeanToPowerBridge supports:\n\nF in MOI.GeometricMeanCone\n\nTarget nodes\n\nGeoMeanToPowerBridge creates:\n\nF in MOI.PowerCone{T}\nMOI.VectorOfVariables in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.GeoMeanBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.GeoMeanBridge","text":"GeoMeanBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nGeoMeanBridge implements a reformulation from MOI.GeometricMeanCone into MOI.RotatedSecondOrderCone.\n\nThe reformulation is best described in an example.\n\nConsider the cone of dimension 4:\n\nt le sqrt3x_1 x_2 x_3\n\nThis can be rewritten as exists y ge 0 such that:\n\nbeginalign*\n t le y\n y^4 le x_1 x_2 x_3 y\nendalign*\n\nNote that we need to create y and not use t^4 directly because t is not allowed to be negative.\n\nThis is equivalent to:\n\nbeginalign*\n t le fracy_1sqrt4\n y_1^2 le 2y_2 y_3\n y_2^2 le 2x_1 x_2 \n y_3^2 le 2x_3(y_1sqrt4) \n y ge 0\nendalign*\n\nMore generally, you can show how the geometric mean code is recursively expanded into a set of new variables y in MOI.Nonnegatives, a set of MOI.RotatedSecondOrderCone constraints, and a MOI.LessThan constraint between t and y_1.\n\nSource node\n\nGeoMeanBridge supports:\n\nH in MOI.GeometricMeanCone\n\nTarget nodes\n\nGeoMeanBridge creates:\n\nF in MOI.LessThan{T}\nG in MOI.RotatedSecondOrderCone\nG in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RelativeEntropyBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RelativeEntropyBridge","text":"RelativeEntropyBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nRelativeEntropyBridge implements the following reformulation that converts a MOI.RelativeEntropyCone into an MOI.ExponentialCone:\n\nu ge sum_i=1^n w_i log left(fracw_iv_iright) into y_i ge 0, u ge sum_i=1^n y_i, and (-y_i w_i v_i) in ExponentialCone.\n\nSource node\n\nRelativeEntropyBridge supports:\n\nH in MOI.RelativeEntropyCone\n\nTarget nodes\n\nRelativeEntropyBridge creates:\n\nF in MOI.GreaterThan{T}\nG in MOI.ExponentialCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormSpectralBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormSpectralBridge","text":"NormSpectralBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nNormSpectralBridge implements the following reformulation:\n\nt ge sigma_1(X) into leftbeginarrayc ctmathbfI X^top X t mathbfIendarrayright succeq 0\n\nSource node\n\nNormSpectralBridge supports:\n\nG in MOI.NormSpectralCone\n\nTarget nodes\n\nNormSpectralBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NormNuclearBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NormNuclearBridge","text":"NormNuclearBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nNormNuclearBridge implements the following reformulation:\n\nt ge sum_i sigma_i (X) into leftbeginarrayc cU X^top X Vendarrayright succeq 0 and 2t ge tr(U) + tr(V).\n\nSource node\n\nNormNuclearBridge supports:\n\nH in MOI.NormNuclearCone\n\nTarget nodes\n\nNormNuclearBridge creates:\n\nF in MOI.GreaterThan{T}\nG in MOI.PositiveSemidefiniteConeTriangle\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SquareBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SquareBridge","text":"SquareBridge{T,F,G,TT,ST} <: Bridges.Constraint.AbstractBridge\n\nSquareBridge implements the following reformulations:\n\n(t u X) in LogDetConeSquare into (t u Y) in LogDetConeTriangle\n(t X) in RootDetConeSquare into (t Y) in RootDetConeTriangle\nX in AbstractSymmetricMatrixSetSquare into Y in AbstractSymmetricMatrixSetTriangle\n\nwhere Y is the upper triangluar component of X.\n\nIn addition, constraints are added as necessary to constrain the matrix X to be symmetric. For example, the constraint for the matrix:\n\nbeginpmatrix\n 1 1 + x 2 - 3x\n 1 + x 2 + x 3 - x\n 2 - 3x 2 + x 2x\nendpmatrix\n\ncan be broken down to the constraint of the symmetric matrix\n\nbeginpmatrix\n 1 1 + x 2 - 3x\n cdot 2 + x 3 - x\n cdot cdot 2x\nendpmatrix\n\nand the equality constraint between the off-diagonal entries (2, 3) and (3, 2) 3 - x == 2 + x. Note that no symmetrization constraint needs to be added between the off-diagonal entries (1, 2) and (2, 1) or between (1, 3) and (3, 1) because the expressions are the same.\n\nSource node\n\nSquareBridge supports:\n\nF in ST\n\nTarget nodes\n\nSquareBridge creates:\n\nG in TT\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.HermitianToSymmetricPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.HermitianToSymmetricPSDBridge","text":"HermitianToSymmetricPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge\n\nHermitianToSymmetricPSDBridge implements the following reformulation:\n\nHermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix.\n\nSee also MOI.Bridges.Variable.HermitianToSymmetricPSDBridge.\n\nSource node\n\nHermitianToSymmetricPSDBridge supports:\n\nG in MOI.HermitianPositiveSemidefiniteConeTriangle\n\nTarget node\n\nHermitianToSymmetricPSDBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\n\nReformulation\n\nThe reformulation is best described by example.\n\nThe Hermitian matrix:\n\nbeginbmatrix\n x_11 x_12 + y_12im x_13 + y_13im\n x_12 - y_12im x_22 x_23 + y_23im\n x_13 - y_13im x_23 - y_23im x_33\nendbmatrix\n\nis positive semidefinite if and only if the symmetric matrix:\n\nbeginbmatrix\n x_11 x_12 x_13 0 y_12 y_13 \n x_22 x_23 -y_12 0 y_23 \n x_33 -y_13 -y_23 0 \n x_11 x_12 x_13 \n x_22 x_23 \n x_33\nendbmatrix\n\nis positive semidefinite.\n\nThe bridge achieves this reformulation by constraining the above matrix to belong to the MOI.PositiveSemidefiniteConeTriangle(6).\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SetDotScalingBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SetDotScalingBridge","text":"SetDotScalingBridge{T,S,F,G} <: Bridges.Constraint.AbstractBridge\n\nSetDotScalingBridge implements the reformulation from constraints in S to constraints in MOI.Scaled{S}.\n\nSource node\n\nSetDotScalingBridge supports:\n\nG in S\n\nTarget node\n\nSetDotScalingBridge creates:\n\nF in MOI.Scaled{S}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SetDotInverseScalingBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SetDotInverseScalingBridge","text":"SetDotInverseScalingBridge{T,S,F,G} <: Bridges.Constraint.AbstractBridge\n\nSetDotInverseScalingBridge implements the reformulation from constraints in the MOI.Scaled{S} to constraints in the S.\n\nSource node\n\nSetDotInverseScalingBridge supports:\n\nG in MOI.Scaled{S}\n\nTarget node\n\nSetDotInverseScalingBridge creates:\n\nF in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.RootDetBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.RootDetBridge","text":"RootDetBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge\n\nThe MOI.RootDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.GeometricMeanCone constraints, see [1, p. 149].\n\nIndeed, t le det(X)^1n if and only if there exists a lower triangular matrix Δ such that:\n\nbeginalign*\n beginpmatrix\n X Δ\n Δ^top mathrmDiag(Δ)\n endpmatrix succeq 0\n (t mathrmDiag(Δ)) in GeometricMeanCone\nendalign*\n\nSource node\n\nRootDetBridge supports:\n\nI in MOI.RootDetConeTriangle\n\nTarget nodes\n\nRootDetBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\nG in MOI.GeometricMeanCone\n\n[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.LogDetBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.LogDetBridge","text":"LogDetBridge{T,F,G,H,I} <: Bridges.Constraint.AbstractBridge\n\nThe MOI.LogDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.ExponentialCone constraints.\n\nIndeed, logdet(X) = sumlimits_i=1^n log(delta_i) where delta_i are the eigenvalues of X.\n\nAdapting the method from [1, p. 149], we see that t le u log(det(Xu)) for u 0 if and only if there exists a lower triangular matrix Δ such that\n\nbeginalign*\n beginpmatrix\n X Δ\n Δ^top mathrmDiag(Δ)\n endpmatrix succeq 0\n t - sum_i=1^n u logleft(fracΔ_iiuright) le 0\nendalign*\n\nWhich we reformulate further into\n\nbeginalign*\n beginpmatrix\n X Δ\n Δ^top mathrmDiag(Δ)\n endpmatrix succeq 0\n (l_i u Δ_ii) in ExponentialConequad forall i \n t - sum_i=1^n l_i le 0\nendalign*\n\nSource node\n\nLogDetBridge supports:\n\nI in MOI.LogDetConeTriangle\n\nTarget nodes\n\nLogDetBridge creates:\n\nF in MOI.PositiveSemidefiniteConeTriangle\nG in MOI.ExponentialCone\nH in MOI.LessThan{T}\n\n[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridge","text":"IndicatorActiveOnFalseBridge{T,F,S} <: Bridges.Constraint.AbstractBridge\n\nIndicatorActiveOnFalseBridge implements the following reformulation:\n\nneg z implies f(x) in S into y implies f(x) in S, z + y = 1, and y in 0 1\n\nSource node\n\nIndicatorActiveOnFalseBridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{MOI.ACTIVATE_ON_ZERO,S}\n\nTarget nodes\n\nIndicatorActiveOnFalseBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{MOI.ACTIVATE_ON_ONE,S}\nMOI.ScalarAffineFunction{T} in MOI.EqualTo\nMOI.VariableIndex in MOI.ZeroOne\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorGreaterToLessThanBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorGreaterToLessThanBridge","text":"IndicatorGreaterToLessThanBridge{T,A} <: Bridges.Constraint.AbstractBridge\n\nIndicatorGreaterToLessThanBridge implements the following reformulation:\n\nz implies f(x) ge l into z implies -f(x) le -l\n\nSource node\n\nIndicatorGreaterToLessThanBridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.GreaterThan{T}}\n\nTarget nodes\n\nIndicatorGreaterToLessThanBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.LessThan{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorLessToGreaterThanBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorLessToGreaterThanBridge","text":"IndicatorLessToGreaterThanBridge{T,A} <: Bridges.Constraint.AbstractBridge\n\nIndicatorLessToGreaterThanBridge implements the following reformulations:\n\nz implies f(x) le u into z implies -f(x) ge -u\n\nSource node\n\nIndicatorLessToGreaterThanBridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.LessThan{T}}\n\nTarget nodes\n\nIndicatorLessToGreaterThanBridge creates:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{A,MOI.GreaterThan{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorSOS1Bridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorSOS1Bridge","text":"IndicatorSOS1Bridge{T,S} <: Bridges.Constraint.AbstractBridge\n\nIndicatorSOS1Bridge implements the following reformulation:\n\nz implies f(x) in S into f(x) + y in S, SOS1(y z)\n\nwarning: Warning\nThis bridge assumes that the solver supports MOI.SOS1{T} constraints in which one of the variables (y) is continuous.\n\nSource node\n\nIndicatorSOS1Bridge supports:\n\nMOI.VectorAffineFunction{T} in MOI.Indicator{MOI.ACTIVATE_ON_ONE,S}\n\nTarget nodes\n\nIndicatorSOS1Bridge creates:\n\nMOI.ScalarAffineFunction{T} in S\nMOI.VectorOfVariables in MOI.SOS1{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SemiToBinaryBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SemiToBinaryBridge","text":"SemiToBinaryBridge{T,S} <: Bridges.Constraint.AbstractBridge\n\nSemiToBinaryBridge implements the following reformulations:\n\nx in 0 cup l u into\nbeginaligned\nx leq z u \nx geq z l \nz in 0 1\nendaligned\nx in 0 cup l ldots u into\nbeginaligned\nx leq z u \nx geq z l \nz in 0 1 \nx in mathbbZ\nendaligned\n\nSource node\n\nSemiToBinaryBridge supports:\n\nMOI.VariableIndex in MOI.Semicontinuous{T}\nMOI.VariableIndex in MOI.Semiinteger{T}\n\nTarget nodes\n\nSemiToBinaryBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\nMOI.VariableIndex{T} in MOI.Integer (if S is MOI.Semiinteger{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ZeroOneBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ZeroOneBridge","text":"ZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge\n\nZeroOneBridge implements the following reformulation:\n\nx in 0 1 into x in mathbbZ, 1x in 0 1.\n\nnote: Note\nZeroOneBridge adds a linear constraint instead of adding variable bounds to avoid conflicting with bounds set by the user.\n\nSource node\n\nZeroOneBridge supports:\n\nMOI.VariableIndex in MOI.ZeroOne\n\nTarget nodes\n\nZeroOneBridge creates:\n\nMOI.VariableIndex in MOI.Integer\nMOI.ScalarAffineFunction{T} in MOI.Interval{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IntegerToZeroOneBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IntegerToZeroOneBridge","text":"IntegerToZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge\n\nIntegerToZeroOneBridge implements the following reformulation:\n\nx in mathbfZ into y_i in 0 1, x == lb + sum 2^i-1 y_i.\n\nSource node\n\nIntegerToZeroOneBridge supports:\n\nVariableIndex in MOI.Integer\n\nTarget nodes\n\nIntegerToZeroOneBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\nDeveloper note\n\nThis bridge is implemented as a constraint bridge instead of a variable bridge because we don't want to substitute the linear combination of y for every instance of x. Doing so would be expensive and greatly reduce the sparsity of the constraints.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.NumberConversionBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.NumberConversionBridge","text":"NumberConversionBridge{T,F1,S1,F2,S2} <: Bridges.Constraint.AbstractBridge\n\nNumberConversionBridge implements the following reformulation:\n\nf1(x) in S1 to f2(x) in S2\n\nwhere f and S are the same functional form, but differ in their coefficient type.\n\nSource node\n\nNumberConversionBridge supports:\n\nF1 in S1\n\nTarget node\n\nNumberConversionBridge creates:\n\nF2 in S2\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.AllDifferentToCountDistinctBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.AllDifferentToCountDistinctBridge","text":"AllDifferentToCountDistinctBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nAllDifferentToCountDistinctBridge implements the following reformulations:\n\nx in textsfAllDifferent(d) to (n x) in textsfCountDistinct(1+d) and n = d\nf(x) in textsfAllDifferent(d) to (d f(x)) in textsfCountDistinct(1+d)\n\nSource node\n\nAllDifferentToCountDistinctBridge supports:\n\nF in MOI.AllDifferent\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nAllDifferentToCountDistinctBridge creates:\n\nF in MOI.CountDistinct\nMOI.VariableIndex in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridge","text":"ReifiedAllDifferentToCountDistinctBridge{T,F} <:\nBridges.Constraint.AbstractBridge\n\nReifiedAllDifferentToCountDistinctBridge implements the following reformulations:\n\nr iff x in textsfAllDifferent(d) to r iff (n x) in textsfCountDistinct(1+d) and n = d\nr iff f(x) in textsfAllDifferent(d) to r iff (d f(x)) in textsfCountDistinct(1+d)\n\nSource node\n\nReifiedAllDifferentToCountDistinctBridge supports:\n\nF in MOI.Reified{MOI.AllDifferent}\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nReifiedAllDifferentToCountDistinctBridge creates:\n\nF in MOI.Reified{MOI.CountDistinct}\nMOI.VariableIndex in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.BinPackingToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.BinPackingToMILPBridge","text":"BinPackingToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nBinPackingToMILPBridge implements the following reformulation:\n\nx in BinPacking(c w) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nThen, we add the capacity constraint for all possible bins j:\n\nsumlimits_i w_i z_ij le c forall j in bigcup_i=1ldotsd S_i\n\nSource node\n\nBinPackingToMILPBridge supports:\n\nF in MOI.BinPacking{T}\n\nTarget nodes\n\nBinPackingToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CircuitToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CircuitToMILPBridge","text":"CircuitToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCircuitToMILPBridge implements the following reformulation:\n\nx in textsfCircuit(d) to the Miller-Tucker-Zemlin formulation of the Traveling Salesperson Problem.\n\nSource node\n\nCircuitToMILPBridge supports:\n\nF in MOI.Circuit\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCircuitToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.VariableIndex in MOI.Integer\nMOI.VariableIndex in MOI.Interval{T}\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountAtLeastToCountBelongsBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountAtLeastToCountBelongsBridge","text":"CountAtLeastToCountBelongsBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountAtLeastToCountBelongsBridge implements the following reformulation:\n\nx in textsfCountAtLeast(n d mathcalS) to (n_i x_d_i) in textsfCountBelongs(1+d mathcalS) and n_i ge n for all i.\n\nSource node\n\nCountAtLeastToCountBelongsBridge supports:\n\nF in MOI.CountAtLeast\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCountAtLeastToCountBelongsBridge creates:\n\nF in MOI.CountBelongs\nMOI.VariableIndex in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountBelongsToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountBelongsToMILPBridge","text":"CountBelongsToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountBelongsToMILPBridge implements the following reformulation:\n\n(n x) in textsfCountBelongs(1+d mathcalS) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nFinally, n is constrained to be the number of z_ij elements that are in mathcalS:\n\nn - sumlimits_iin 1ldots d j in mathcalS z_ij = 0\n\nSource node\n\nCountBelongsToMILPBridge supports:\n\nF in MOI.CountBelongs\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCountBelongsToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountDistinctToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountDistinctToMILPBridge","text":"CountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountDistinctToMILPBridge implements the following reformulation:\n\n(n x) in textsfCountDistinct(1+d) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nThen, we introduce new binary variables y_j, which are 1 if a variable takes the value j in the optimal solution and 0 otherwise.\n\nbeginaligned\ny_j in 0 1 forall j in bigcup_i=1ldotsd S_i \ny_j le sumlimits_i in 1ldots d j in S_i z_ij le M y_j forall j in bigcup_i=1ldotsd S_i\nendaligned\n\nFinally, n is constrained to be the number of y_j elements that are non-zero:\n\nn - sumlimits_j in bigcup_i=1ldotsd S_i y_j = 0\n\nSource node\n\nCountDistinctToMILPBridge supports:\n\nF in MOI.CountDistinct\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nCountDistinctToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.ReifiedCountDistinctToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.ReifiedCountDistinctToMILPBridge","text":"ReifiedCountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nReifiedCountDistinctToMILPBridge implements the following reformulation:\n\nr iff (n x) in textsfCountDistinct(1+d) into a mixed-integer linear program.\n\nReformulation\n\nThe reformulation is non-trivial, and it depends on the finite domain of each variable x_i, which we as define S_i = l_ildotsu_i.\n\nFirst, we introduce new binary variables z_ij, which are 1 if variable x_i takes the value j in the optimal solution and 0 otherwise:\n\nbeginaligned\nz_ij in 0 1 forall i in 1ldots d j in S_i \nx_i - sumlimits_jin S_i j cdot z_ij = 0 forall i in 1ldots d \nsumlimits_jin S_i z_ij = 1 forall i in 1ldots d \nendaligned\n\nThen, we introduce new binary variables y_j, which are 1 if a variable takes the value j in the optimal solution and 0 otherwise.\n\nbeginaligned\ny_j in 0 1 forall j in bigcup_i=1ldotsd S_i \ny_j le sumlimits_i in 1ldots d j in S_i z_ij le M y_j forall j in bigcup_i=1ldotsd S_i\nendaligned\n\nFinally, n is constrained to be the number of y_j elements that are non-zero, with some slack:\n\nn - sumlimits_j in bigcup_i=1ldotsd S_i y_j = delta^+ - delta^-\n\nAnd then the slack is constrained to respect the reif variable r:\n\nbeginaligned\nd_1 le delta^+ le M d_1 \nd_2 le delta^- le M d_s \nd_1 + d_2 + r = 1 \nd_1 d_2 in 0 1\nendaligned\n\nSource node\n\nReifiedCountDistinctToMILPBridge supports:\n\nF in MOI.Reified{MOI.CountDistinct}\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nReifiedCountDistinctToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.CountGreaterThanToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.CountGreaterThanToMILPBridge","text":"CountGreaterThanToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nCountGreaterThanToMILPBridge implements the following reformulation:\n\n(c y x) in CountGreaterThan() into a mixed-integer linear program.\n\nSource node\n\nCountGreaterThanToMILPBridge supports:\n\nF in MOI.CountGreaterThan\n\nTarget nodes\n\nCountGreaterThanToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.GreaterThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.TableToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.TableToMILPBridge","text":"TableToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nTableToMILPBridge implements the following reformulation:\n\nx in Table(t) into\nbeginaligned\nz_j in 0 1 quad forall i j \nsumlimits_j=1^n z_j = 1 \nsumlimits_j=1^n t_ij z_j = x_i quad forall i\nendaligned\n\nSource node\n\nTableToMILPBridge supports:\n\nF in MOI.Table{T}\n\nTarget nodes\n\nTableToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOS1ToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOS1ToMILPBridge","text":"SOS1ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nSOS1ToMILPBridge implements the following reformulation:\n\nx in textsfSOS1(d) into a mixed-integer linear program.\n\nSource node\n\nSOS1ToMILPBridge supports:\n\nF in MOI.SOS1\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nSOS1ToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.SOS2ToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.SOS2ToMILPBridge","text":"SOS2ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge\n\nSOS2ToMILPBridge implements the following reformulation:\n\nx in textsfSOS2(d) into a mixed-integer linear program.\n\nSource node\n\nSOS2ToMILPBridge supports:\n\nF in MOI.SOS2\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nSOS2ToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\nMOI.ScalarAffineFunction{T} in MOI.LessThan{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Constraint.IndicatorToMILPBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Constraint.IndicatorToMILPBridge","text":"IndicatorToMILPBridge{T,F,A,S} <: Bridges.Constraint.AbstractBridge\n\nIndicatorToMILPBridge implements the following reformulation:\n\nx in textsfIndicator(s) into a mixed-integer linear program.\n\nSource node\n\nIndicatorToMILPBridge supports:\n\nF in MOI.Indicator{A,S}\n\nwhere F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.\n\nTarget nodes\n\nIndicatorToMILPBridge creates:\n\nMOI.VariableIndex in MOI.ZeroOne\nMOI.ScalarAffineFunction{T} in S\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#objective_bridges_ref","page":"List of bridges","title":"Objective bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"These bridges are subtypes of Bridges.Objective.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"Bridges.Objective.FunctionizeBridge\nBridges.Objective.QuadratizeBridge\nBridges.Objective.VectorFunctionizeBridge\nBridges.Objective.FunctionConversionBridge\nBridges.Objective.SlackBridge\nBridges.Objective.VectorSlackBridge","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.FunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.FunctionizeBridge","text":"FunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},G}\n\nFunctionizeBridge implements the following reformulations:\n\nmin x into min1x + 0\nmax x into max1x + 0\n\nwhere T is the coefficient type of 1 and 0.\n\nSource node\n\nFunctionizeBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nFunctionizeBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.QuadratizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.QuadratizeBridge","text":"QuadratizeBridge{T,G} <: FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G}\n\nQuadratizeBridge implements the following reformulations:\n\nmin a^top x + b into minx^top mathbf0 x + a^top x + b\nmax a^top x + b into maxx^top mathbf0 x + a^top x + b\n\nwhere T is the coefficient type of 0.\n\nSource node\n\nQuadratizeBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nQuadratizeBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.VectorFunctionizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.VectorFunctionizeBridge","text":"VectorFunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.VectorAffineFunction{T},G}\n\nVectorFunctionizeBridge implements the following reformulations:\n\nmin x into min1x + 0\nmax x into max1x + 0\n\nwhere T is the coefficient type of 1 and 0.\n\nSource node\n\nVectorFunctionizeBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nVectorFunctionizeBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{MOI.VectorAffineFunction{T}}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.FunctionConversionBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.FunctionConversionBridge","text":"FunctionConversionBridge{T,F,G} <: AbstractBridge\n\nFunctionConversionBridge implements the following reformulations:\n\nmin g(x) into minf(x)\nmax g(x) into maxf(x)\n\nfor these pairs of functions:\n\nMOI.ScalarAffineFunctionto [MOI.ScalarQuadraticFunction`](@ref)\nMOI.ScalarQuadraticFunction to MOI.ScalarNonlinearFunction\nMOI.VectorAffineFunction to MOI.VectorQuadraticFunction\n\nSource node\n\nFunctionConversionBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nFunctionConversionBridge creates:\n\nOne objective node: MOI.ObjectiveFunction{F}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.SlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.SlackBridge","text":"SlackBridge{T,F,G}\n\nSlackBridge implements the following reformulations:\n\nminf(x) into miny f(x) - y le 0\nmaxf(x) into maxy f(x) - y ge 0\n\nwhere F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).\n\nSource node\n\nSlackBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nSlackBridge creates:\n\nOne variable node: MOI.VariableIndex in MOI.Reals\nOne objective node: MOI.ObjectiveFunction{MOI.VariableIndex}\nOne constraint node, that depends on the MOI.ObjectiveSense:\nF-in-MOI.LessThan if MIN_SENSE\nF-in-MOI.GreaterThan if MAX_SENSE\n\nwarning: Warning\nWhen using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Objective.VectorSlackBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Objective.VectorSlackBridge","text":"VectorSlackBridge{T,F,G}\n\nVectorSlackBridge implements the following reformulations:\n\nminf(x) into miny y - f(x) in mathbbR_+ \nmaxf(x) into maxy f(x) - y in mathbbR_+ \n\nwhere F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).\n\nSource node\n\nVectorSlackBridge supports:\n\nMOI.ObjectiveFunction{G}\n\nTarget nodes\n\nVectorSlackBridge creates:\n\nOne variable node: MOI.VectorOfVariables in MOI.Reals\nOne objective node: MOI.ObjectiveFunction{MOI.VectorOfVariables}\nOne constraint node: F-in-MOI.Nonnegatives\n\nwarning: Warning\nWhen using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#variable_bridges_ref","page":"List of bridges","title":"Variable bridges","text":"","category":"section"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"These bridges are subtypes of Bridges.Variable.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/list_of_bridges/","page":"List of bridges","title":"List of bridges","text":"Bridges.Variable.FreeBridge\nBridges.Variable.NonposToNonnegBridge\nBridges.Variable.RSOCtoPSDBridge\nBridges.Variable.RSOCtoSOCBridge\nBridges.Variable.SOCtoRSOCBridge\nBridges.Variable.VectorizeBridge\nBridges.Variable.ZerosBridge\nBridges.Variable.HermitianToSymmetricPSDBridge\nBridges.Variable.ParameterToEqualToBridge","category":"page"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.FreeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.FreeBridge","text":"FreeBridge{T} <: Bridges.Variable.AbstractBridge\n\nFreeBridge implements the following reformulation:\n\nx in mathbbR into y z ge 0 with the substitution rule x = y - z,\n\nwhere T is the coefficient type of y - z.\n\nSource node\n\nFreeBridge supports:\n\nMOI.VectorOfVariables in MOI.Reals\n\nTarget nodes\n\nFreeBridge creates:\n\nOne variable node: MOI.VectorOfVariables in MOI.Nonnegatives\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.NonposToNonnegBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.NonposToNonnegBridge","text":"NonposToNonnegBridge{T} <: Bridges.Variable.AbstractBridge\n\nNonposToNonnegBridge implements the following reformulation:\n\nx in mathbbR_- into y in mathbbR_+ with the substitution rule x = -y,\n\nwhere T is the coefficient type of -y.\n\nSource node\n\nNonposToNonnegBridge supports:\n\nMOI.VectorOfVariables in MOI.Nonpositives\n\nTarget nodes\n\nNonposToNonnegBridge creates:\n\nOne variable node: MOI.VectorOfVariables in MOI.Nonnegatives,\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.RSOCtoPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.RSOCtoPSDBridge","text":"RSOCtoPSDBridge{T} <: Bridges.Variable.AbstractBridge\n\nRSOCtoPSDBridge implements the following reformulation:\n\nx_2^2 le 2tu where t u ge 0 into Y succeq 0, with the substitution rule: Y = leftbeginarrayc ct x^top x 2u mathbfIendarrayright\n\nAdditional bounds are added to ensure the off-diagonals of the 2uI submatrix are 0, and linear constraints are added to ensure the diagonal of 2uI takes the same values.\n\nAs a special case, if x = 0, then RSOCtoPSDBridge reformulates into (t u) in mathbbR_+.\n\nSource node\n\nRSOCtoPSDBridge supports:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\nTarget nodes\n\nRSOCtoPSDBridge creates:\n\nOne variable node that depends on the input dimension:\nMOI.VectorOfVariables in MOI.Nonnegatives if dimension is 1 or 2\nMOI.VectorOfVariables in\nMOI.PositiveSemidefiniteConeTriangle otherwise\nThe constraint node MOI.VariableIndex in MOI.EqualTo\nThe constant node MOI.ScalarAffineFunction in MOI.EqualTo\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.RSOCtoSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.RSOCtoSOCBridge","text":"RSOCtoSOCBridge{T} <: Bridges.Variable.AbstractBridge\n\nRSOCtoSOCBridge implements the following reformulation:\n\nx_2^2 le 2tu into v_2 le w, with the substitution rules t = fracwsqrt 2 + fracv_1sqrt 2, u = fracwsqrt 2 - fracv_1sqrt 2, and x = (v_2ldotsv_N).\n\nSource node\n\nRSOCtoSOCBridge supports:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\nTarget node\n\nRSOCtoSOCBridge creates:\n\nMOI.VectorOfVariables in MOI.SecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.SOCtoRSOCBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.SOCtoRSOCBridge","text":"SOCtoRSOCBridge{T} <: Bridges.Variable.AbstractBridge\n\nSOCtoRSOCBridge implements the following reformulation:\n\nx_2 le t into 2uv ge w_2^2, with the substitution rules t = fracusqrt 2 + fracvsqrt 2, x = (fracusqrt 2 - fracvsqrt 2 w).\n\nAssumptions\n\nSOCtoRSOCBridge assumes that x ge 1.\n\nSource node\n\nSOCtoRSOCBridge supports:\n\nMOI.VectorOfVariables in MOI.SecondOrderCone\n\nTarget node\n\nSOCtoRSOCBridge creates:\n\nMOI.VectorOfVariables in MOI.RotatedSecondOrderCone\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.VectorizeBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.VectorizeBridge","text":"VectorizeBridge{T,S} <: Bridges.Variable.AbstractBridge\n\nVectorizeBridge implements the following reformulations:\n\nx ge a into y in mathbbR_+ with the substitution rule x = a + y\nx le a into y in mathbbR_- with the substitution rule x = a + y\nx == a into y in 0 with the substitution rule x = a + y\n\nwhere T is the coefficient type of a + y.\n\nSource node\n\nVectorizeBridge supports:\n\nMOI.VariableIndex in MOI.GreaterThan{T}\nMOI.VariableIndex in MOI.LessThan{T}\nMOI.VariableIndex in MOI.EqualTo{T}\n\nTarget nodes\n\nVectorizeBridge creates:\n\nOne variable node: MOI.VectorOfVariables in S, where S is one of MOI.Nonnegatives, MOI.Nonpositives, MOI.Zeros depending on the type of S.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.ZerosBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.ZerosBridge","text":"ZerosBridge{T} <: Bridges.Variable.AbstractBridge\n\nZerosBridge implements the following reformulation:\n\nx in 0 into the substitution rule x = 0,\n\nwhere T is the coefficient type of 0.\n\nSource node\n\nZerosBridge supports:\n\nMOI.VectorOfVariables in MOI.Zeros\n\nTarget nodes\n\nZerosBridge does not create target nodes. It replaces all instances of x with 0 via substitution. This means that no variables are created in the underlying model.\n\nCaveats\n\nThe bridged variables are similar to parameters with zero values. Parameters with non-zero values can be created with constrained variables in MOI.EqualTo by combining a VectorizeBridge and this bridge.\n\nHowever, functions modified by ZerosBridge cannot be unbridged. That is, for a given function, we cannot determine if the bridged variables were used.\n\nA related implication is that this bridge does not support MOI.ConstraintDual. However, if a MOI.Utilities.CachingOptimizer is used, the dual can be determined by the bridged optimizer using MOI.Utilities.get_fallback because the caching optimizer records the unbridged function.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.HermitianToSymmetricPSDBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.HermitianToSymmetricPSDBridge","text":"HermitianToSymmetricPSDBridge{T} <: Bridges.Variable.AbstractBridge\n\nHermitianToSymmetricPSDBridge implements the following reformulation:\n\nHermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix satisfying equality constraints described below.\n\nSource node\n\nHermitianToSymmetricPSDBridge supports:\n\nMOI.VectorOfVariables in MOI.HermitianPositiveSemidefiniteConeTriangle\n\nTarget node\n\nHermitianToSymmetricPSDBridge creates:\n\nMOI.VectorOfVariables in MOI.PositiveSemidefiniteConeTriangle\nMOI.ScalarAffineFunction{T} in MOI.EqualTo{T}\n\nReformulation\n\nThe reformulation is best described by example.\n\nThe Hermitian matrix:\n\nbeginbmatrix\n x_11 x_12 + y_12im x_13 + y_13im\n x_12 - y_12im x_22 x_23 + y_23im\n x_13 - y_13im x_23 - y_23im x_33\nendbmatrix\n\nis positive semidefinite if and only if the symmetric matrix:\n\nbeginbmatrix\n x_11 x_12 x_13 0 y_12 y_13 \n x_22 x_23 -y_12 0 y_23 \n x_33 -y_13 -y_23 0 \n x_11 x_12 x_13 \n x_22 x_23 \n x_33\nendbmatrix\n\nis positive semidefinite.\n\nThe bridge achieves this reformulation by adding a new set of variables in MOI.PositiveSemidefiniteConeTriangle(6), and then adding three groups of equality constraints to:\n\nconstrain the two x blocks to be equal\nforce the diagonal of the y blocks to be 0\nforce the lower triangular of the y block to be the negative of the upper triangle.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/list_of_bridges/#MathOptInterface.Bridges.Variable.ParameterToEqualToBridge","page":"List of bridges","title":"MathOptInterface.Bridges.Variable.ParameterToEqualToBridge","text":"ParameterToEqualToBridge{T} <: Bridges.Variable.AbstractBridge\n\nParameterToEqualToBridge implements the following reformulation:\n\nx in Parameter(v) into x == v\n\nSource node\n\nParameterToEqualToBridge supports:\n\nMOI.VariableIndex in MOI.Parameter\n\nTarget nodes\n\nParameterToEqualToBridge creates:\n\nOne variable node: MOI.VariableIndex in MOI.EqualTo{T}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/overview/#The-Bridges-submodule","page":"Overview","title":"The Bridges submodule","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The Bridges module simplifies the process of converting models between equivalent formulations.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nRead our paper for more details on how bridges are implemented.","category":"page"},{"location":"submodules/Bridges/overview/#Why-bridges?","page":"Overview","title":"Why bridges?","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"A constraint can often be written in a number of equivalent formulations. For example, the constraint l le a^top x le u (ScalarAffineFunction-in-Interval) could be re-formulated as two constraints: a^top x ge l (ScalarAffineFunction-in-GreaterThan) and a^top x le u (ScalarAffineFunction-in-LessThan). An alternative re-formulation is to add a dummy variable y with the constraints l le y le u (VariableIndex-in-Interval) and a^top x - y = 0 (ScalarAffineFunction-in-EqualTo).","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"To avoid each solver having to code these transformations manually, MathOptInterface provides bridges.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"A bridge is a small transformation from one constraint type to another (potentially collection of) constraint type.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Because these bridges are included in MathOptInterface, they can be re-used by any optimizer. Some bridges also implement constraint modifications and constraint primal and dual translations.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Several bridges can be used in combination to transform a single constraint into a form that the solver may understand. Choosing the bridges to use takes the form of finding a shortest path in the hyper-graph of bridges. The methodology is detailed in the MOI paper.","category":"page"},{"location":"submodules/Bridges/overview/#The-three-types-of-bridges","page":"Overview","title":"The three types of bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"There are three types of bridges in MathOptInterface:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Constraint bridges\nVariable bridges\nObjective bridges","category":"page"},{"location":"submodules/Bridges/overview/#Constraint-bridges","page":"Overview","title":"Constraint bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Constraint bridges convert constraints formulated by the user into an equivalent form supported by the solver. Constraint bridges are subtypes of Bridges.Constraint.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The equivalent formulation may add constraints (and possibly also variables) in the underlying model.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"In particular, constraint bridges can focus on rewriting the function of a constraint, and do not change the set. Function bridges are subtypes of Bridges.Constraint.AbstractFunctionConversionBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Read the list of implemented constraint bridges for more details on the types of transformations that are available. Function bridges are Bridges.Constraint.ScalarFunctionizeBridge and Bridges.Constraint.VectorFunctionizeBridge.","category":"page"},{"location":"submodules/Bridges/overview/#variable_bridges","page":"Overview","title":"Variable bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Variable bridges convert variables added by the user, either free with add_variable/add_variables, or constrained with add_constrained_variable/add_constrained_variables, into an equivalent form supported by the solver. Variable bridges are subtypes of Bridges.Variable.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The equivalent formulation may add constraints (and possibly also variables) in the underlying model.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Read the list of implemented variable bridges for more details on the types of transformations that are available.","category":"page"},{"location":"submodules/Bridges/overview/#Objective-bridges","page":"Overview","title":"Objective bridges","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Objective bridges convert the ObjectiveFunction set by the user into an equivalent form supported by the solver. Objective bridges are subtypes of Bridges.Objective.AbstractBridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"The equivalent formulation may add constraints (and possibly also variables) in the underlying model.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Read the list of implemented objective bridges for more details on the types of transformations that are available.","category":"page"},{"location":"submodules/Bridges/overview/#Bridges.full_bridge_optimizer","page":"Overview","title":"Bridges.full_bridge_optimizer","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nUnless you have an advanced use-case, this is probably the only function you need to care about.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"To enable the full power of MathOptInterface's bridges, wrap an optimizer in a Bridges.full_bridge_optimizer.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> inner_optimizer = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64)\nMOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}\nwith 0 variable bridges\nwith 0 constraint bridges\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Now, use optimizer as normal, and bridging will happen lazily behind the scenes. By lazily, we mean that bridging will happen if and only if the constraint is not supported by the inner_optimizer.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"info: Info\nMost bridges are added by default in Bridges.full_bridge_optimizer. However, for technical reasons, some bridges are not added by default. Three examples include Bridges.Constraint.SOCtoPSDBridge, Bridges.Constraint.SOCtoNonConvexQuadBridge and Bridges.Constraint.RSOCtoNonConvexQuadBridge. See the docs of those bridges for more information.","category":"page"},{"location":"submodules/Bridges/overview/#Add-a-single-bridge","page":"Overview","title":"Add a single bridge","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"If you don't want to use Bridges.full_bridge_optimizer, you can wrap an optimizer in a single bridge.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"However, this will force the constraint to be bridged, even if the inner_optimizer supports it.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> inner_optimizer = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer)\nMOIB.Constraint.SingleBridgeOptimizer{MOIB.Constraint.SplitIntervalBridge{Float64}, MOIU.Model{Float64}}\nwith 0 constraint bridges\nwith inner model MOIU.Model{Float64}\n\njulia> x = MOI.add_variable(optimizer)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n\njulia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())\n1-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})\n\njulia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())\n2-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64})\n (MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64})","category":"page"},{"location":"submodules/Bridges/overview/#Bridges.LazyBridgeOptimizer","page":"Overview","title":"Bridges.LazyBridgeOptimizer","text":"","category":"section"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"If you don't want to use Bridges.full_bridge_optimizer, but you need more than a single bridge (or you want the bridging to happen lazily), you can manually construct a Bridges.LazyBridgeOptimizer.","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"First, wrap an inner optimizer:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> inner_optimizer = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> optimizer = MOI.Bridges.LazyBridgeOptimizer(inner_optimizer)\nMOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}\nwith 0 variable bridges\nwith 0 constraint bridges\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Then use Bridges.add_bridge to add individual bridges:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Constraint.SplitIntervalBridge{Float64})\n\njulia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Objective.FunctionizeBridge{Float64})","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"Now the constraints will be bridged only if needed:","category":"page"},{"location":"submodules/Bridges/overview/","page":"Overview","title":"Overview","text":"julia> x = MOI.add_variable(optimizer)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n\njulia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())\n1-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})\n\njulia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())\n1-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})","category":"page"},{"location":"developer/checklists/#Checklists","page":"Checklists","title":"Checklists","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"The purpose of this page is to collate a series of checklists for commonly performed changes to the source code of MathOptInterface.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"In each case, copy the checklist into the description of the pull request.","category":"page"},{"location":"developer/checklists/#Making-a-release","page":"Checklists","title":"Making a release","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when making a release of the MathOptInterface repository.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] `version` field of `Project.toml` has been updated\n - If a breaking change, increment the MAJOR field and reset others to 0\n - If adding new features, increment the MINOR field and reset PATCH to 0\n - If adding bug fixes or documentation changes, increment the PATCH field\n\n## Documentation\n\n - [ ] Add a new entry to `docs/src/changelog.md`, following existing style\n\n## Tests\n\n - [ ] The `solver-tests.yml` GitHub action does not have unexpected failures.\n To run the action, go to:\n https://github.com/jump-dev/MathOptInterface.jl/actions/workflows/solver-tests.yml\n and click \"Run workflow\"","category":"page"},{"location":"developer/checklists/#Adding-a-new-set","page":"Checklists","title":"Adding a new set","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when adding a new set to the MathOptInterface repository.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] Add a new `AbstractScalarSet` or `AbstractVectorSet` to `src/sets.jl`\n - [ ] If `isbitstype(S) == false`, implement `Base.copy(set::S)`\n - [ ] If `isbitstype(S) == false`, implement `Base.:(==)(x::S, y::S)`\n - [ ] If an `AbstractVectorSet`, implement `dimension(set::S)`, unless the\n dimension is given by `set.dimension`.\n\n## Utilities\n\n - [ ] If an `AbstractVectorSet`, implement `Utilities.set_dot`,\n unless the dot product between two vectors in the set is equivalent to\n `LinearAlgebra.dot`\n - [ ] If an `AbstractVectorSet`, implement `Utilities.set_with_dimension` in\n `src/Utilities/matrix_of_constraints.jl`\n - [ ] Add the set to the `@model` macro at the bottom of `src/Utilities.model.jl`\n\n## Documentation\n\n - [ ] Add a docstring, which gives the mathematical definition of the set,\n along with an `## Example` block containing a `jldoctest`\n - [ ] Add the docstring to `docs/src/reference/standard_form.md`\n - [ ] Add the set to the relevant table in `docs/src/manual/standard_form.md`\n\n## Tests\n\n - [ ] Define a new `_set(::Type{S})` method in `src/Test/test_basic_constraint.jl`\n and add the name of the set to the list at the bottom of that files\n - [ ] If the set has any checks in its constructor, add tests to `test/sets.jl`\n\n## MathOptFormat\n\n - [ ] Open an issue at `https://github.com/jump-dev/MathOptFormat` to add\n support for the new set {{ replace with link to the issue }}\n\n## Optional\n\n - [ ] Implement `dual_set(::S)` and `dual_set_type(::Type{S})`\n - [ ] Add new tests to the `Test` submodule exercising your new set\n - [ ] Add new bridges to convert your set into more commonly used sets","category":"page"},{"location":"developer/checklists/#Adding-a-new-bridge","page":"Checklists","title":"Adding a new bridge","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when adding a new bridge to the MathOptInterface repository.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"The steps are mostly the same, but locations depend on whether the bridge is a Constraint, Objective, or Variable bridge. In each case below, replace XXX with the appropriate type of bridge.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] Create a new file in `src/Bridges/XXX/bridges`\n - [ ] Define the bridge, following existing examples. The name of the bridge\n struct must end in `Bridge`\n - [ ] Check if your bridge can be a subtype of [`MOI.Bridges.Constraint.SetMapBridge`](@ref)\n - [ ] Define a new `const` that is a `SingleBridgeOptimizer` wrapping the\n new bridge. The name of the const must be the name of the bridge, less\n the `Bridge` suffix\n - [ ] `include` the file in `src/Bridges/XXX/bridges/XXX.jl`\n - [ ] If the bridge should be enabled by default, add the bridge to\n `add_all_bridges` at the bottom of `src/Bridges/XXX/XXX.jl`\n\n## Tests\n\n - [ ] Create a new file in the appropriate subdirectory of `tests/Bridges/XXX`\n - [ ] Use `MOI.Bridges.runtests` to test various inputs and outputs of the\n bridge\n - [ ] If, after opening the pull request to add the bridge, some lines are not\n covered by the tests, add additional bridge-specific tests to cover the\n untested lines.\n\n## Documentation\n\n - [ ] Add a docstring which uses the same template as existing bridges.\n - [ ] Add the docstring to `docs/src/submodules/Bridges/list_of_bridges.md`\n\n## Final touch\n\nIf the bridge depends on run-time values of other variables and constraints in\nthe model:\n\n - [ ] Implement `MOI.Utilities.needs_final_touch(::Bridge)`\n - [ ] Implement `MOI.Utilities.final_touch(::Bridge, ::MOI.ModelLike)`\n - [ ] Ensure that `final_touch` can be called multiple times in a row","category":"page"},{"location":"developer/checklists/#Updating-MathOptFormat","page":"Checklists","title":"Updating MathOptFormat","text":"","category":"section"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"Use this checklist when updating the version of MathOptFormat.","category":"page"},{"location":"developer/checklists/","page":"Checklists","title":"Checklists","text":"## Basic\n\n - [ ] The file at `src/FileFormats/MOF/mof.schema.json` is updated\n - [ ] The constant `_SUPPORTED_VERSIONS` is updated in\n `src/FileFormats/MOF/MOF.jl`\n\n## New sets\n\n - [ ] New sets are added to the `@model` in `src/FileFormats/MOF/MOF.jl`\n - [ ] New sets are added to the `@enum` in `src/FileFormats/MOF/read.jl`\n - [ ] `set_to_moi` is defined for each set in `src/FileFormats/MOF/read.jl`\n - [ ] `head_name` is defined for each set in `src/FileFormats/MOF/write.jl`\n - [ ] A new unit test calling `_test_model_equality` is aded to\n `test/FileFormats/MOF/MOF.jl`\n\n## Tests\n\n - [ ] The version field in `test/FileFormats/MOF/nlp.mof.json` is updated\n\n## Documentation\n\n - [ ] The version fields are updated in `docs/src/submodules/FileFormats/overview.md`","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/standard_form/#Standard-form-problem","page":"Standard form problem","title":"Standard form problem","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"MathOptInterface represents optimization problems in the standard form:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"beginalign\n min_x in mathbbR^n f_0(x)\n \n textst f_i(x) in mathcalS_i i = 1 ldots m\nendalign","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"where:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"the functions f_0 f_1 ldots f_m are specified by AbstractFunction objects\nthe sets mathcalS_1 ldots mathcalS_m are specified by AbstractSet objects","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"tip: Tip\nFor more information on this standard form, read our paper.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"MOI defines some commonly used functions and sets, but the interface is extensible to other sets recognized by the solver.","category":"page"},{"location":"manual/standard_form/#Functions","page":"Standard form problem","title":"Functions","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The function types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Function Description\nVariableIndex x_j, the projection onto a single coordinate defined by a variable index j.\nVectorOfVariables The projection onto multiple coordinates (that is, extracting a sub-vector).\nScalarAffineFunction a^T x + b, where a is a vector and b scalar.\nScalarNonlinearFunction f(x), where f is a nonlinear function.\nVectorAffineFunction A x + b, where A is a matrix and b is a vector.\nScalarQuadraticFunction frac12 x^T Q x + a^T x + b, where Q is a symmetric matrix, a is a vector, and b is a constant.\nVectorQuadraticFunction A vector of scalar-valued quadratic functions.\nVectorNonlinearFunction f(x), where f is a vector-valued nonlinear function.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Extensions for nonlinear programming are present but not yet well documented.","category":"page"},{"location":"manual/standard_form/#One-dimensional-sets","page":"Standard form problem","title":"One-dimensional sets","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The one-dimensional set types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nLessThan(u) (-infty u\nGreaterThan(l) l infty)\nEqualTo(v) v\nInterval(l, u) l u\nInteger() mathbbZ\nZeroOne() 0 1 \nSemicontinuous(l, u) 0 cup l u\nSemiinteger(l, u) 0 cup ll+1ldotsu-1u","category":"page"},{"location":"manual/standard_form/#Vector-cones","page":"Standard form problem","title":"Vector cones","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The vector-valued set types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nReals(d) mathbbR^d\nZeros(d) 0^d\nNonnegatives(d) x in mathbbR^d x ge 0 \nNonpositives(d) x in mathbbR^d x le 0 \nSecondOrderCone(d) (tx) in mathbbR^d t ge lVert x rVert_2 \nRotatedSecondOrderCone(d) (tux) in mathbbR^d 2tu ge lVert x rVert_2^2 t ge 0u ge 0 \nExponentialCone() (xyz) in mathbbR^3 y exp (xy) le z y 0 \nDualExponentialCone() (uvw) in mathbbR^3 -u exp (vu) le exp(1) w u 0 \nGeometricMeanCone(d) (tx) in mathbbR^1+n x ge 0 t le sqrtnx_1 x_2 cdots x_n where n is d - 1\nPowerCone(α) (xyz) in mathbbR^3 x^alpha y^1-alpha ge z x ge 0y ge 0 \nDualPowerCone(α) (uvw) in mathbbR^3 left(fracualpharight)^alphaleft(fracv1-alpharight)^1-alpha ge w uv ge 0 \nNormOneCone(d) (tx) in mathbbR^d t ge sum_i lvert x_i rvert \nNormInfinityCone(d) (tx) in mathbbR^d t ge max_i lvert x_i rvert \nRelativeEntropyCone(d) (u v w) in mathbbR^d u ge sum_i w_i log (fracw_iv_i) v_i ge 0 w_i ge 0 \nHyperRectangle(l, u) x in barmathbbR^d x_i in l_i u_i forall i=1ldotsd\nNormCone(p, d) (tx) in mathbbR^d t ge left(sumlimits_i lvert x_i rvert^pright)^frac1p ","category":"page"},{"location":"manual/standard_form/#Matrix-cones","page":"Standard form problem","title":"Matrix cones","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"The matrix-valued set types implemented in MathOptInterface.jl are:","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nRootDetConeTriangle(d) (tX) in mathbbR^1+d(1+d)2 t le det(X)^1d X mbox is the upper triangle of a PSD matrix \nRootDetConeSquare(d) (tX) in mathbbR^1+d^2 t le det(X)^1d X mbox is a PSD matrix \nPositiveSemidefiniteConeTriangle(d) X in mathbbR^d(d+1)2 X mbox is the upper triangle of a PSD matrix \nPositiveSemidefiniteConeSquare(d) X in mathbbR^d^2 X mbox is a PSD matrix \nLogDetConeTriangle(d) (tuX) in mathbbR^2+d(1+d)2 t le ulog(det(Xu)) X mbox is the upper triangle of a PSD matrix u 0 \nLogDetConeSquare(d) (tuX) in mathbbR^2+d^2 t le u log(det(Xu)) X mbox is a PSD matrix u 0 \nNormSpectralCone(r, c) (t X) in mathbbR^1 + r times c t ge sigma_1(X) X mbox is a rtimes cmbox matrix \nNormNuclearCone(r, c) (t X) in mathbbR^1 + r times c t ge sum_i sigma_i(X) X mbox is a rtimes cmbox matrix \nHermitianPositiveSemidefiniteConeTriangle(d) The cone of Hermitian positive semidefinite matrices, with\nside_dimension rows and columns. \nScaled(S) The set S scaled so that Utilities.set_dot corresponds to LinearAlgebra.dot","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Some of these cones can take two forms: XXXConeTriangle and XXXConeSquare.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"In XXXConeTriangle sets, the matrix is assumed to be symmetric, and the elements are provided by a vector, in which the entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row).","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"In XXXConeSquare sets, the entries of the matrix are given column by column (or equivalently, row by row), and the matrix is constrained to be symmetric. As an example, given a 2-by-2 matrix of variables X and a one-dimensional variable t, we can specify a root-det constraint as [t, X11, X12, X22] ∈ RootDetConeTriangle or [t, X11, X12, X21, X22] ∈ RootDetConeSquare.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"We provide both forms to enable flexibility for solvers who may natively support one or the other. Transformations between XXXConeTriangle and XXXConeSquare are handled by bridges, which removes the chance of conversion mistakes by users or solver developers.","category":"page"},{"location":"manual/standard_form/#Multi-dimensional-sets-with-combinatorial-structure","page":"Standard form problem","title":"Multi-dimensional sets with combinatorial structure","text":"","category":"section"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Other sets are vector-valued, with a particular combinatorial structure. Read their docstrings for more information on how to interpret them.","category":"page"},{"location":"manual/standard_form/","page":"Standard form problem","title":"Standard form problem","text":"Set Description\nSOS1 A Special Ordered Set (SOS) of Type I\nSOS2 A Special Ordered Set (SOS) of Type II\nIndicator A set to specify an indicator constraint\nComplements A set to specify a mixed complementarity constraint\nAllDifferent The all_different global constraint\nBinPacking The bin_packing global constraint\nCircuit The circuit global constraint\nCountAtLeast The at_least global constraint\nCountBelongs The nvalue global constraint\nCountDistinct The distinct global constraint\nCountGreaterThan The count_gt global constraint\nCumulative The cumulative global constraint\nPath The path global constraint\nTable The table global constraint","category":"page"},{"location":"reference/modification/","page":"Modifications","title":"Modifications","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/modification/#Modifications","page":"Modifications","title":"Modifications","text":"","category":"section"},{"location":"reference/modification/","page":"Modifications","title":"Modifications","text":"modify\nAbstractFunctionModification\nScalarConstantChange\nVectorConstantChange\nScalarCoefficientChange\nScalarQuadraticCoefficientChange\nMultirowChange","category":"page"},{"location":"reference/modification/#MathOptInterface.modify","page":"Modifications","title":"MathOptInterface.modify","text":"Constraint Function\n\nmodify(model::ModelLike, ci::ConstraintIndex, change::AbstractFunctionModification)\n\nApply the modification specified by change to the function of constraint ci.\n\nAn ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by the model model.\n\nExamples\n\nmodify(model, ci, ScalarConstantChange(10.0))\n\nObjective Function\n\nmodify(model::ModelLike, ::ObjectiveFunction, change::AbstractFunctionModification)\n\nApply the modification specified by change to the objective function of model. To change the function completely, call set instead.\n\nAn ModifyObjectiveNotAllowed error is thrown if modifying objectives is not supported by the model model.\n\nExamples\n\nmodify(model, ObjectiveFunction{ScalarAffineFunction{Float64}}(), ScalarConstantChange(10.0))\n\nMultiple modifications in Constraint Functions\n\nmodify(\n model::ModelLike,\n cis::AbstractVector{<:ConstraintIndex},\n changes::AbstractVector{<:AbstractFunctionModification},\n)\n\nApply multiple modifications specified by changes to the functions of constraints cis.\n\nA ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by model.\n\nExamples\n\nmodify(\n model,\n [ci, ci],\n [\n ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),\n ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),\n ],\n)\n\nMultiple modifications in the Objective Function\n\nmodify(\n model::ModelLike,\n attr::ObjectiveFunction,\n changes::AbstractVector{<:AbstractFunctionModification},\n)\n\nApply multiple modifications specified by changes to the functions of constraints cis.\n\nA ModifyObjectiveNotAllowed error is thrown if modifying objective coefficients is not supported by model.\n\nExamples\n\nmodify(\n model,\n ObjectiveFunction{ScalarAffineFunction{Float64}}(),\n [\n ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),\n ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),\n ],\n)\n\n\n\n\n\n","category":"function"},{"location":"reference/modification/#MathOptInterface.AbstractFunctionModification","page":"Modifications","title":"MathOptInterface.AbstractFunctionModification","text":"AbstractFunctionModification\n\nAn abstract supertype for structs which specify partial modifications to functions, to be used for making small modifications instead of replacing the functions entirely.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.ScalarConstantChange","page":"Modifications","title":"MathOptInterface.ScalarConstantChange","text":"ScalarConstantChange{T}(new_constant::T)\n\nA struct used to request a change in the constant term of a scalar-valued function.\n\nApplicable to ScalarAffineFunction and ScalarQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.VectorConstantChange","page":"Modifications","title":"MathOptInterface.VectorConstantChange","text":"VectorConstantChange{T}(new_constant::Vector{T})\n\nA struct used to request a change in the constant vector of a vector-valued function.\n\nApplicable to VectorAffineFunction and VectorQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.ScalarCoefficientChange","page":"Modifications","title":"MathOptInterface.ScalarCoefficientChange","text":"ScalarCoefficientChange{T}(variable::VariableIndex, new_coefficient::T)\n\nA struct used to request a change in the linear coefficient of a single variable in a scalar-valued function.\n\nApplicable to ScalarAffineFunction and ScalarQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.ScalarQuadraticCoefficientChange","page":"Modifications","title":"MathOptInterface.ScalarQuadraticCoefficientChange","text":"ScalarQuadraticCoefficientChange{T}(\n variable_1::VariableIndex,\n variable_2::VariableIndex,\n new_coefficient::T,\n)\n\nA struct used to request a change in the quadratic coefficient of a ScalarQuadraticFunction.\n\nScaling factors\n\nA ScalarQuadraticFunction has an implicit 0.5 scaling factor in front of the Q matrix. This modification applies to terms in the Q matrix.\n\nIf variable_1 == variable_2, this modification sets the corresponding diagonal element of the Q matrix to new_coefficient.\n\nIf variable_1 != variable_2, this modification is equivalent to setting both the corresponding upper- and lower-triangular elements of the Q matrix to new_coefficient.\n\nAs a consequence:\n\nto modify the term x^2 to become 2x^2, new_coefficient must be 4\nto modify the term xy to become 2xy, new_coefficient must be 2\n\n\n\n\n\n","category":"type"},{"location":"reference/modification/#MathOptInterface.MultirowChange","page":"Modifications","title":"MathOptInterface.MultirowChange","text":"MultirowChange{T}(\n variable::VariableIndex,\n new_coefficients::Vector{Tuple{Int64,T}},\n) where {T}\n\nA struct used to request a change in the linear coefficients of a single variable in a vector-valued function.\n\nNew coefficients are specified by (output_index, coefficient) tuples.\n\nApplicable to VectorAffineFunction and VectorQuadraticFunction.\n\n\n\n\n\n","category":"type"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"CurrentModule = MathOptInterface","category":"page"},{"location":"changelog/#Release-notes","page":"Release notes","title":"Release notes","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.","category":"page"},{"location":"changelog/#v1.25.2-(January-29,-2024)","page":"Release notes","title":"v1.25.2 (January 29, 2024)","text":"","category":"section"},{"location":"changelog/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed getting ConstraintPrimal if variable bridges are present (#2396)\nFixed modify_function! for ScalarQuadraticCoefficientChange (#2408)\nFixed writing FileFormats.MOF files if ScalarNonlinearFunction contains ScalarAffineFunction or ScalarQuadraticFunction (#2409)","category":"page"},{"location":"changelog/#Other","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Clarified ordering of nonlinear tape in documentation (#2401)\nUpdated vale.sh (#2403) (#2404)\nTidied `src/Utilities/results.jl (#2411)","category":"page"},{"location":"changelog/#v1.25.1-(January-11,-2024)","page":"Release notes","title":"v1.25.1 (January 11, 2024)","text":"","category":"section"},{"location":"changelog/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed map_indices for AbstractAutomaticDifferentiation (#2394)\nFixed deleting a variable in Bridges.Variable.VectorizeBridge (#2393)\nFixed super type of LowerBoundAlreadySet and UpperBoundAlreadySet (#2397)","category":"page"},{"location":"changelog/#Other-2","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Removed a duplicated test (#2395)","category":"page"},{"location":"changelog/#v1.25.0-(January-5,-2024)","page":"Release notes","title":"v1.25.0 (January 5, 2024)","text":"","category":"section"},{"location":"changelog/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added the AutomaticDifferentiationBackend attribute (#2386)","category":"page"},{"location":"changelog/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed initialize for Nonlinear.ExprGraphOnly (#2387)\nFixed converting 0-valued ScalarAffineFunction and ScalarQuadraticFunction to ScalarNonlinearFunction (#2388)\nFixed reading .nl files with non-empty variable and constraint names (#2390)\nFixed reading .nl files with no objective (#2391)\nFixed reading .nl files with free ranged constraints (#2392)","category":"page"},{"location":"changelog/#v1.24.0-(January-2,-2024)","page":"Release notes","title":"v1.24.0 (January 2, 2024)","text":"","category":"section"},{"location":"changelog/#Added-2","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added get_fallback for ConstraintDual of variable bounds (#2373)","category":"page"},{"location":"changelog/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed RSOCtoPSDBridge for dimension 2 (#2359)\nFixed getting ConstraintFunction in conversion bridge (#2360)\nFixed map_indices (#2367)\nFixed SlackBridgePrimalDualStart for non-slack bridges (#2365)\nFixed test_attribute_TimeLimitSec (#2370)\nFixed order of model attributes during copy_to (#2372)\nFixed ConstraintIndex conflicts between variable and constraint bridges (#2362)\nFixed corner-case deletion in bridges (#2377)\nFixed ListOfVariablesWithAttributeSet for variable bridges (#2380)\nFixed SlackBridge if scalar constant is not zero (#2382)\nFixed setting multiple bounds on a bridged variable (#2383)","category":"page"},{"location":"changelog/#Other-3","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Minor documentation improvements (#2355), (#2374)\nImproved side_dimension_for_vectorized_dimension (#2356)\nAdded DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)\nRefactored SDPAModel into a separate test file and test more widely (#2364), (#2357)","category":"page"},{"location":"changelog/#v1.23.0-(November-29,-2023)","page":"Release notes","title":"v1.23.0 (November 29, 2023)","text":"","category":"section"},{"location":"changelog/#Added-3","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added ConstraintPrimalStart for Bridges.Constraint.GeoMeanBridge (#2348)\nAdded verbose keyword argument to Test.runtests (#2347)\nAdded Bridges.FirstBridge attribute (#2211)","category":"page"},{"location":"changelog/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)\nFixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)","category":"page"},{"location":"changelog/#v1.22.0-(November-6,-2023)","page":"Release notes","title":"v1.22.0 (November 6, 2023)","text":"","category":"section"},{"location":"changelog/#Added-4","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new bridges (#2318)\nBridges.Constraint.SOS1ToMILPBridge\nBridges.Constraint.SOS2ToMILPBridge\nBridges.Constraint.IndicatorToMILPBridge\nAdded starting values for bridges (#2330) (#2337) (#2338) (#2339)\nBridges.Constraint.NumberConversionBridge\nBridges.Constraint.SquareBridge\nBridges.Variable.HermitianToSymmetricPSDBridge\nBridges.Variable.ParameterToEqualToBridge\nBridges.Variable.RSOCtoPSDBridge\nAdded ListOfVariablesWithAttributeSet and ListOfConstraintsWithAttributeSet (#2331) (#2342)\nAdded support for printing ConstraintName when models are printed (#2336)","category":"page"},{"location":"changelog/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"ScalarFunctionConstantNotZero errors are now skipped in Test.runtests (#2325)\nFixed VectorNonlinearFunction support in Bridges.Constraint.NormOneBridge and Bridges.Constraint.NormInfinityBridge (#2324)\nFixed various get for ConstraintFunction to return a copy, and added tests (#2328)\nFixed supports of ConstraintPrimalStart and VariablePrimalStart for some bridges (#2340)","category":"page"},{"location":"changelog/#Other-4","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed typo in docstring of ScalarAffineFunction (#2326)\nAdded Gurobi to solver-tests.yml (#2332)\nImproved the error message when a bridge does not support an attribute (#2329)\nImproved documentation for implementing a bridge (#2334)\nUpdated [compat] bounds in Project.toml (#2344)","category":"page"},{"location":"changelog/#v1.21.0-(October-25,-2023)","page":"Release notes","title":"v1.21.0 (October 25, 2023)","text":"","category":"section"},{"location":"changelog/#Added-5","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added SolutionLimit attribute (#2291)\nAdded support for MathOptFormat v1.6 and v1.7 (#2293) (#2298) (#2299) (#2321)\nAdded ScalarQuadraticCoefficientChange (#2296) (#2320) (#2322)\nAdded Utilities.modify_constants (#2300)\nAdded support for is_empty and empty! of Nonlinear.Model (#2305)\nAdded Bridges.Objective.FunctionConversionBridge (#2303)\nAdded Bridges.ModifyBridgeNotAllowed (#2307)\nAdded more sets for Utilities.distance_to_set (#2314)","category":"page"},{"location":"changelog/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed test_attribute_TimeLimitSec (#2256)\nFixed conversion cost in objective bridges (#2309)","category":"page"},{"location":"changelog/#Other-5","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed flakey link checking in documentation (#2297)\nMinor documentation fixes (#2304) (#2313)\nFixed [compat] section of Project.toml (#2310)\nAdded MultiObjectiveAlgorithms to solver-tests.yml (#2312)","category":"page"},{"location":"changelog/#v1.20.1-(September-24,-2023)","page":"Release notes","title":"v1.20.1 (September 24, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-8","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Removed incorrect kwargs in some copy_to methods (#2272)\nFixed ConstraintDualStart for Bridges.Constraint.SplitIntervalBridge (#2275)\nFixed MethodError when trying to modify a variable objective (#2278)\nFixed stack-overflow in Utilities.operate(+,...) with many arguments (#2285) (#2290)","category":"page"},{"location":"changelog/#Other-6","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added MathOptSetDistances to solver-tests.yml (#2265)\nUpdated Documenter (#2266)\nFixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)\nVarious style improvements\nReplaced using Package with import Package where possible (#2274)\nRemoved Utilities.EMPTYSTRING (#2283)\nRemoved unnecessary const acronyms in Utilities (#2280) (#2281)\nRemoved invalid and unused method (#2286)\nRefactored src/Utilities/model.jl (#2287)","category":"page"},{"location":"changelog/#v1.20.0-(September-7,-2023)","page":"Release notes","title":"v1.20.0 (September 7, 2023)","text":"","category":"section"},{"location":"changelog/#Added-6","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Scaled set (#2237) (#2263) (#2264)\nAdded ObjectiveLimit attribute (#2257)","category":"page"},{"location":"changelog/#Other-7","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Updated dependencies (#2258)\nImproved performance of ScalarNonlinearFunction utilities (#2259)\nFixed docstrings (#2261)","category":"page"},{"location":"changelog/#v1.19.0-(August-15,-2023)","page":"Release notes","title":"v1.19.0 (August 15, 2023)","text":"","category":"section"},{"location":"changelog/#Added-7","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added VectorNonlinearFunction (#2201)\nAdded new bridges\nBridges.Constraint.IntegerToZeroOneBridge (#2205)\nBridges.Constraint.ToScalarQuadraticBridge (#2235)\nBridges.Constraint.ToVectorQuadraticBridge (#2235)\nBridges.Constraint.ToScalarNonlinearBridge (#2233) (#2235)\nBridges.Constraint.FunctionConversionBridge (#2235)\nAdded Bridges.bridging_cost for setting a bridge-specific cost in the bridging graph (#2235)\nAdded Utilities.eval_variables support for ScalarNonlinearFunction (#2218) (#2219)\nAdded support for ScalarNonlinearFunction in FileFormats.NL (#2228) (#2231)\nAdded support for writing non-Float64 functions in FileFormats.MOF\nAdded Utilities.lazy_map (#2254)","category":"page"},{"location":"changelog/#Fixed-9","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed method ambiguities in operate (#2224)\nFixed reading LP file with a -infinity <= x <= +infinity variable (#2225)\nFixed missing require in Test.test_nonlinear_duals (#2230)\nFixed bug in ConstraintPrimal of Bridges.Constraint.QuadtoSOCBridge (#2240)","category":"page"},{"location":"changelog/#Other-8","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added extensions to solver-tests.yml (#2229)\nRefactored test/Benchmarks (#2234)\nFixed warnings in tests (#2241) (#2243)\nSmall refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)\nFixed various typos (#2251) (#2255)\nPartitioned how we run the tests on GitHub actions (#2252) (#2253)","category":"page"},{"location":"changelog/#v1.18.0-(June-23,-2023)","page":"Release notes","title":"v1.18.0 (June 23, 2023)","text":"","category":"section"},{"location":"changelog/#Added-8","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.SlackBridgePrimalDualStart (#2194)\nAdded constraint_gradient_structure and eval_constraint_gradient (#2200)","category":"page"},{"location":"changelog/#Fixed-10","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a missing @require in MOI.Test (#2195) (#2196)\nFixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)\nFixed splatting nonlinear expression with univariate operator (#2221)","category":"page"},{"location":"changelog/#Other-9","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Removed unused argument names (#2199)\nReduced memory requirement for tests (#2204)\nRefactored Utilities.promote_operation (#2206)\nImproved code style in Utilities/mutable_arithmetics.jl (#2209)\nRefactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)","category":"page"},{"location":"changelog/#v1.17.1-(June-6,-2023)","page":"Release notes","title":"v1.17.1 (June 6, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-11","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed comparison of ScalarFunctionConstantNotZero (#2190)","category":"page"},{"location":"changelog/#Other-10","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added documentation for enum instances (#2186)\nUpdated chatroom links in documentation (#2188)\nChanged the documentation to build on Julia v1.9 (#2191)","category":"page"},{"location":"changelog/#v1.17.0-(June-1,-2023)","page":"Release notes","title":"v1.17.0 (June 1, 2023)","text":"","category":"section"},{"location":"changelog/#Added-9","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added ScalarNonlinearFunction (#2059)\nAdded a variety of tests for NormSpectralCone, NormNuclearCone, and HermitianPositiveSemidefiniteConeTriangle (#2174)\nAdded Utilities.value_type for computing the value type of a function (#2176)","category":"page"},{"location":"changelog/#Fixed-12","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed support for external sets in Utilities.loadfromstring! (#2177)\nFixed promote_operation for ScalarNonlinearFunction (#2179)\nFixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)","category":"page"},{"location":"changelog/#v1.16.0-(May-16,-2023)","page":"Release notes","title":"v1.16.0 (May 16, 2023)","text":"","category":"section"},{"location":"changelog/#Added-10","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for MathOptFormat v1.3 and v1.4 (#2158) (#2169)\nAdded new method to the nonlinear API (#2162) (#2164)\neval_hessian_constraint\neval_hessian_objective\nhessian_constraint_structure\nhessian_objective_structure\nAdded new sets\nNormCone (#2119)\nScaledPositiveSemidefiniteConeTriangle (#2154)","category":"page"},{"location":"changelog/#Fixed-13","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed support for Julia v1.9 to work around a bug in the upstream Julia compiler (#2161) (#2163)\nFixed a correctness bug in Bridges.Constraint.HermitianToSymmetricPSDBridge (#2171)\nFixed convert(::VariableIndex, ::ScalarAffineFunction) when the function has terms with 0coefficients (#2173)","category":"page"},{"location":"changelog/#Other-11","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed solver-tests.yml (#2157)\nUpdated documentation links to developer chatroom (#2160)\nAdded various tests for bridges (#2156)\nAdded checklists to the developer documentation (#2167) (#2168)","category":"page"},{"location":"changelog/#v1.15.1-(April-25,-2023)","page":"Release notes","title":"v1.15.1 (April 25, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-14","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed deleting a variable in a bridged objective (#2150)","category":"page"},{"location":"changelog/#v1.15.0-(April-19,-2023)","page":"Release notes","title":"v1.15.0 (April 19, 2023)","text":"","category":"section"},{"location":"changelog/#Added-11","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.VectorFunctionizeBridge (#2139)","category":"page"},{"location":"changelog/#Fixed-15","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed support for Rational in Bridges.Constraint.SplitIntervalBridge (#2137)\nFixed printing of LaTeX models (#2141)\nFixed modify in Bridges.Objective.VectorSlackBridge (#2144)\nFixed NAME record with spaces in FileFormats.MPS (#2146)\nFixed deleting a variable in a bridged objective (#2147)","category":"page"},{"location":"changelog/#Other-12","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add a test for variables in one-sided open Interval sets (#2133)\nMinor style fixes in the source code (#2148)","category":"page"},{"location":"changelog/#v1.14.1-(April-6,-2023)","page":"Release notes","title":"v1.14.1 (April 6, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-16","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Bridges.print_active_bridges (#2135)","category":"page"},{"location":"changelog/#Other-13","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added a warning when an ambiguous string is passed to exclude in Test.runtests (#2136)","category":"page"},{"location":"changelog/#v1.14.0-(April-4,-2023)","page":"Release notes","title":"v1.14.0 (April 4, 2023)","text":"","category":"section"},{"location":"changelog/#Added-12","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for starting values in Bridges.Constraint.QuadtoSOCBridge (#2115)\nAdded support for Regex in the include and exclude arguments to Test.runtests (#2129)\nAdded Bridges.print_active_bridges methods for individual objectives and constraints (#2128)","category":"page"},{"location":"changelog/#Fixed-17","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed ResultCount when parsing .sol files in FileFormats.NL (#2130)","category":"page"},{"location":"changelog/#v1.13.2-(March-21,-2023)","page":"Release notes","title":"v1.13.2 (March 21, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-18","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed splatting of containers in MOI.Nonlinear (#2120)\nFixed a bug reading LP files with default bounds (#2121)\nFixed a bug in which Bridges.Constraint.HermitianToSymmetricPSDBridge was not enabled by default (#2123)","category":"page"},{"location":"changelog/#Other-14","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed typos in the documentation (#2114)\nFunctions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)","category":"page"},{"location":"changelog/#v1.13.1-(March-3,-2023)","page":"Release notes","title":"v1.13.1 (March 3, 2023)","text":"","category":"section"},{"location":"changelog/#Other-15","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)\nImproved the docstrings in src/functions.jl (#2108)","category":"page"},{"location":"changelog/#v1.13.0-(February-28,-2023)","page":"Release notes","title":"v1.13.0 (February 28, 2023)","text":"","category":"section"},{"location":"changelog/#Added-13","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.Constraint.NumberConversionBridge (#2091)\nAdded Parameter set (#2095) (#2105) (#2106) (#2109)\nAdded with_cache_type argument to instantiate (#2097)\nAdded support for HermitianPositiveSemidefiniteConeTriangle in Utilities.Model (#2100)","category":"page"},{"location":"changelog/#Fixed-19","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed bug when Utilities.@product_of_sets is empty (#2101)\nFixed Bridges.print_active_bridges when variable bridge is an AbstractScalarSet (#2107)","category":"page"},{"location":"changelog/#Other-16","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added tests for vector-valued objective functions in FileFormats.MOF (#2093)\nUsed and documented preference for import MathOptInterface as MOI (#2096)\nFix and test links in the documentation with linkcheck = true (#2098)\nImproved docstrings of sets in src/sets.jl (#2099)\nSkip checking flakey links in documentation with linkcheck_ignore (#2103)","category":"page"},{"location":"changelog/#v1.12.0-(February-10,-2023)","page":"Release notes","title":"v1.12.0 (February 10, 2023)","text":"","category":"section"},{"location":"changelog/#Added-14","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for vector-valued objective functions (#2070)\nAdded a Utilities.distance_to_set method for SecondOrderCone (#2060)","category":"page"},{"location":"changelog/#Fixed-20","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)","category":"page"},{"location":"changelog/#Other-17","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new tests that a set ObjectiveFunction appears in ListOfModelAttributesSet (#2085)\nImproved the docstrings of a number of constraint-programming related sets (#2087)","category":"page"},{"location":"changelog/#v1.11.5-(January-24,-2023)","page":"Release notes","title":"v1.11.5 (January 24, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-21","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)","category":"page"},{"location":"changelog/#Other-18","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)","category":"page"},{"location":"changelog/#v1.11.4-(January-12,-2023)","page":"Release notes","title":"v1.11.4 (January 12, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-22","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .lp files with an Integer section (#2078)","category":"page"},{"location":"changelog/#v1.11.3-(January-12,-2023)","page":"Release notes","title":"v1.11.3 (January 12, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-23","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a performance bug when deleting a vector of constraints (#2072)\nFixed a bug reading .lp files with terms like x -1 y (#2076)","category":"page"},{"location":"changelog/#Other-19","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Documented the two-argument method of optimize! (#2074)","category":"page"},{"location":"changelog/#v1.11.2-(January-2,-2023)","page":"Release notes","title":"v1.11.2 (January 2, 2023)","text":"","category":"section"},{"location":"changelog/#Fixed-24","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)\nFixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)","category":"page"},{"location":"changelog/#v1.11.1-(December-22,-2022)","page":"Release notes","title":"v1.11.1 (December 22, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-25","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)","category":"page"},{"location":"changelog/#v1.11.0-(December-2,-2022)","page":"Release notes","title":"v1.11.0 (December 2, 2022)","text":"","category":"section"},{"location":"changelog/#Added-15","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Utilities.PenaltyRelaxation and Utilities.ScalarPenaltyRelaxation (#1995)\nAdded Utilities.distance_to_set (#2048)\nAdded support for ConstraintPrimalStart and ConstraintDualStart in FileFormats.MOF (#2056)","category":"page"},{"location":"changelog/#Other-20","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Tidied these release notes (#2055)","category":"page"},{"location":"changelog/#v1.10.0-(November-22,-2022)","page":"Release notes","title":"v1.10.0 (November 22, 2022)","text":"","category":"section"},{"location":"changelog/#Added-16","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new methods set(::OptimizerWithAttributes, ::RawOptimizerAttribute, value) and get(::OptimizerWithAttributes, ::RawOptimizerAttribute) (#2049)\nAdded new methods Utilities.DoubleDicts.outer_keys and Utilities.DoubleDicts.nonempty_outer_keys (#2052)","category":"page"},{"location":"changelog/#Fixed-26","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)\nFixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)\nFixed reading of free variables in FileFormats.LP (#2044)\nFixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)\nFixed situations in which x^y returns a complex value in Nonlinear (#2050)","category":"page"},{"location":"changelog/#Other-21","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)\nRemoved specialized iterators for keys and values in Utilities.CleverDicts (#2051)","category":"page"},{"location":"changelog/#v1.9.0-(October-29,-2022)","page":"Release notes","title":"v1.9.0 (October 29, 2022)","text":"","category":"section"},{"location":"changelog/#Added-17","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added default fallback for getting ListOfConstraintIndices and NumberOfConstraints when the constraint type is unsupported by the model (#2021)\nAdded support for min and max in nonlinear expressions (#2023)\nAdded support for Indicator{EqualTo{T}} constraints in FileFormats.MPS (#2022)\nAdded default fallback for write_to_file and read_from_file (#2029)","category":"page"},{"location":"changelog/#Fixed-27","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)\nFixed reading free rows in FileFormats.MPS files (#2009)\nFixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)\nFixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)\nFixed the requirements check in Test.test_constraint_get_ConstraintIndex (#2024)","category":"page"},{"location":"changelog/#v1.8.2-(September-20,-2022)","page":"Release notes","title":"v1.8.2 (September 20, 2022)","text":"","category":"section"},{"location":"changelog/#Documentation","page":"Release notes","title":"Documentation","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added vale as a documentation linter (#2002)\nImproved styling of code blocks in the PDF (#1999) (#2000)\nFixed a number of typos in the documentation (#2001) (#2003)","category":"page"},{"location":"changelog/#v1.8.1-(September-12,-2022)","page":"Release notes","title":"v1.8.1 (September 12, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-28","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)","category":"page"},{"location":"changelog/#v1.8.0-(September-1,-2022)","page":"Release notes","title":"v1.8.0 (September 1, 2022)","text":"","category":"section"},{"location":"changelog/#Added-18","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new sets\nHyperRectangle (#1961)\nReified (#1955)\nAdded new bridges (#1955)\nBridges.Constraint.ReifiedAllDifferentToCountDistinctBridge\nBridges.Constraint.ReifiedCountDistinctToMILPBridge\nBridges.Constraint.SplitHyperRectangleBridge\nAdded support for atan(y, x) in Nonlinear (#1987)","category":"page"},{"location":"changelog/#Fixed-29","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)\nAllow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)","category":"page"},{"location":"changelog/#v1.7.0-(August-16,-2022)","page":"Release notes","title":"v1.7.0 (August 16, 2022)","text":"","category":"section"},{"location":"changelog/#Added-19","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new sets\nHermitianPositiveSemidefiniteConeTriangle\nAdded new optimizer-independent options\nRelativeGapTolerance\nAbsoluteGapTolerance\nAdded new bridges\nBridges.Constraint.GeoMeanToPowerBridge\nBridges.Constraint.HermitianToSymmetricPSDBridge\nBridges.Constraint.IndicatorGreaterToLessThanBridge\nBridges.Constraint.IndicatorLessToGreaterThanBridge\nBridges.Constraint.SplitComplexZerosBridge\nBridges.Constraint.SplitComplexEqualToBridge\nBridges.Objective.QuadratizeBridge\nAdded support for generic number types in Utilities.loadfromstring!\nUpdated FileFormats.MOF to MathOptFormat v1.1, enabling support for constraint programming sets in the MOF file format\nAdded support in various FileFormats for\nindicator constraints in FileFormats.MPS\nquadratic constraints and an objective in FileFormats.LP\nquadratic constraints and an objective in FileFormats.MPS","category":"page"},{"location":"changelog/#Fixed-30","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed some missing promotion rules","category":"page"},{"location":"changelog/#Other-22","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved the performance of Jacobian products in Nonlinear\nRemoved an un-needed copy in Utilities.modify_function\nVarious clean-ups in Bridges/bridge_optimizer.jl","category":"page"},{"location":"changelog/#v1.6.1-(July-23,-2022)","page":"Release notes","title":"v1.6.1 (July 23, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-31","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added support for ExponentialCone in MatrixOfConstraints\nFix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint","category":"page"},{"location":"changelog/#v1.6.0-(July-2,-2022)","page":"Release notes","title":"v1.6.0 (July 2, 2022)","text":"","category":"section"},{"location":"changelog/#Added-20","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Bridges.needs_final_touch and Bridges.final_touch\nAdded new bridges from constraint programming sets to mixed-integer linear programs:\nAllDifferentToCountDistinctBridge\nCountAtLeastToCountBelongsBridge\nCountBelongsToMILPBridge\nCountDistinctToMILPBridge\nCountGreaterThanToMILPBridge\nCircuitToMILPBridge","category":"page"},{"location":"changelog/#Fixed-32","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear\nFix BinPackingToMILPBridge to respect variable bounds\nFix SemiToBinaryBridge to throw error if other bounds are set","category":"page"},{"location":"changelog/#v1.5.0-(June-27,-2022)","page":"Release notes","title":"v1.5.0 (June 27, 2022)","text":"","category":"section"},{"location":"changelog/#Added-21","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error\nAdded Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue\nAdded new bridges:\nRootDetConeSquare to RootDetConeTriangle\nLogDetConeSquare to LogDetConeTriangle\nBinPacking to a mixed-integer linear program\nTable to a mixed-integer linear program\nAdded Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer","category":"page"},{"location":"changelog/#Fixed-33","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed ZeroOne tests with lower and upper bounds\nFixed error in FileFormats.LP when reading a malformed file\nFixed reading of nonlinear programs in FileFormats.MOF\nFixed bug in ConstraintDual when using SquareBridge","category":"page"},{"location":"changelog/#Other-23","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved documentation of nonlinear API\nDocumented duality convention for PositiveSemidefiniteConeSquare sets\nFixed typo in Bridges.Constraint.QuadToSOCBridge docstring","category":"page"},{"location":"changelog/#v1.4.0-(June-9,-2022)","page":"Release notes","title":"v1.4.0 (June 9, 2022)","text":"","category":"section"},{"location":"changelog/#Added-22","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added a number of sets for constraint programming:\nAllDifferent\nBinPacking\nCircuit\nCountAtLeast\nCountBelongs\nCountDistinct\nCountGreaterThan\nCumulative\nPath\nTable\nAdded support for user-defined hessians in Nonlinear\nAdded Bridges.runtests to simplify the testing of bridge implementations","category":"page"},{"location":"changelog/#Fixed-34","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in FileFormats.NL when writing univariate *","category":"page"},{"location":"changelog/#Other-24","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Began a large refactoring of the Bridges submodule, with greatly improved documentation.","category":"page"},{"location":"changelog/#v1.3.0-(May-27,-2022)","page":"Release notes","title":"v1.3.0 (May 27, 2022)","text":"","category":"section"},{"location":"changelog/#Added-23","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.\nAdd FileFormats.NL.SolFileResults(::IO, ::Model)\nAdd FileFormats.NL.read!(::IO, ::Model)\nAdd MOI.modify that accepts a vector of modifications","category":"page"},{"location":"changelog/#Fixed-35","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Test which attempted to include non-.jl files\nFixed a bug in FileFormats for models with open interval constraints","category":"page"},{"location":"changelog/#Other-25","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a performance issue in Utilities.DoubleDict\nVarious minor improvements to the documentation","category":"page"},{"location":"changelog/#v1.2.0-(April-25,-2022)","page":"Release notes","title":"v1.2.0 (April 25, 2022)","text":"","category":"section"},{"location":"changelog/#Added-24","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add support for the FORMAT_REW/.rew file format in FileFormats.","category":"page"},{"location":"changelog/#Fixed-36","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix bug handling of default variable bounds in FileFormats.LP\nFix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.","category":"page"},{"location":"changelog/#v1.1.2-(March-31,-2022)","page":"Release notes","title":"v1.1.2 (March 31, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-37","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix a range of bugs in FileFormats.LP\nFix reading of problem dimensions in FileFormats.SDPA","category":"page"},{"location":"changelog/#v1.1.1-(March-23,-2022)","page":"Release notes","title":"v1.1.1 (March 23, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-38","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix bug in test_model_UpperBoundAlreadySet\nFix bug in test_infeasible_ tests\nFix bug in test_objective_ObjectiveFunction_blank\nRelax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.","category":"page"},{"location":"changelog/#New-tests","page":"Release notes","title":"New tests","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add test_conic_empty_matrix that checks conic solvers support problems with no variables.","category":"page"},{"location":"changelog/#v1.1.0-(March-2,-2022)","page":"Release notes","title":"v1.1.0 (March 2, 2022)","text":"","category":"section"},{"location":"changelog/#Added-25","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.","category":"page"},{"location":"changelog/#v1.0.2-(March-1,-2022)","page":"Release notes","title":"v1.0.2 (March 1, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-39","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in the test_model_ScalarFunctionConstantNotZero test\nFixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute\nIdentified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.","category":"page"},{"location":"changelog/#v1.0.1-(February-25,-2022)","page":"Release notes","title":"v1.0.1 (February 25, 2022)","text":"","category":"section"},{"location":"changelog/#Fixed-40","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer\nFixed a bug in which shift_constant did not promote mixed types of coefficients\nFixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed\nFixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function\nFixed a bug when modifying scalar constants of a function containing a bridged variable\nFixed a bug in which final_touch was not always called with a CachingOptimizer","category":"page"},{"location":"changelog/#v1.0.0-(February-17,-2022)","page":"Release notes","title":"v1.0.0 (February 17, 2022)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.","category":"page"},{"location":"changelog/#Breaking","page":"Release notes","title":"Breaking","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Julia 1.6 is now the minimum supported version\nAll deprecations have been removed","category":"page"},{"location":"changelog/#Troubleshooting-problems-when-updating","page":"Release notes","title":"Troubleshooting problems when updating","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"To find the deprecated features you are using, start Julia with --depwarn=yes:","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"$ julia --depwarn=yes","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Then install MathOptInterface v0.10.9:","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"julia> using Pkg\njulia> pkg\"add MathOptInterface@0.10\"","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.","category":"page"},{"location":"changelog/#v0.10.9-(February-16,-2022)","page":"Release notes","title":"v0.10.9 (February 16, 2022)","text":"","category":"section"},{"location":"changelog/#Added-26","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers\nAdded MOI.default_cache for specifying the model used in CachingOptimizer","category":"page"},{"location":"changelog/#Fixed-41","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed LaTeX printing of MOI.Interval sets","category":"page"},{"location":"changelog/#Other-26","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added Aqua.jl as a CI check, and fixed suggested issues\nThe constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.","category":"page"},{"location":"changelog/#v0.10.8-(February-3,-2022)","page":"Release notes","title":"v0.10.8 (February 3, 2022)","text":"","category":"section"},{"location":"changelog/#Added-27","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added a Base.read! for FileFormats.LP.","category":"page"},{"location":"changelog/#Fixed-42","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a bug in MutableSparseMatrix\nFixed a bug when calling operate!(vcat, ...) with Number arguments\nRemoved unintended export of deprecated symbols\nFixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.","category":"page"},{"location":"changelog/#v0.10.7-(January-5,-2022)","page":"Release notes","title":"v0.10.7 (January 5, 2022)","text":"","category":"section"},{"location":"changelog/#Added-28","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.","category":"page"},{"location":"changelog/#Fixed-43","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.\nFixed an error message in FileFormats.CBF\nFixed comparison in test_linear_integration_Interval\nFixed errors for ConstraintPrimal in a CachingOptimizer\nFixed printing of models with non-Float64 coefficients.","category":"page"},{"location":"changelog/#Other-27","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various improvements to reduce time-to-first-solve latency\nImproved error message when an optimizer does not support compute_conflict!","category":"page"},{"location":"changelog/#v0.10.6-(November-30,-2021)","page":"Release notes","title":"v0.10.6 (November 30, 2021)","text":"","category":"section"},{"location":"changelog/#Added-29","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added new documentation and tests for infeasibility certificates\nAdded a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v\"0.10.5\" to run tests added in v0.10.5 and earlier.\nMOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).\nAdded infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE\nCachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.","category":"page"},{"location":"changelog/#Fixed-44","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed a StackOverflow bug in copy_to\nFixed error thrown when nonconvex quadratic constraints cannot be bridged\nFixed a bug in copy_to for FileFormats.NL.Model\nFixed a bug in FileFormats.NL when printing large integers\nRemove a common test failure for LowerBoundAlreadySet tests\nUtilities.num_rows is now exported\nRemove parts of failing test_model_copy_to_xxx tests due to bridges","category":"page"},{"location":"changelog/#v0.10.5-(November-7,-2021)","page":"Release notes","title":"v0.10.5 (November 7, 2021)","text":"","category":"section"},{"location":"changelog/#Fixed-45","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed getter in UniversalFallback\nFixed test_solve_conflict_zeroone_ii","category":"page"},{"location":"changelog/#Other-28","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Make normalize_and_add_constraint more flexible\nUpdate paper BibTeX","category":"page"},{"location":"changelog/#v0.10.4-(October-26,-2021)","page":"Release notes","title":"v0.10.4 (October 26, 2021)","text":"","category":"section"},{"location":"changelog/#Added-30","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add SolverVersion attribute\nAdd new tests:\ntest_solve_conflict_zeroone_ii\ntest_nonlinear_objective\nUtilities.VariablesContainer now supports ConstraintFunction and ConstraintSet\nThe documentation is now available as a PDF","category":"page"},{"location":"changelog/#Other-29","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Update to MutableArithmetics 0.3\nVarious improvements to the documentation","category":"page"},{"location":"changelog/#v0.10.3-(September-18,-2021)","page":"Release notes","title":"v0.10.3 (September 18, 2021)","text":"","category":"section"},{"location":"changelog/#Fixed-46","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed bug which prevented callbacks from working through a CachingOptimizer\nFixed bug in Test submodule","category":"page"},{"location":"changelog/#v0.10.2-(September-16,-2021)","page":"Release notes","title":"v0.10.2 (September 16, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Updated MathOptFormat to v1.0\nUpdated JSONSchema to v1.0\nAdded Utilities.set_with_dimension\nAdded two-argument optimize!(::AbstractOptimizer, ::ModelLike)\nThe experimental feature copy_to_and_optimize! has been removed\nDet bridges now support getting ConstraintFunction and ConstraintSet\nVarious minor bug fixes identified by improved testing","category":"page"},{"location":"changelog/#v0.10.1-(September-8,-2021)","page":"Release notes","title":"v0.10.1 (September 8, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various fixes to MOI.Test","category":"page"},{"location":"changelog/#v0.10.0-(September-6,-2021)","page":"Release notes","title":"v0.10.0 (September 6, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.","category":"page"},{"location":"changelog/#Breaking-in-MOI","page":"Release notes","title":"Breaking in MOI","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"SingleVariable has been removed; use VariableIndex instead\nSingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError\nSettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed\nVariableIndex constraints should not support ConstraintName\nVariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead\nListOfConstraints has been renamed to ListOfConstraintTypesPresent\nListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}\nSolveTime has been renamed to SolveTimeSec\nIndicatorSet has been renamed to Indicator\nRawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument\nThe .N field in result attributes has been renamed to .result_index\nThe .variable_index field in ScalarAffineTerm has been renamed to .variable\nThe .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1\nThe .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2\nThe order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.\nThe index_value function has been removed. Use .value instead.\nisapprox has been removed for SOS1 and SOS2.\nThe dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.\ncopy_to no longer takes keyword arguments:\ncopy_names: now copy names if they are supported by the destination solver\nfilter_constraints: use Utilities.ModelFilter instead\nwarn_attributes: never warn about optimizer attributes","category":"page"},{"location":"changelog/#Breaking-in-Bridges","page":"Release notes","title":"Breaking in Bridges","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge\nConstraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge\nBridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.\nBridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges\nThe signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).","category":"page"},{"location":"changelog/#Breaking-in-FileFormats","page":"Release notes","title":"Breaking in FileFormats","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.","category":"page"},{"location":"changelog/#Breaking-in-Utilities","page":"Release notes","title":"Breaking in Utilities","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.\nUtilities.supports_default_copy has been renamed to supports_incremental_interface\nUtilities.automatic_copy_to has been renamed to Utilities.default_copy_to\nThe allocate-load API has been removed\nCachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.\nThe field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.\nThe size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.\nThe size argument to Utilities.IndexMap(::Integer) has been removed.\nUtilities.DoubleDicts have been significantly refactored. Consult the source code for details.\nUtilities.test_models_equal has been moved to MOI.Test","category":"page"},{"location":"changelog/#Breaking-in-Test","page":"Release notes","title":"Breaking in Test","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"MOI.Test has been renamed to MOI.DeprecatedTest\nAn entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.","category":"page"},{"location":"changelog/#Other-changes:","page":"Release notes","title":"Other changes:","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"attribute_value_type has been added\ncopy_to_and_optimize! has been added\nVariableBasisStatus has been added\nprint(model) now prints a human-readable description of the model\nVarious improvements to the FileFormats submodule\nFileFormats.CBF was refactored and received bugfixes\nSupport for MathOptFormat v0.6 was added in FileFormats.MOF\nFileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.\nFileFormats.NL has been added to support nonlinear files\nImproved type inference throughout to reduce latency","category":"page"},{"location":"changelog/#Updating","page":"Release notes","title":"Updating","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"A helpful script when updating is:","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"for (root, dirs, files) in walkdir(\".\")\n for file in files\n if !endswith(file, \".jl\")\n continue\n end\n path = joinpath(root, file)\n s = read(path, String)\n for pair in [\n \".variable_index\" => \".variable\",\n \"RawParameter\" => \"RawOptimizerAttribute\",\n \"ListOfConstraints\" => \"ListOfConstraintTypesPresent\",\n \"TestConfig\" => \"Config\",\n \"attr.N\" => \"attr.result_index\",\n \"SolveTime\" => \"SolveTimeSec\",\n \"DataType\" => \"Type\",\n \"Utilities.supports_default_copy_to\" =>\n \"supports_incremental_interface\",\n \"SingleVariableConstraintNameError\" =>\n \"VariableIndexConstraintNameError\",\n \"SettingSingleVariableFunctionNotAllowed\" =>\n \"SettingVariableIndexFunctionNotAllowed\",\n \"automatic_copy_to\" => \"default_copy_to\",\n ]\n s = replace(s, pair)\n end\n write(path, s)\n end\nend","category":"page"},{"location":"changelog/#v0.9.22-(May-22,-2021)","page":"Release notes","title":"v0.9.22 (May 22, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"This release contains backports from the ongoing development of the v0.10 release.","category":"page"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.\nImproved performance of Utilities.is_canonical.\nFixed Utilities.pass_nonvariable_constraints with bridged variables.\nFixed performance regression of Utilities.Model.\nFixed ordering of objective setting in parser.","category":"page"},{"location":"changelog/#v0.9.21-(April-23,-2021)","page":"Release notes","title":"v0.9.21 (April 23, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added supports_shift_constant.\nImprove performance of bridging quadratic constraints.\nAdd precompilation statements.\nLarge improvements to the documentation.\nFix a variety of inference issues, benefiting precompilation and reducing initial latency.\nRawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.\nUtilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.","category":"page"},{"location":"changelog/#v0.9.20-(February-20,-2021)","page":"Release notes","title":"v0.9.20 (February 20, 2021)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improved performance of Utilities.ScalarFunctionIterator\nAdded support for compute_conflict to MOI layers\nAdded test with zero off-diagonal quadratic term in objective\nFixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints\nFixed modification of un-set objective\nFixed function modification with duplicate terms\nMade unit tests abort without failing if the problem class is not supported\nFormatted code with JuliaFormatter\nClarified BasisStatusCode's docstring","category":"page"},{"location":"changelog/#v0.9.19-(December-1,-2020)","page":"Release notes","title":"v0.9.19 (December 1, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added CallbackNodeStatus attribute\nAdded bridge from GreaterThan or LessThan to Interval\nAdded tests for infeasibility certificates and double optimize\nFixed support for Julia v1.6\nRe-organized MOI docs and added documentation for adding a test","category":"page"},{"location":"changelog/#v0.9.18-(November-3,-2020)","page":"Release notes","title":"v0.9.18 (November 3, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various improvements for working with complex numbers\nAdded GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint","category":"page"},{"location":"changelog/#v0.9.17-(September-21,-2020)","page":"Release notes","title":"v0.9.17 (September 21, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed CleverDict with variable of negative index value\nImplement supports_add_constrained_variable for MockOptimizer","category":"page"},{"location":"changelog/#v0.9.16-(September-17,-2020)","page":"Release notes","title":"v0.9.16 (September 17, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Various fixes:\n32-bit support\nCleverDict with abstract value type\nChecks in test suite","category":"page"},{"location":"changelog/#v0.9.15-(September-14,-2020)","page":"Release notes","title":"v0.9.15 (September 14, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Bridges improvements:\n(R)SOCtoNonConvexQuad bridge\nZeroOne bridge\nUse supports_add_constrained_variable in LazyBridgeOptimizer\nExposed VariableBridgeCost and ConstraintBridgeCost attributes\nPrioritize constraining variables on creation according to these costs\nRefactor bridge debugging\nLarge performance improvements across all submodules\nLots of documentation improvements\nFileFormats improvements:\nUpdate MathOptFormat to v0.5\nFix supported objectives in FileFormats\nTesting improvements:\nAdd name option for basic_constraint_test\nBug fixes and missing methods\nAdd length for iterators\nFix bug with duplicate terms\nFix order of LinearOfConstraintIndices","category":"page"},{"location":"changelog/#v0.9.14-(May-30,-2020)","page":"Release notes","title":"v0.9.14 (May 30, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).\nBump JSONSchema dependency from v0.2 to v0.3 (#1090).\nDocumentation improvements:\nFix typos (#1054, #1060, #1061, #1064, #1069, #1070).\nRemove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).\nUtilities improvements:\nFix is_canonical for quadratic functions (#1081, #1089).\nImplement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).\nAdd support for custom objective functions for UniversalFallback (#1086).\nDeterministic ordering of constraints in UniversalFallback (#1088).\nTesting improvements:\nAdd NormOneCone/NormInfinityCone tests (#1045).\nBridges improvements:\nAdd bridges from Semiinteger and Semicontinuous (#1059).\nImplement getting ConstraintSet for Variable.FlipSignBridge (#1066).\nFix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).\nFix NormOne/NormInf bridges with nonzero constants (#1045).\nFix StackOverflow in debug (#1063).\nFileFormats improvements:\n[SDPA] Implement the extension for integer variables (#1079).\n[SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).\n[SDPA] No scaling of off-diagonal coefficient (#1076).\n[SDPA] Add missing negation of constant (#1075).","category":"page"},{"location":"changelog/#v0.9.13-(March-24,-2020)","page":"Release notes","title":"v0.9.13 (March 24, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added tests for Semicontinuous and Semiinteger variables (#1033).\nAdded tests for using ExprGraphs from NLP evaluators (#1043).\nUpdate version compatibilities of dependencies (#1034, #1051, #1052).\nFixed typos in documentation (#1044).","category":"page"},{"location":"changelog/#v0.9.12-(February-28,-2020)","page":"Release notes","title":"v0.9.12 (February 28, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed writing NLPBlock in MathOptFormat (#1037).\nFixed MockOptimizer for result attributes with non-one result index (#1039).\nUpdated test template with instantiate (#1032).","category":"page"},{"location":"changelog/#v0.9.11-(February-21,-2020)","page":"Release notes","title":"v0.9.11 (February 21, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).\nDescribed dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).\nFixed typos in documentation (#1022, #1024).\nFixed warning of unsupported attribute (#1027).\nAdded more rootdet/logdet conic tests (#1026).\nImplemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).","category":"page"},{"location":"changelog/#v0.9.10-(January-31,-2020)","page":"Release notes","title":"v0.9.10 (January 31, 2020)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).\nAdded RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).\nAdded NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).\nAdded supports_constrained_variable(s) (#1004).\nAdded dual_set_type (#1002).\nAdded tests for vector specialized version of delete (#989, #1011).\nAdded PSD3 test (#1007).\nClarified dual solution of Tests.pow1v and Tests.pow1f (#1013).\nAdded support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).\nFixed Utilities.vectorize for empty vector (#1003).\nFixed free variables in LP writer (#1006).","category":"page"},{"location":"changelog/#v0.9.9-(December-29,-2019)","page":"Release notes","title":"v0.9.9 (December 29, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).\nImproved performance of deletion of vector of variables in MOI.Utilities.Model (#983).\nUpdated to MutableArithmetics v0.2 (#981).\nAdded MutableArithmetics.promote_operation allocation tests (#975).\nFixed inference issue on Julia v1.1 (#982).","category":"page"},{"location":"changelog/#v0.9.8-(December-19,-2019)","page":"Release notes","title":"v0.9.8 (December 19, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Implemented MutableArithmetics API (#924).\nFixed callbacks with CachingOptimizer (#959).\nFixed MOI.dimension for MOI.Complements (#948).\nAdded fallback for add_variables (#972).\nAdded is_diagonal_vectorized_index utility (#965).\nImproved linear constraints display in manual (#963, #964).\nBridges improvements:\nAdded IndicatorSet to SOS1 bridge (#877).\nAdded support for starting values for Variable.VectorizeBridge (#944).\nFixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).\nFixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).\nFixed choice between variable or constraint bridges for constrained variables (#973).\nImprove performance of bridge shortest path (#945, #946, #956).\nAdded docstring for test_delete_bridge (#954).\nAdded Variable bridge tests (#952).","category":"page"},{"location":"changelog/#v0.9.7-(October-30,-2019)","page":"Release notes","title":"v0.9.7 (October 30, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Implemented _result_index_field for NLPBlockDual (#934).\nFixed copy of model with starting values for vector constraints (#941).\nBridges improvements:\nImproved performance of add_bridge and added has_bridge (#935).\nAdded AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).\nAdded support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).","category":"page"},{"location":"changelog/#v0.9.6-(October-25,-2019)","page":"Release notes","title":"v0.9.6 (October 25, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added complementarity constraints (#913).\nAllowed ModelLike objects as value of attributes (#928).\nTesting improvements:\nAdded dual_objective_value option to MOI.Test.TestConfig (#922).\nAdded InvalidIndex tests in basic_constraint_tests (#921).\nAdded tests for the constant term in indicator constraint (#929).\nBridges improvements:\nAdded support for starting values for Functionize bridges (#923).\nAdded variable indices context to variable bridges (#920).\nFixed a typo in printing o debug_supports (#927).","category":"page"},{"location":"changelog/#v0.9.5-(October-9,-2019)","page":"Release notes","title":"v0.9.5 (October 9, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).\nAdded tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).\nUse 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).\nBridges improvements:\nAdded debug utilities for unsupported variable/constraint/objective (#861).\nFixed deletion of variables in bridged VectorOfVariables constraints (#909).\nFixed result_index with objective bridges (#911).","category":"page"},{"location":"changelog/#v0.9.4-(October-2,-2019)","page":"Release notes","title":"v0.9.4 (October 2, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Added solver-independent MIP callbacks (#782).\nImplements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).\nAdded tests for result count of solution attributes (#901, #904).\nAdded NumberOfThreads attribute (#892).\nAdded Utilities.get_bounds to get the bounds on a variable (#890).\nAdded a note on duplicate coefficients in documentation (#581).\nAdded result index in ConstraintBasisStatus (#898).\nAdded extension dictionary to Utilities.Model (#884, #895).\nFixed deletion of constrained variables for CachingOptimizer (#905).\nImplemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).\nBridges improvements:\nAdded Variable.RSOCtoSOCBridge (#907).\nImplemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).","category":"page"},{"location":"changelog/#v0.9.3-(September-20,-2019)","page":"Release notes","title":"v0.9.3 (September 20, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixed ambiguity detected in Julia v1.3 (#891, #893).\nFixed missing sets from ListOfSupportedConstraints (#880).\nFixed copy of VectorOfVariables constraints with duplicate indices (#886).\nAdded extension dictionary to MOIU.Model (#884).\nImplemented MOI.get for function and set for GeoMeanBridge (#888).\nUpdated documentation for SingleVariable indices and bridges (#885).\nTesting improvements:\nAdded more comprehensive tests for names (#882).\nAdded tests for SingleVariable duals (#883).\nAdded tests for DualExponentialCone and DualPowerCone (#873).\nImprovements for arbitrary coefficient type:\nFixed == for sets with mutable fields (#887).\nRemoved some Float64 assumptions in bridges (#878).\nAutomatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).","category":"page"},{"location":"changelog/#v0.9.2-(September-5,-2019)","page":"Release notes","title":"v0.9.2 (September 5, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).\nGeneralized contlinear tests for arbitrary coefficient type (#855).\nFixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).\nFixed Allocate-Load copy for single variable constraints (#856).\nBridges improvements:\nAdd objective bridges (#789).\nFixed Variable.RSOCtoPSDBridge for dimension 2 (#869).\nAdded Variable.SOCtoRSOCBridge (#865).\nAdded Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).\nFixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).","category":"page"},{"location":"changelog/#v0.9.1-(August-22,-2019)","page":"Release notes","title":"v0.9.1 (August 22, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix support for Julia v1.2 (#834).\nL1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).\nAdded tests to MOI.Test.nametest (#833).\nFix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).\nImplements operate for operators * and / between vector function and constant (#837).\nImplements show for MOI.Utilities.IndexMap (#847).\nFix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).\nFix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).","category":"page"},{"location":"changelog/#v0.9.0-(August-13,-2019)","page":"Release notes","title":"v0.9.0 (August 13, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Support for Julia v0.6 and v0.7 was dropped (#714, #717).\nA MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).\nadd_constrained_variable and add_constrained_variables were added (#759).\nSupport for indicator constraints was added (#709, #712).\nDualObjectiveValue attribute was added (#473).\nRawParameter attribute was added (#733).\nA dual_set function was added (#804).\nA Benchmarks submodule was added to facilitate solver benchmarking (#769).\nA submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).\nThe field of ObjectiveValue was renamed to result_index (#729).\nThe _constant and Utilities.getconstant function were renamed to constant\nREDUCTION_CERTIFICATE result status was added (#734).\nAbstract matrix sets were added (#731).\nTesting improvements:\nThe testing guideline was updated (#728).\nQuadratic tests were added (#697).\nUnit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).\nA rotated second-order cone test was added (#759).\nA power cone test was added (#768).\nTests for ZeroOne variables with variable bounds were added (#772).\nAn unbounded test was added (#773).\nExisting tests had a few updates (#702, #703, #763).\nDocumentation improvements:\nAdded a section on CachingOptimizer (#777).\nAdded a section on UniversalFallback, Model and @model (#762).\nTransition the knapsack example to a doctest with MockOptimizer (#786).\nUtilities improvements:\nA CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).\nThe Utilities.constant function was renamed to Utilities.constant_vector (#740).\nImplement optimizer attributes for CachingOptimizer (#745).\nRename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).\noperate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).\nFix a type piracy of operate (#784).\nThe load_constraint fallback signature was fixed (#760).\nThe set_dot function was extended to work with sparse arrays (#805).\nBridges improvements:\nThe bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).\nBridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).\nFix constraint attributes for bridges (#699).\nConstraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).\nVariable bridges were added in (#759).\nVarious improvements (#746, #747).","category":"page"},{"location":"changelog/#v0.8.4-(March-13,-2019)","page":"Release notes","title":"v0.8.4 (March 13, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Performance improvement in default_copy_to and bridge optimizer (#696).\nAdd Silent and implement setting optimizer attributes in caching and mock optimizers (#695).\nAdd Functionize bridges (SingleVariable and VectorOfVariables) (#659).\nMinor typo fixes (#694).","category":"page"},{"location":"changelog/#v0.8.3-(March-6,-2019)","page":"Release notes","title":"v0.8.3 (March 6, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Use zero constant in scalar constraint function of MOI.Test.copytest (#691).\nFix variable deletion with SingleVariable objective function (#690).\nFix LazyBridgeOptimizer with bridges that add no constraints (#689).\nError message improvements (#673, #685, #686, #688).\nDocumentation improvements (#682, #683, #687).\nBasis status:\nRemove VariableBasisStatus (#679).\nTest ConstraintBasisStatus and implement it in bridges (#678).\nFix inference of NumberOfVariables and NumberOfConstraints (#677).\nImplement division between a quadratic function and a number (#675).","category":"page"},{"location":"changelog/#v0.8.2-(February-7,-2019)","page":"Release notes","title":"v0.8.2 (February 7, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add RawStatusString attribute (#629).\nDo not set names to the optimizer but only to the cache in CachingOptimizer (#638).\nMake scalar MOI functions act as scalars in broadcast (#646).\nAdd function utilities:\nImplement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).\nAdd a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).\nImprove support for starting values:\nShow a warning in copy when starting values are not supported instead of throwing an error (#630).\nFix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).\nAdd a test in contlineartest with partially set VariablePrimalStart.\nBridges improvements:\nFix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.\nAdd Slack bridges (#610, #650).\nAdd FlipSign bridges (#658).\nAdd tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).\nUse tolerance to compare VariablePrimal in rotatedsoc1 test (#632).\nUse a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).","category":"page"},{"location":"changelog/#v0.8.1-(January-7,-2019)","page":"Release notes","title":"v0.8.1 (January 7, 2019)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).\nRename fullbridgeoptimizer into full_bridge_optimizer (#621).\nAllow custom constraint types with full_bridge_optimizer (#617).\nAdd Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).","category":"page"},{"location":"changelog/#v0.8.0-(December-18,-2018)","page":"Release notes","title":"v0.8.0 (December 18, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.\nRename CachingOptimizer methods for style compliance.\nAdd an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.","category":"page"},{"location":"changelog/#v0.7.0-(December-13,-2018)","page":"Release notes","title":"v0.7.0 (December 13, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.\nCheck supports_default_copy_to in tests (#594).\nKey pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.\nAdd perspective dimension to log-det cone (#593).","category":"page"},{"location":"changelog/#v0.6.4-(November-27,-2018)","page":"Release notes","title":"v0.6.4 (November 27, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).\nAdd a solver naming guideline (#578).\nMake FeasibilitySense the default ObjectiveSense (#579).\nFix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).\nDocument solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).","category":"page"},{"location":"changelog/#v0.6.3-(November-16,-2018)","page":"Release notes","title":"v0.6.3 (November 16, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)\nAttributes may now be partially set (some values could be nothing). (#563)\nPerformance improvements in Utilities.Model (#549, #567, #568)\nFix bug in QuadtoSOC (#558).\nNew supports_default_copy_to method that optimizers should implement to control caching behavior.\nDocumentation improvements.","category":"page"},{"location":"changelog/#v0.6.2-(October-26,-2018)","page":"Release notes","title":"v0.6.2 (October 26, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improve hygiene of @model macro (#544).\nFix bug in copy tests (#543).\nFix bug in UniversalFallback attribute getter (#540).\nAllow all correct solutions for solve_blank_obj unit test (#537).\nAdd errors for Allocate-Load and bad constraints (#534).\n[performance] Add specialized implementation of hash for VariableIndex (#533).\n[performance] Construct the name to object dictionaries lazily in model (#535).\nAdd the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).","category":"page"},{"location":"changelog/#v0.6.1-(September-22,-2018)","page":"Release notes","title":"v0.6.1 (September 22, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).\nAdd warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).\nModify MOIT.copytest to not add multiples constraints on the same variable (#521).\nAdd missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).","category":"page"},{"location":"changelog/#v0.6.0-(August-30,-2018)","page":"Release notes","title":"v0.6.0 (August 30, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.\nRename functions according to the JuMP style guide:\ncopy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;\nset! -> set;\naddvariable[s]! -> add_variable[s];\nsupportsconstraint -> supports_constraint;\naddconstraint[s]! -> add_constraint[s];\nisvalid -> is_valid;\nisempty -> is_empty;\nBase.delete! -> delete;\nmodify! -> modify;\ntransform! -> transform;\ninitialize! -> initialize;\nwrite -> write_to_file; and\nread! -> read_from_file.\nRemove free! (use Base.finalize instead).\nAdd the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.\nAdd result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.\nAdd tests for ObjectiveBound.\nAdd test for empty rows in vector linear constraint.\nRework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)\ncanget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).","category":"page"},{"location":"changelog/#v0.5.0-(August-5,-2018)","page":"Release notes","title":"v0.5.0 (August 5, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fix names with CachingOptimizer.\nCleanup thanks to @mohamed82008.\nAdded a universal fallback for constraints.\nFast utilities for function canonicalization thanks to @rdeits.\nRenamed dimension field to side_dimension in the context of matrix-like sets.\nNew and improved tests for cases like duplicate terms and ObjectiveBound.\nRemoved cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.\nThe API for copy! is updated to remove the CopyResult type.\nUpdates for the new JuMP style guide.","category":"page"},{"location":"changelog/#v0.4.1-(June-28,-2018)","page":"Release notes","title":"v0.4.1 (June 28, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Fixes vector function modification on 32 bits.\nFixes Bellman-Ford algorithm for bridges.\nAdded an NLP test with FeasibilitySense.\nUpdate modification documentation.","category":"page"},{"location":"changelog/#v0.4.0-(June-23,-2018)","page":"Release notes","title":"v0.4.0 (June 23, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Helper constructors for VectorAffineTerm and VectorQuadraticTerm.\nAdded modify_lhs to TestConfig.\nAdditional unit tests for optimizers.\nAdded a type parameter to CachingOptimizer for the optimizer field.\nNew API for problem modification (#388)\nTests pass without deprecation warnings on Julia 0.7.\nSmall fixes and documentation updates.","category":"page"},{"location":"changelog/#v0.3.0-(May-25,-2018)","page":"Release notes","title":"v0.3.0 (May 25, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.\nImprovements to MockOptimizer.\nSignificant changes to Bridges.\nNew and improved unit tests.\nFixes for Julia 0.7.","category":"page"},{"location":"changelog/#v0.2.0-(April-24,-2018)","page":"Release notes","title":"v0.2.0 (April 24, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Improvements to and better coverage of Tests.\nDocumentation fixes.\nSolverName attribute.\nChanges to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).\nAddition of NLP tests.\nIntroduction of UniversalFallback.\ncopynames keyword argument to MOI.copy!.\nAdd Bridges submodule.","category":"page"},{"location":"changelog/#v0.1.0-(February-28,-2018)","page":"Release notes","title":"v0.1.0 (February 28, 2018)","text":"","category":"section"},{"location":"changelog/","page":"Release notes","title":"Release notes","text":"Initial public release.\nThe framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"background/duality/#Duality","page":"Duality","title":"Duality","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Conic duality is the starting point for MOI's duality conventions. When all functions are affine (or coordinate projections), and all constraint sets are closed convex cones, the model may be called a conic optimization problem.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For a minimization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_x in mathbbR^n a_0^T x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and the dual is a maximization problem in standard conic form:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_y_1 ldots y_m -sum_i=1^m b_i^T y_i + b_0\n\n textst a_0 - sum_i=1^m A_i^T y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"where each mathcalC_i is a closed convex cone and mathcalC_i^* is its dual cone.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For a maximization problem in geometric conic form, the primal is:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_x in mathbbR^n a_0^T x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and the dual is a minimization problem in standard conic form:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_y_1 ldots y_m sum_i=1^m b_i^T y_i + b_0\n\n textst a_0 + sum_i=1^m A_i^T y_i = 0\n\n y_i in mathcalC_i^* i = 1 ldots m\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"A linear inequality constraint a^T x + b ge c is equivalent to a^T x + b - c in mathbbR_+, and a^T x + b le c is equivalent to a^T x + b - c in mathbbR_-. Variable-wise constraints are affine constraints with the appropriate identity mapping in place of A_i.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For the special case of minimization LPs, the MOI primal form can be stated as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_x in mathbbR^n a_0^T x + b_0\n\n textst\nA_1 x ge b_1\n A_2 x le b_2\n A_3 x = b_3\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"By applying the stated transformations to conic form, taking the dual, and transforming back into linear inequality form, one obtains the following dual:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_y_1y_2y_3 b_1^Ty_1 + b_2^Ty_2 + b_3^Ty_3 + b_0\n\n textst\nA_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 = a_0\n y_1 ge 0\n y_2 le 0\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For maximization LPs, the MOI primal form can be stated as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max_x in mathbbR^n a_0^T x + b_0\n\n textst\nA_1 x ge b_1\n A_2 x le b_2\n A_3 x = b_3\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and similarly, the dual is:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min_y_1y_2y_3 -b_1^Ty_1 - b_2^Ty_2 - b_3^Ty_3 + b_0\n\n textst\nA_1^Ty_1 + A_2^Ty_2 + A_3^Ty_3 = -a_0\n y_1 ge 0\n y_2 le 0\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"warning: Warning\nFor the LP case, the signs of the feasible dual variables depend only on the sense of the corresponding primal inequality and not on the objective sense.","category":"page"},{"location":"background/duality/#Duality-and-scalar-product","page":"Duality","title":"Duality and scalar product","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"The scalar product is different from the canonical one for the sets PositiveSemidefiniteConeTriangle, LogDetConeTriangle, RootDetConeTriangle.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If the set C_i of the section Duality is one of these three cones, then the rows of the matrix A_i corresponding to off-diagonal entries are twice the value of the coefficients field in the VectorAffineFunction for the corresponding rows. See PositiveSemidefiniteConeTriangle for details.","category":"page"},{"location":"background/duality/#Dual-for-problems-with-quadratic-functions","page":"Duality","title":"Dual for problems with quadratic functions","text":"","category":"section"},{"location":"background/duality/#Quadratic-Programs-(QPs)","page":"Duality","title":"Quadratic Programs (QPs)","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"For quadratic programs with only affine conic constraints,","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign*\n min_x in mathbbR^n frac12x^TQ_0x + a_0^T x + b_0\n\n textst A_i x + b_i in mathcalC_i i = 1 ldots m\nendalign*","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with cones mathcalC_i subseteq mathbbR^m_i for i = 1 ldots m, consider the Lagrangian function","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"L(x y) = frac12x^TQ_0x + a_0^T x + b_0 - sum_i = 1^m y_i^T (A_i x + b_i)","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Let z(y) denote sum_i = 1^m A_i^T y_i - a_0, the Lagrangian can be rewritten as","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"L(x y) = frac12x^TQ_0x - z(y)^T x + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"The condition nabla_x L(x y) = 0 gives","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"0 = nabla_x L(x y) = Q_0x + a_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"which gives Q_0x = z(y). This allows to obtain that","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"min_x in mathbbR^n L(x y) = -frac12x^TQ_0x + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"so the dual problem is","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"max_y_i in mathcalC_i^* min_x in mathbbR^n -frac12x^TQ_0x + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If Q_0 is invertible, we have x = Q_0^-1z(y) hence","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"min_x in mathbbR^n L(x y) = -frac12z(y)^TQ_0^-1z(y) + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"so the dual problem is","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"max_y_i in mathcalC_i^* -frac12z(y)^TQ_0^-1z(y) + b_0 - sum_i = 1^m y_i^T b_i","category":"page"},{"location":"background/duality/#Quadratically-Constrained-Quadratic-Programs-(QCQPs)","page":"Duality","title":"Quadratically Constrained Quadratic Programs (QCQPs)","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Given a problem with both quadratic function and quadratic objectives:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign*\n min_x in mathbbR^n frac12x^TQ_0x + a_0^T x + b_0\n\n textst frac12x^TQ_ix + a_i^T x + b_i in mathcalC_i i = 1 ldots m\nendalign*","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with cones mathcalC_i subseteq mathbbR for i = 1 ldots m, consider the Lagrangian function","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"L(x y) = frac12x^TQ_0x + a_0^T x + b_0 - sum_i = 1^m y_i (frac12x^TQ_ix + a_i^T x + b_i)","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"A pair of primal-dual variables (x^star y^star) is optimal if","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"x^star is a minimizer of\nmin_x in mathbbR^n L(x y^star)\nThat is,\n0 = nabla_x L(x y^star) = Q_0x + a_0 - sum_i = 1^m y_i^star (Q_ix + a_i)\nand y^star is a maximizer of\nmax_y_i in mathcalC_i^* L(x^star y)\nThat is, for all i = 1 ldots m, frac12x^TQ_ix + a_i^T x + b_i is either zero or in the normal cone of mathcalC_i^* at y^star. For instance, if mathcalC_i is z in mathbbR z le 0 , this means that if frac12x^TQ_ix + a_i^T x + b_i is nonzero at x^star then y_i^star = 0. This is the classical complementary slackness condition.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If mathcalC_i is a vector set, the discussion remains valid with y_i(frac12x^TQ_ix + a_i^T x + b_i) replaced with the scalar product between y_i and the vector of scalar-valued quadratic functions.","category":"page"},{"location":"background/duality/#Dual-for-square-semidefinite-matrices","page":"Duality","title":"Dual for square semidefinite matrices","text":"","category":"section"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"The set PositiveSemidefiniteConeTriangle is a self-dual. That is, querying ConstraintDual of a PositiveSemidefiniteConeTriangle constraint returns a vector that is itself a member of PositiveSemidefiniteConeTriangle.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"However, the dual of PositiveSemidefiniteConeSquare is not so straight forward. This section explains the duality convention we use, and how it is derived.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"info: Info\nIf you have a PositiveSemidefiniteConeSquare constraint, the result matrix A from ConstraintDual is not positive semidefinite. However, A + A^top is positive semidefinite.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Let mathcalS_+ be the cone of symmetric semidefinite matrices in the fracn(n+1)2 dimensional space of symmetric mathbbR^n times n matrices. That is, mathcalS_+ is the set PositiveSemidefiniteConeTriangle. It is well known that mathcalS_+ is a self-dual proper cone.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Let mathcalP_+ be the cone of symmetric semidefinite matrices in the n^2 dimensional space of mathbbR^n times n matrices. That is mathcalP_+ is the set PositiveSemidefiniteConeSquare.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"In addition, let mathcalD_+ be the cone of matrices A such that A+A^top in mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"mathcalP_+ is not proper because it is not solid (it is not n^2 dimensional), so it is not necessarily true that mathcalP_+^** = mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"However, this is the case, because we will show that mathcalP_+^* = mathcalD_+ and mathcalD_+^* = mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"First, let us see why mathcalP_+^* = mathcalD_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If B is symmetric, then","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"langle AB rangle = langle A^top B^top rangle = langle A^top Brangle","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"so","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"2langle A B rangle = langle A B rangle + langle A^top B rangle = langle A + A^top B rangle","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Therefore, langle ABrangle ge 0 for all B in mathcalP_+ if and only if langle A+A^topBrangle ge 0 for all B in mathcalP_+. Since A+A^top is symmetric, and we know that mathcalS_+ is self-dual, we have shown that mathcalP_+^* is the set of matrices A such that A+A^top in mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Second, let us see why mathcalD_+^* = mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Since A in mathcalD_+ implies that A^top in mathcalD_+, B in mathcalD_+^* means that langle A+A^topBrangle ge 0 for all A in mathcalD_+, and hence B in mathcalP_+.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"To see why it should be symmetric, simply notice that if B_ij B_ji, then langle ABrangle can be made arbitrarily small by setting A_ij = A_ij + s and A_ji = A_ji - s, with s arbitrarily large, and A stays in mathcalD_+ because A+A^top does not change.","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"Typically, the primal/dual pair for semidefinite programs is presented as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min langle C X rangle \ntextst langle A_k Xrangle = b_k forall k \n X in mathcalS_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with the dual","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max sum_k b_k y_k \ntextst C - sum A_k y_k in mathcalS_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"If we allow A_k to be non-symmetric, we should instead use:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min langle C X rangle \ntextst langle A_k Xrangle = b_k forall k \n X in mathcalD_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with the dual","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max sum b_k y_k \ntextst C - sum A_k y_k in mathcalP_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"This is implemented as:","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n min langle C Z rangle + langle C - C^top S rangle \ntextst langle A_k Z rangle + langle A_k - A_k^top S rangle = b_k forall k \n Z in mathcalS_+\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"with the dual","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"beginalign\n max sum b_k y_k \ntextst C+C^top - sum (A_k+A_k^top) y_k in mathcalS_+ \n C-C^top - sum(A_k-A_k^top) y_k = 0\nendalign","category":"page"},{"location":"background/duality/","page":"Duality","title":"Duality","text":"and we recover Z = X + X^top.","category":"page"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/callbacks/#Callbacks","page":"Callbacks","title":"Callbacks","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"AbstractCallback\nAbstractSubmittable\nsubmit","category":"page"},{"location":"reference/callbacks/#MathOptInterface.AbstractCallback","page":"Callbacks","title":"MathOptInterface.AbstractCallback","text":"abstract type AbstractCallback <: AbstractModelAttribute end\n\nAbstract type for a model attribute representing a callback function. The value set to subtypes of AbstractCallback is a function that may be called during optimize!. As optimize! is in progress, the result attributes (that is, the attributes attr such that is_set_by_optimize(attr)) may not be accessible from the callback, hence trying to get result attributes might throw a OptimizeInProgress error.\n\nAt most one callback of each type can be registered. If an optimizer already has a function for a callback type, and the user registers a new function, then the old one is replaced.\n\nThe value of the attribute should be a function taking only one argument, commonly called callback_data, that can be used for instance in LazyConstraintCallback, HeuristicCallback and UserCutCallback.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.AbstractSubmittable","page":"Callbacks","title":"MathOptInterface.AbstractSubmittable","text":"AbstractSubmittable\n\nAbstract supertype for objects that can be submitted to the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.submit","page":"Callbacks","title":"MathOptInterface.submit","text":"submit(\n optimizer::AbstractOptimizer,\n sub::AbstractSubmittable,\n values...,\n)::Nothing\n\nSubmit values to the submittable sub of the optimizer optimizer.\n\nAn UnsupportedSubmittable error is thrown if model does not support the attribute attr (see supports) and a SubmitNotAllowed error is thrown if it supports the submittable sub but it cannot be submitted.\n\n\n\n\n\n","category":"function"},{"location":"reference/callbacks/#Attributes","page":"Callbacks","title":"Attributes","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"CallbackNodeStatus\nCallbackVariablePrimal\nCallbackNodeStatusCode\nCALLBACK_NODE_STATUS_INTEGER\nCALLBACK_NODE_STATUS_FRACTIONAL\nCALLBACK_NODE_STATUS_UNKNOWN","category":"page"},{"location":"reference/callbacks/#MathOptInterface.CallbackNodeStatus","page":"Callbacks","title":"MathOptInterface.CallbackNodeStatus","text":"CallbackNodeStatus(callback_data)\n\nAn optimizer attribute describing the (in)feasibility of the primal solution available from CallbackVariablePrimal during a callback identified by callback_data.\n\nReturns a CallbackNodeStatusCode Enum.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.CallbackVariablePrimal","page":"Callbacks","title":"MathOptInterface.CallbackVariablePrimal","text":"CallbackVariablePrimal(callback_data)\n\nA variable attribute for the assignment to some primal variable's value during the callback identified by callback_data.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.CallbackNodeStatusCode","page":"Callbacks","title":"MathOptInterface.CallbackNodeStatusCode","text":"CallbackNodeStatusCode\n\nAn Enum of possible return values from calling get with CallbackNodeStatus.\n\nValues\n\nPossible values are:\n\nCALLBACK_NODE_STATUS_INTEGER: the primal solution available from CallbackVariablePrimal is integer feasible.\nCALLBACK_NODE_STATUS_FRACTIONAL: the primal solution available from CallbackVariablePrimal is integer infeasible.\nCALLBACK_NODE_STATUS_UNKNOWN: the primal solution available from CallbackVariablePrimal might be integer feasible or infeasible.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.CALLBACK_NODE_STATUS_INTEGER","page":"Callbacks","title":"MathOptInterface.CALLBACK_NODE_STATUS_INTEGER","text":"CALLBACK_NODE_STATUS_INTEGER::CallbackNodeStatusCode\n\nAn instance of the CallbackNodeStatusCode enum.\n\nCALLBACK_NODE_STATUS_INTEGER: the primal solution available from CallbackVariablePrimal is integer feasible.\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.CALLBACK_NODE_STATUS_FRACTIONAL","page":"Callbacks","title":"MathOptInterface.CALLBACK_NODE_STATUS_FRACTIONAL","text":"CALLBACK_NODE_STATUS_FRACTIONAL::CallbackNodeStatusCode\n\nAn instance of the CallbackNodeStatusCode enum.\n\nCALLBACK_NODE_STATUS_FRACTIONAL: the primal solution available from CallbackVariablePrimal is integer infeasible.\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.CALLBACK_NODE_STATUS_UNKNOWN","page":"Callbacks","title":"MathOptInterface.CALLBACK_NODE_STATUS_UNKNOWN","text":"CALLBACK_NODE_STATUS_UNKNOWN::CallbackNodeStatusCode\n\nAn instance of the CallbackNodeStatusCode enum.\n\nCALLBACK_NODE_STATUS_UNKNOWN: the primal solution available from CallbackVariablePrimal might be integer feasible or infeasible.\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#Lazy-constraints","page":"Callbacks","title":"Lazy constraints","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"LazyConstraintCallback\nLazyConstraint","category":"page"},{"location":"reference/callbacks/#MathOptInterface.LazyConstraintCallback","page":"Callbacks","title":"MathOptInterface.LazyConstraintCallback","text":"LazyConstraintCallback() <: AbstractCallback\n\nThe callback can be used to reduce the feasible set given the current primal solution by submitting a LazyConstraint. For instance, it may be called at an incumbent of a mixed-integer problem. Note that there is no guarantee that the callback is called at every feasible primal solution.\n\nThe current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.\n\nExamples\n\nx = MOI.add_variables(optimizer, 8)\nMOI.set(optimizer, MOI.LazyConstraintCallback(), callback_data -> begin\n sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)\n if # should add a lazy constraint\n func = # computes function\n set = # computes set\n MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)\n end\nend)\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.LazyConstraint","page":"Callbacks","title":"MathOptInterface.LazyConstraint","text":"LazyConstraint(callback_data)\n\nLazy constraint func-in-set submitted as func, set. The optimal solution returned by VariablePrimal will satisfy all lazy constraints that have been submitted.\n\nThis can be submitted only from the LazyConstraintCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the feasible solution callback.\n\nExamples\n\nSuppose x and y are VariableIndexs of optimizer. To add a LazyConstraint for 2x + 3y <= 1, write\n\nfunc = 2.0x + 3.0y\nset = MOI.LessThan(1.0)\nMOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)\n\ninside a LazyConstraintCallback of data callback_data.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#User-cuts","page":"Callbacks","title":"User cuts","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"UserCutCallback\nUserCut","category":"page"},{"location":"reference/callbacks/#MathOptInterface.UserCutCallback","page":"Callbacks","title":"MathOptInterface.UserCutCallback","text":"UserCutCallback() <: AbstractCallback\n\nThe callback can be used to submit UserCut given the current primal solution. For instance, it may be called at fractional (that is, non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is not guarantee that the callback is called everytime the solver has an infeasible solution.\n\nThe infeasible solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.\n\nExamples\n\nx = MOI.add_variables(optimizer, 8)\nMOI.set(optimizer, MOI.UserCutCallback(), callback_data -> begin\n sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)\n if # can find a user cut\n func = # computes function\n set = # computes set\n MOI.submit(optimizer, MOI.UserCut(callback_data), func, set)\n end\nend\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.UserCut","page":"Callbacks","title":"MathOptInterface.UserCut","text":"UserCut(callback_data)\n\nConstraint func-to-set suggested to help the solver detect the solution given by CallbackVariablePrimal as infeasible. The cut is submitted as func, set. Typically CallbackVariablePrimal will violate integrality constraints, and a cut would be of the form ScalarAffineFunction-in-LessThan or ScalarAffineFunction-in-GreaterThan. Note that, as opposed to LazyConstraint, the provided constraint cannot modify the feasible set, the constraint should be redundant, for example, it may be a consequence of affine and integrality constraints.\n\nThis can be submitted only from the UserCutCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the infeasible solution callback.\n\nNote that the solver may silently ignore the provided constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#Heuristic-solutions","page":"Callbacks","title":"Heuristic solutions","text":"","category":"section"},{"location":"reference/callbacks/","page":"Callbacks","title":"Callbacks","text":"HeuristicCallback\nHeuristicSolution\nHeuristicSolutionStatus\nHEURISTIC_SOLUTION_ACCEPTED\nHEURISTIC_SOLUTION_REJECTED\nHEURISTIC_SOLUTION_UNKNOWN","category":"page"},{"location":"reference/callbacks/#MathOptInterface.HeuristicCallback","page":"Callbacks","title":"MathOptInterface.HeuristicCallback","text":"HeuristicCallback() <: AbstractCallback\n\nThe callback can be used to submit HeuristicSolution given the current primal solution. For example, it may be called at fractional (that is, non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is no guarantee that the callback is called every time the solver has an infeasible solution.\n\nThe current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.\n\nExamples\n\nx = MOI.add_variables(optimizer, 8)\nMOI.set(optimizer, MOI.HeuristicCallback(), callback_data -> begin\n sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)\n if # can find a heuristic solution\n values = # computes heuristic solution\n MOI.submit(optimizer, MOI.HeuristicSolution(callback_data), x,\n values)\n end\nend\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.HeuristicSolution","page":"Callbacks","title":"MathOptInterface.HeuristicSolution","text":"HeuristicSolution(callback_data)\n\nHeuristically obtained feasible solution. The solution is submitted as variables, values where values[i] gives the value of variables[i], similarly to set. The submit call returns a HeuristicSolutionStatus indicating whether the provided solution was accepted or rejected.\n\nThis can be submitted only from the HeuristicCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the heuristic callback.\n\nSome solvers require a complete solution, others only partial solutions.\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.HeuristicSolutionStatus","page":"Callbacks","title":"MathOptInterface.HeuristicSolutionStatus","text":"HeuristicSolutionStatus\n\nAn Enum of possible return values for submit with HeuristicSolution. This informs whether the heuristic solution was accepted or rejected.\n\nValues\n\nPossible values are:\n\nHEURISTIC_SOLUTION_ACCEPTED: The heuristic solution was accepted\nHEURISTIC_SOLUTION_REJECTED: The heuristic solution was rejected\nHEURISTIC_SOLUTION_UNKNOWN: No information available on the acceptance\n\n\n\n\n\n","category":"type"},{"location":"reference/callbacks/#MathOptInterface.HEURISTIC_SOLUTION_ACCEPTED","page":"Callbacks","title":"MathOptInterface.HEURISTIC_SOLUTION_ACCEPTED","text":"HEURISTIC_SOLUTION_ACCEPTED::HeuristicSolutionStatus\n\nAn instance of the HeuristicSolutionStatus enum.\n\nHEURISTIC_SOLUTION_ACCEPTED: The heuristic solution was accepted\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.HEURISTIC_SOLUTION_REJECTED","page":"Callbacks","title":"MathOptInterface.HEURISTIC_SOLUTION_REJECTED","text":"HEURISTIC_SOLUTION_REJECTED::HeuristicSolutionStatus\n\nAn instance of the HeuristicSolutionStatus enum.\n\nHEURISTIC_SOLUTION_REJECTED: The heuristic solution was rejected\n\n\n\n\n\n","category":"constant"},{"location":"reference/callbacks/#MathOptInterface.HEURISTIC_SOLUTION_UNKNOWN","page":"Callbacks","title":"MathOptInterface.HEURISTIC_SOLUTION_UNKNOWN","text":"HEURISTIC_SOLUTION_UNKNOWN::HeuristicSolutionStatus\n\nAn instance of the HeuristicSolutionStatus enum.\n\nHEURISTIC_SOLUTION_UNKNOWN: No information available on the acceptance\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/","page":"Models","title":"Models","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/models/#Models","page":"Models","title":"Models","text":"","category":"section"},{"location":"reference/models/#Attribute-interface","page":"Models","title":"Attribute interface","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"is_set_by_optimize\nis_copyable\nget\nget!\nset\nsupports\nattribute_value_type","category":"page"},{"location":"reference/models/#MathOptInterface.is_set_by_optimize","page":"Models","title":"MathOptInterface.is_set_by_optimize","text":"is_set_by_optimize(::AnyAttribute)\n\nReturn a Bool indicating whether the value of the attribute is set during an optimize! call, that is, the attribute is used to query the result of the optimization.\n\nIf an attribute can be set by the user, define is_copyable instead.\n\nAn attribute cannot be both is_copyable and is_set_by_optimize.\n\nDefault fallback\n\nThis function returns false by default so it should be implemented for attributes that are set by optimize!.\n\nUndefined behavior\n\nQuerying the value of the attribute that is_set_by_optimize before a call to optimize! is undefined and depends on solver-specific behavior.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.is_copyable","page":"Models","title":"MathOptInterface.is_copyable","text":"is_copyable(::AnyAttribute)\n\nReturn a Bool indicating whether the value of the attribute may be copied during copy_to using set.\n\nIf an attribute is_copyable, then it cannot be modified by the optimizer, and get must always return the value that was set by the user.\n\nIf an attribute is the result of an optimization, define is_set_by_optimize instead.\n\nAn attribute cannot be both is_set_by_optimize and is_copyable.\n\nDefault fallback\n\nBy default is_copyable(attr) returns !is_set_by_optimize(attr), which is most probably true.\n\nIf an attribute should not be copied, define is_copyable(::MyAttribute) = false.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.get","page":"Models","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64\n\nReturn the number of variables created by the bridge b in the model.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\nMOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)\n\nReturn the list of variables created by the bridge b.\n\nSee also MOI.ListOfVariableIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\nMOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}\n\nReturn the number of constraints of the type F-in-S created by the bridge b.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\nMOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}\n\nReturn a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.\n\nSee also MOI.ListOfConstraintIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\nfunction MOI.get(\n model::MOI.ModelLike,\n attr::MOI.AbstractConstraintAttribute,\n bridge::AbstractBridge,\n)\n\nReturn the value of the attribute attr of the model model for the constraint bridged by bridge.\n\n\n\n\n\nget(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute)\n\nReturn an attribute attr of the optimizer optimizer.\n\nget(model::ModelLike, attr::AbstractModelAttribute)\n\nReturn an attribute attr of the model model.\n\nget(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex)\n\nIf the attribute attr is set for the variable v in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.\n\nget(model::ModelLike, attr::AbstractVariableAttribute, v::Vector{VariableIndex})\n\nReturn a vector of attributes corresponding to each variable in the collection v in the model model.\n\nget(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex)\n\nIf the attribute attr is set for the constraint c in the model model, return its value, return nothing otherwise. If the attribute attr is not supported by model then an error should be thrown instead of returning nothing.\n\nget(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n c::Vector{ConstraintIndex{F,S}},\n) where {F,S}\n\nReturn a vector of attributes corresponding to each constraint in the collection c in the model model.\n\nget(model::ModelLike, ::Type{VariableIndex}, name::String)\n\nIf a variable with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two variables have the same name.\n\nget(\n model::ModelLike,\n ::Type{ConstraintIndex{F,S}},\n name::String,\n) where {F,S}\n\nIf an F-in-S constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. Errors if two constraints have the same name.\n\nget(model::ModelLike, ::Type{ConstraintIndex}, name::String)\n\nIf any constraint with name name exists in the model model, return the corresponding index, otherwise return nothing. This version is available for convenience but may incur a performance penalty because it is not type stable. Errors if two constraints have the same name.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.get!","page":"Models","title":"MathOptInterface.get!","text":"get!(output, model::ModelLike, args...)\n\nAn in-place version of get.\n\nThe signature matches that of get except that the result is placed in the vector output.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.set","page":"Models","title":"MathOptInterface.set","text":"function MOI.set(\n model::MOI.ModelLike,\n attr::MOI.AbstractConstraintAttribute,\n bridge::AbstractBridge,\n value,\n)\n\nSet the value of the attribute attr of the model model for the constraint bridged by bridge.\n\n\n\n\n\nset(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute, value)\n\nAssign value to the attribute attr of the optimizer optimizer.\n\nset(model::ModelLike, attr::AbstractModelAttribute, value)\n\nAssign value to the attribute attr of the model model.\n\nset(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)\n\nAssign value to the attribute attr of variable v in model model.\n\nset(\n model::ModelLike,\n attr::AbstractVariableAttribute,\n v::Vector{VariableIndex},\n vector_of_values,\n)\n\nAssign a value respectively to the attribute attr of each variable in the collection v in model model.\n\nset(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n c::ConstraintIndex,\n value,\n)\n\nAssign a value to the attribute attr of constraint c in model model.\n\nset(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n c::Vector{ConstraintIndex{F,S}},\n vector_of_values,\n) where {F,S}\n\nAssign a value respectively to the attribute attr of each constraint in the collection c in model model.\n\nAn UnsupportedAttribute error is thrown if model does not support the attribute attr (see supports) and a SetAttributeNotAllowed error is thrown if it supports the attribute attr but it cannot be set.\n\nset(\n model::ModelLike,\n ::ConstraintSet,\n c::ConstraintIndex{F,S},\n set::S,\n) where {F,S}\n\nChange the set of constraint c to the new set set which should be of the same type as the original set.\n\nset(\n model::ModelLike,\n ::ConstraintFunction,\n c::ConstraintIndex{F,S},\n func::F,\n) where {F,S}\n\nReplace the function in constraint c with func. F must match the original function type used to define the constraint.\n\nnote: Note\nSetting the constraint function is not allowed if F is VariableIndex; a SettingVariableIndexNotAllowed error is thrown instead. This is because, it would require changing the index c since the index of VariableIndex constraints must be the same as the index of the variable.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.supports","page":"Models","title":"MathOptInterface.supports","text":"MOI.supports(\n model::MOI.ModelLike,\n attr::MOI.AbstractConstraintAttribute,\n BT::Type{<:AbstractBridge},\n)\n\nReturn a Bool indicating whether BT supports setting attr to model.\n\n\n\n\n\nsupports(model::ModelLike, sub::AbstractSubmittable)::Bool\n\nReturn a Bool indicating whether model supports the submittable sub.\n\nsupports(model::ModelLike, attr::AbstractOptimizerAttribute)::Bool\n\nReturn a Bool indicating whether model supports the optimizer attribute attr. That is, it returns false if copy_to(model, src) shows a warning in case attr is in the ListOfOptimizerAttributesSet of src; see copy_to for more details on how unsupported optimizer attributes are handled in copy.\n\nsupports(model::ModelLike, attr::AbstractModelAttribute)::Bool\n\nReturn a Bool indicating whether model supports the model attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfModelAttributesSet of src.\n\nsupports(\n model::ModelLike,\n attr::AbstractVariableAttribute,\n ::Type{VariableIndex},\n)::Bool\n\nReturn a Bool indicating whether model supports the variable attribute attr. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfVariableAttributesSet of src.\n\nsupports(\n model::ModelLike,\n attr::AbstractConstraintAttribute,\n ::Type{ConstraintIndex{F,S}},\n)::Bool where {F,S}\n\nReturn a Bool indicating whether model supports the constraint attribute attr applied to an F-in-S constraint. That is, it returns false if copy_to(model, src) cannot be performed in case attr is in the ListOfConstraintAttributesSet of src.\n\nFor all five methods, if the attribute is only not supported in specific circumstances, it should still return true.\n\nNote that supports is only defined for attributes for which is_copyable returns true as other attributes do not appear in the list of attributes set obtained by ListOfXXXAttributesSet.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.attribute_value_type","page":"Models","title":"MathOptInterface.attribute_value_type","text":"attribute_value_type(attr::AnyAttribute)\n\nGiven an attribute attr, return the type of value expected by get, or returned by set.\n\nNotes\n\nOnly implement this if it make sense to do so. If un-implemented, the default is Any.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#Model-interface","page":"Models","title":"Model interface","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"ModelLike\nis_empty\nempty!\nwrite_to_file\nread_from_file\nsupports_incremental_interface\ncopy_to\nIndexMap","category":"page"},{"location":"reference/models/#MathOptInterface.ModelLike","page":"Models","title":"MathOptInterface.ModelLike","text":"ModelLike\n\nAbstract supertype for objects that implement the \"Model\" interface for defining an optimization problem.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.is_empty","page":"Models","title":"MathOptInterface.is_empty","text":"is_empty(model::ModelLike)\n\nReturns false if the model has any model attribute set or has any variables or constraints.\n\nNote that an empty model can have optimizer attributes set.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.empty!","page":"Models","title":"MathOptInterface.empty!","text":"empty!(model::ModelLike)\n\nEmpty the model, that is, remove all variables, constraints and model attributes but not optimizer attributes.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.write_to_file","page":"Models","title":"MathOptInterface.write_to_file","text":"write_to_file(model::ModelLike, filename::String)\n\nWrite the current model to the file at filename.\n\nSupported file types depend on the model type.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.read_from_file","page":"Models","title":"MathOptInterface.read_from_file","text":"read_from_file(model::ModelLike, filename::String)\n\nRead the file filename into the model model. If model is non-empty, this may throw an error.\n\nSupported file types depend on the model type.\n\nNote\n\nOnce the contents of the file are loaded into the model, users can query the variables via get(model, ListOfVariableIndices()). However, some filetypes, such as LP files, do not maintain an explicit ordering of the variables. Therefore, the returned list may be in an arbitrary order.\n\nTo avoid depending on the order of the indices, look up each variable index by name using get(model, VariableIndex, \"name\").\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.supports_incremental_interface","page":"Models","title":"MathOptInterface.supports_incremental_interface","text":"supports_incremental_interface(model::ModelLike)\n\nReturn a Bool indicating whether model supports building incrementally via add_variable and add_constraint.\n\nThe main purpose of this function is to determine whether a model can be loaded into model incrementally or whether it should be cached and copied at once instead.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.copy_to","page":"Models","title":"MathOptInterface.copy_to","text":"copy_to(dest::ModelLike, src::ModelLike)::IndexMap\n\nCopy the model from src into dest.\n\nThe target dest is emptied, and all previous indices to variables and constraints in dest are invalidated.\n\nReturns an IndexMap object that translates variable and constraint indices from the src model to the corresponding indices in the dest model.\n\nNotes\n\nIf a constraint that in src is not supported by dest, then an UnsupportedConstraint error is thrown.\nIf an AbstractModelAttribute, AbstractVariableAttribute, or AbstractConstraintAttribute is set in src but not supported by dest, then an UnsupportedAttribute error is thrown.\n\nAbstractOptimizerAttributes are not copied to the dest model.\n\nIndexMap\n\nImplementations of copy_to must return an IndexMap. For technical reasons, this type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide MOI.IndexMap as an alias.\n\nExample\n\n# Given empty `ModelLike` objects `src` and `dest`.\n\nx = add_variable(src)\n\nis_valid(src, x) # true\nis_valid(dest, x) # false (`dest` has no variables)\n\nindex_map = copy_to(dest, src)\nis_valid(dest, x) # false (unless index_map[x] == x)\nis_valid(dest, index_map[x]) # true\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.IndexMap","page":"Models","title":"MathOptInterface.IndexMap","text":"IndexMap()\n\nThe dictionary-like object returned by copy_to.\n\nIndexMap\n\nImplementations of copy_to must return an IndexMap. For technical reasons, the IndexMap type is defined in the Utilities submodule as MOI.Utilities.IndexMap. However, since it is an integral part of the MOI API, we provide this MOI.IndexMap as an alias.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#Model-attributes","page":"Models","title":"Model attributes","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"AbstractModelAttribute\nName\nObjectiveFunction\nObjectiveFunctionType\nObjectiveSense\nOptimizationSense\nMIN_SENSE\nMAX_SENSE\nFEASIBILITY_SENSE\nNumberOfVariables\nListOfVariableIndices\nListOfConstraintTypesPresent\nNumberOfConstraints\nListOfConstraintIndices\nListOfOptimizerAttributesSet\nListOfModelAttributesSet\nListOfVariableAttributesSet\nListOfVariablesWithAttributeSet\nListOfConstraintAttributesSet\nListOfConstraintsWithAttributeSet\nUserDefinedFunction\nListOfSupportedNonlinearOperators","category":"page"},{"location":"reference/models/#MathOptInterface.AbstractModelAttribute","page":"Models","title":"MathOptInterface.AbstractModelAttribute","text":"AbstractModelAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.Name","page":"Models","title":"MathOptInterface.Name","text":"Name()\n\nA model attribute for the string identifying the model. It has a default value of \"\" if not set`.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveFunction","page":"Models","title":"MathOptInterface.ObjectiveFunction","text":"ObjectiveFunction{F<:AbstractScalarFunction}()\n\nA model attribute for the objective function which has a type F<:AbstractScalarFunction.\n\nF should be guaranteed to be equivalent but not necessarily identical to the function type provided by the user.\n\nThrows an InexactError if the objective function cannot be converted to F, for example, the objective function is quadratic and F is ScalarAffineFunction{Float64} or it has non-integer coefficient and F is ScalarAffineFunction{Int}.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveFunctionType","page":"Models","title":"MathOptInterface.ObjectiveFunctionType","text":"ObjectiveFunctionType()\n\nA model attribute for the type F of the objective function set using the ObjectiveFunction{F} attribute.\n\nExamples\n\nIn the following code, attr should be equal to MOI.VariableIndex:\n\nx = MOI.add_variable(model)\nMOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x)\nattr = MOI.get(model, MOI.ObjectiveFunctionType())\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveSense","page":"Models","title":"MathOptInterface.ObjectiveSense","text":"ObjectiveSense()\n\nA model attribute for the objective sense of the objective function, which must be an OptimizationSense: MIN_SENSE, MAX_SENSE, or FEASIBILITY_SENSE. The default is FEASIBILITY_SENSE.\n\nInteraction with ObjectiveFunction\n\nSetting the sense to FEASIBILITY_SENSE unsets the ObjectiveFunction attribute. That is, if you first set ObjectiveFunction and then set ObjectiveSense to be FEASIBILITY_SENSE, no objective function will be passed to the solver.\n\nIn addition, some reformulations of ObjectiveFunction via bridges rely on the value of ObjectiveSense. Therefore, you should set ObjectiveSense before setting ObjectiveFunction.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.OptimizationSense","page":"Models","title":"MathOptInterface.OptimizationSense","text":"OptimizationSense\n\nAn enum for the value of the ObjectiveSense attribute.\n\nValues\n\nPossible values are:\n\nMIN_SENSE: the goal is to minimize the objective function\nMAX_SENSE: the goal is to maximize the objective function\nFEASIBILITY_SENSE: the model does not have an objective function\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.MIN_SENSE","page":"Models","title":"MathOptInterface.MIN_SENSE","text":"MIN_SENSE::OptimizationSense\n\nAn instance of the OptimizationSense enum.\n\nMIN_SENSE: the goal is to minimize the objective function\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.MAX_SENSE","page":"Models","title":"MathOptInterface.MAX_SENSE","text":"MAX_SENSE::OptimizationSense\n\nAn instance of the OptimizationSense enum.\n\nMAX_SENSE: the goal is to maximize the objective function\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.FEASIBILITY_SENSE","page":"Models","title":"MathOptInterface.FEASIBILITY_SENSE","text":"FEASIBILITY_SENSE::OptimizationSense\n\nAn instance of the OptimizationSense enum.\n\nFEASIBILITY_SENSE: the model does not have an objective function\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NumberOfVariables","page":"Models","title":"MathOptInterface.NumberOfVariables","text":"NumberOfVariables()\n\nA model attribute for the number of variables in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfVariableIndices","page":"Models","title":"MathOptInterface.ListOfVariableIndices","text":"ListOfVariableIndices()\n\nA model attribute for the Vector{VariableIndex} of all variable indices present in the model (that is, of length equal to the value of NumberOfVariables in the order in which they were added.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintTypesPresent","page":"Models","title":"MathOptInterface.ListOfConstraintTypesPresent","text":"ListOfConstraintTypesPresent()\n\nA model attribute for the list of tuples of the form (F,S), where F is a function type and S is a set type indicating that the attribute NumberOfConstraints{F,S} has a value greater than zero.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NumberOfConstraints","page":"Models","title":"MathOptInterface.NumberOfConstraints","text":"NumberOfConstraints{F,S}()\n\nA model attribute for the number of constraints of the type F-in-S present in the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintIndices","page":"Models","title":"MathOptInterface.ListOfConstraintIndices","text":"ListOfConstraintIndices{F,S}()\n\nA model attribute for the Vector{ConstraintIndex{F,S}} of all constraint indices of type F-in-S in the model (that is, of length equal to the value of NumberOfConstraints{F,S}) in the order in which they were added.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfOptimizerAttributesSet","page":"Models","title":"MathOptInterface.ListOfOptimizerAttributesSet","text":"ListOfOptimizerAttributesSet()\n\nAn optimizer attribute for the Vector{AbstractOptimizerAttribute} of all optimizer attributes that were set.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfModelAttributesSet","page":"Models","title":"MathOptInterface.ListOfModelAttributesSet","text":"ListOfModelAttributesSet()\n\nA model attribute for the Vector{AbstractModelAttribute} of all model attributes attr such that:\n\nis_copyable(attr) returns true, and\nthe attribute was set to the model\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfVariableAttributesSet","page":"Models","title":"MathOptInterface.ListOfVariableAttributesSet","text":"ListOfVariableAttributesSet()\n\nA model attribute for the Vector{AbstractVariableAttribute} of all variable attributes attr such that 1) is_copyable(attr) returns true and 2) the attribute was set to variables.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfVariablesWithAttributeSet","page":"Models","title":"MathOptInterface.ListOfVariablesWithAttributeSet","text":"ListOfVariablesWithAttributeSet(attr::AbstractVariableAttribute)\n\nA model attribute for the Vector{VariableIndex} of all variables with the attribute attr set.\n\nThe returned list may not be minimal, so some elements may have their default value set.\n\nNote\n\nThis is an optional attribute to implement. The default fallback is to get ListOfVariableIndices.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintAttributesSet","page":"Models","title":"MathOptInterface.ListOfConstraintAttributesSet","text":"ListOfConstraintAttributesSet{F, S}()\n\nA model attribute for the Vector{AbstractConstraintAttribute} of all constraint attributes attr such that:\n\nis_copyable(attr) returns true and\nthe attribute was set to F-in-S constraints.\n\nNote\n\nThe attributes ConstraintFunction and ConstraintSet should not be included in the list even if then have been set with set.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfConstraintsWithAttributeSet","page":"Models","title":"MathOptInterface.ListOfConstraintsWithAttributeSet","text":"ListOfConstraintsWithAttributeSet{F,S}(attr:AbstractConstraintAttribute)\n\nA model attribute for the Vector{ConstraintIndex{F,S}} of all constraints with the attribute attr set.\n\nThe returned list may not be minimal, so some elements may have their default value set.\n\nNote\n\nThis is an optional attribute to implement. The default fallback is to get ListOfConstraintIndices.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.UserDefinedFunction","page":"Models","title":"MathOptInterface.UserDefinedFunction","text":"UserDefinedFunction(name::Symbol, arity::Int) <: AbstractModelAttribute\n\nSet this attribute to register a user-defined function by the name of name with arity arguments.\n\nOnce registered, name will appear in ListOfSupportedNonlinearOperators.\n\nYou cannot register multiple UserDefinedFunctions with the same name but different arity.\n\nValue type\n\nThe value to be set is a tuple containing one, two, or three functions to evaluate the function, the first-order derivative, and the second-order derivative respectively. Both derivatives are optional, but if you pass the second-order derivative you must also pass the first-order derivative.\n\nFor univariate functions with arity == 1, the functions in the tuple must have the form:\n\nf(x::T)::T: returns the value of the function at x\n∇f(x::T)::T: returns the first-order derivative of f with respect to x\n∇²f(x::T)::T: returns the second-order derivative of f with respect to x.\n\nFor multivariate functions with arity > 1, the functions in the tuple must have the form:\n\nf(x::T...)::T: returns the value of the function at x\n∇f(g::AbstractVector{T}, x::T...)::Nothing: fills the components of g, with g[i] being the first-order partial derivative of f with respect to x[i]\n∇²f(H::AbstractMatrix{T}, x::T...)::Nothing: fills the non-zero components of H, with H[i, j] being the second-order partial derivative of f with respect to x[i] and then x[j]. H is initialized to the zero matrix, so you do not need to set any zero elements.\n\nExamples\n\njulia> import MathOptInterface as MOI\n\njulia> f(x, y) = x^2 + y^2\nf (generic function with 1 method)\n\njulia> function ∇f(g, x, y)\n g .= 2 * x, 2 * y\n return\n end\n∇f (generic function with 1 method)\n\njulia> function ∇²f(H, x...)\n H[1, 1] = H[2, 2] = 2.0\n return\n end\n∇²f (generic function with 1 method)\n\njulia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nMOIU.UniversalFallback{MOIU.Model{Float64}}\nfallback for MOIU.Model{Float64}\n\njulia> MOI.set(model, MOI.UserDefinedFunction(:f, 2), (f,))\n\njulia> MOI.set(model, MOI.UserDefinedFunction(:g, 2), (f, ∇f))\n\njulia> MOI.set(model, MOI.UserDefinedFunction(:h, 2), (f, ∇f, ∇²f))\n\njulia> x = MOI.add_variables(model, 2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n\njulia> MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n\njulia> obj_f = MOI.ScalarNonlinearFunction(:f, Any[x[1], x[2]])\nf(MOI.VariableIndex(1), MOI.VariableIndex(2))\n\njulia> MOI.set(model, MOI.ObjectiveFunction{typeof(obj_f)}(), obj_f)\n\njulia> print(model)\nMinimize ScalarNonlinearFunction:\n f(v[1], v[2])\n\nSubject to:\n\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ListOfSupportedNonlinearOperators","page":"Models","title":"MathOptInterface.ListOfSupportedNonlinearOperators","text":"ListOfSupportedNonlinearOperators() <: AbstractModelAttribute\n\nWhen queried with get, return a Vector{Symbol} listing the operators supported by the model.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#Optimizer-interface","page":"Models","title":"Optimizer interface","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"AbstractOptimizer\nOptimizerWithAttributes\noptimize!\noptimize!(::ModelLike, ::ModelLike)\ninstantiate\ndefault_cache","category":"page"},{"location":"reference/models/#MathOptInterface.AbstractOptimizer","page":"Models","title":"MathOptInterface.AbstractOptimizer","text":"AbstractOptimizer <: ModelLike\n\nAbstract supertype for objects representing an instance of an optimization problem tied to a particular solver. This is typically a solver's in-memory representation. In addition to ModelLike, AbstractOptimizer objects let you solve the model and query the solution.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.OptimizerWithAttributes","page":"Models","title":"MathOptInterface.OptimizerWithAttributes","text":"struct OptimizerWithAttributes\n optimizer_constructor\n params::Vector{Pair{AbstractOptimizerAttribute,<:Any}}\nend\n\nObject grouping an optimizer constructor and a list of optimizer attributes. Instances are created with instantiate.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.optimize!","page":"Models","title":"MathOptInterface.optimize!","text":"optimize!(optimizer::AbstractOptimizer)\n\nOptimize the problem contained in optimizer.\n\nBefore calling optimize!, the problem should first be constructed using the incremental interface (see supports_incremental_interface) or copy_to.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.optimize!-Tuple{MathOptInterface.ModelLike, MathOptInterface.ModelLike}","page":"Models","title":"MathOptInterface.optimize!","text":"optimize!(dest::AbstractOptimizer, src::ModelLike)::Tuple{IndexMap,Bool}\n\nA \"one-shot\" call that copies the problem from src into dest and then uses dest to optimize the problem.\n\nReturns a tuple of an IndexMap and a Bool copied.\n\nThe IndexMap object translates variable and constraint indices from the src model to the corresponding indices in the dest optimizer. See copy_to for details.\nIf copied == true, src was copied to dest and then cached, allowing incremental modification if supported by the solver.\nIf copied == false, a cache of the model was not kept in dest. Therefore, only the solution information (attributes for which is_set_by_optimize is true) is available to query.\n\nnote: Note\nThe main purpose of optimize! method with two arguments is for use in Utilities.CachingOptimizer.\n\nRelationship to the single-argument optimize!\n\nThe default fallback of optimize!(dest::AbstractOptimizer, src::ModelLike) is\n\nfunction optimize!(dest::AbstractOptimizer, src::ModelLike)\n index_map = copy_to(dest, src)\n optimize!(dest)\n return index_map, true\nend\n\nTherefore, subtypes of AbstractOptimizer should either implement this two-argument method, or implement both copy_to(::Optimizer, ::ModelLike) and optimize!(::Optimizer).\n\n\n\n\n\n","category":"method"},{"location":"reference/models/#MathOptInterface.instantiate","page":"Models","title":"MathOptInterface.instantiate","text":"instantiate(\n optimizer_constructor,\n with_cache_type::Union{Nothing,Type} = nothing,\n with_bridge_type::Union{Nothing,Type} = nothing,\n)\n\nCreate an instance of an optimizer by either:\n\ncalling optimizer_constructor.optimizer_constructor() and setting the parameters in optimizer_constructor.params if optimizer_constructor is a OptimizerWithAttributes\ncalling optimizer_constructor() if optimizer_constructor is callable.\n\nwithcachetype\n\nIf with_cache_type is not nothing, then the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the model. This is most useful if the optimizer you are constructing does not support the incremental interface (see supports_incremental_interface).\n\nwithbridgetype\n\nIf with_bridge_type is not nothing, the optimizer is wrapped in a Bridges.full_bridge_optimizer, enabling all the bridges defined in the MOI.Bridges submodule with coefficient type with_bridge_type.\n\nIn addition, if the optimizer created by optimizer_constructor does not support the incremental interface (see supports_incremental_interface), then, irrespective of with_cache_type, the optimizer is wrapped in a Utilities.CachingOptimizer to store a cache of the bridged model.\n\nIf with_cache_type and with_bridge_type are both not nothing, then they must be the same type.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.default_cache","page":"Models","title":"MathOptInterface.default_cache","text":"default_cache(optimizer::ModelLike, ::Type{T}) where {T}\n\nReturn a new instance of the default model type to be used as cache for optimizer in a Utilities.CachingOptimizer for holding constraints of coefficient type T. By default, this returns Utilities.UniversalFallback(Utilities.Model{T}()). If copying from a instance of a given model type is faster for optimizer then a new method returning an instance of this model type should be defined.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#Optimizer-attributes","page":"Models","title":"Optimizer attributes","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"AbstractOptimizerAttribute\nSolverName\nSolverVersion\nSilent\nTimeLimitSec\nObjectiveLimit\nSolutionLimit\nRawOptimizerAttribute\nNumberOfThreads\nRawSolver\nAbsoluteGapTolerance\nRelativeGapTolerance\nAutomaticDifferentiationBackend","category":"page"},{"location":"reference/models/#MathOptInterface.AbstractOptimizerAttribute","page":"Models","title":"MathOptInterface.AbstractOptimizerAttribute","text":"AbstractOptimizerAttribute\n\nAbstract supertype for attribute objects that can be used to set or get attributes (properties) of the optimizer.\n\nNotes\n\nThe difference between AbstractOptimizerAttribute and AbstractModelAttribute lies in the behavior of is_empty, empty! and copy_to. Typically optimizer attributes affect only how the model is solved.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolverName","page":"Models","title":"MathOptInterface.SolverName","text":"SolverName()\n\nAn optimizer attribute for the string identifying the solver/optimizer.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolverVersion","page":"Models","title":"MathOptInterface.SolverVersion","text":"SolverVersion()\n\nAn optimizer attribute for the string identifying the version of the solver.\n\nnote: Note\nFor solvers supporting semantic versioning, the SolverVersion should be a string of the form \"vMAJOR.MINOR.PATCH\", so that it can be converted to a Julia VersionNumber (for example, `VersionNumber(\"v1.2.3\")).We do not require Semantic Versioning because some solvers use alternate versioning systems. For example, CPLEX uses Calendar Versioning, so SolverVersion will return a string like \"202001\".\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.Silent","page":"Models","title":"MathOptInterface.Silent","text":"Silent()\n\nAn optimizer attribute for silencing the output of an optimizer. When set to true, it takes precedence over any other attribute controlling verbosity and requires the solver to produce no output. The default value is false which has no effect. In this case the verbosity is controlled by other attributes.\n\nNote\n\nEvery optimizer should have verbosity on by default. For instance, if a solver has a solver-specific log level attribute, the MOI implementation should set it to 1 by default. If the user sets Silent to true, then the log level should be set to 0, even if the user specifically sets a value of log level. If the value of Silent is false then the log level set to the solver is the value given by the user for this solver-specific parameter or 1 if none is given.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.TimeLimitSec","page":"Models","title":"MathOptInterface.TimeLimitSec","text":"TimeLimitSec()\n\nAn optimizer attribute for setting a time limit (in seconds) for an optimization. When set to nothing, it deactivates the solver time limit. The default value is nothing.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveLimit","page":"Models","title":"MathOptInterface.ObjectiveLimit","text":"ObjectiveLimit()\n\nAn optimizer attribute for setting a limit on the objective value.\n\nThe provided limit must be a Union{Real,Nothing}.\n\nWhen set to nothing, the limit reverts to the solver's default.\n\nThe default value is nothing.\n\nThe solver may stop when the ObjectiveValue is better (lower for minimization, higher for maximization) than the ObjectiveLimit. If stopped, the TerminationStatus should be OBJECTIVE_LIMIT.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolutionLimit","page":"Models","title":"MathOptInterface.SolutionLimit","text":"SolutionLimit()\n\nAn optimizer attribute for setting a limit on the number of available feasible solutions.\n\nDefault values\n\nThe provided limit must be a Union{Nothing,Int}.\n\nWhen set to nothing, the limit reverts to the solver's default.\n\nThe default value is nothing.\n\nTermination criteria\n\nThe solver may stop when the ResultCount is larger than or equal to the SolutionLimit. If stopped because of this attribute, the TerminationStatus must be SOLUTION_LIMIT.\n\nSolution quality\n\nThe quality of the available solutions is solver-dependent. The set of resulting solutions is not guaranteed to contain an optimal solution.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RawOptimizerAttribute","page":"Models","title":"MathOptInterface.RawOptimizerAttribute","text":"RawOptimizerAttribute(name::String)\n\nAn optimizer attribute for the solver-specific parameter identified by name.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NumberOfThreads","page":"Models","title":"MathOptInterface.NumberOfThreads","text":"NumberOfThreads()\n\nAn optimizer attribute for setting the number of threads used for an optimization. When set to nothing uses solver default. Values are positive integers. The default value is nothing.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RawSolver","page":"Models","title":"MathOptInterface.RawSolver","text":"RawSolver()\n\nA model attribute for the object that may be used to access a solver-specific API for this optimizer.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.AbsoluteGapTolerance","page":"Models","title":"MathOptInterface.AbsoluteGapTolerance","text":"AbsoluteGapTolerance()\n\nAn optimizer attribute for setting the absolute gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.\n\nTo set a relative gap tolerance, see RelativeGapTolerance.\n\nwarning: Warning\nThe mathematical definition of \"absolute gap\", and its treatment during the optimization, are solver-dependent. However, assuming no other limit nor issue is encountered during the optimization, most solvers that implement this attribute will stop once f - b g_abs, where b is the best bound, f is the best feasible objective value, and g_abs is the absolute gap.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RelativeGapTolerance","page":"Models","title":"MathOptInterface.RelativeGapTolerance","text":"RelativeGapTolerance()\n\nAn optimizer attribute for setting the relative gap tolerance for an optimization. This is an optimizer attribute, and should be set before calling optimize!. When set to nothing (if supported), uses solver default.\n\nIf you are looking for the relative gap of the current best solution, see RelativeGap. If no limit nor issue is encountered during the optimization, the value of RelativeGap should be at most as large as RelativeGapTolerance.\n\n# Before optimizing: set relative gap tolerance\n# set 0.1% relative gap tolerance\nMOI.set(model, MOI.RelativeGapTolerance(), 1e-3)\nMOI.optimize!(model)\n\n# After optimizing (assuming all went well)\n# The relative gap tolerance has not changed...\nMOI.get(model, MOI.RelativeGapTolerance()) # returns 1e-3\n# ... and the relative gap of the obtained solution is smaller or equal to the\n# tolerance\nMOI.get(model, MOI.RelativeGap()) # should return something ≤ 1e-3\n\nwarning: Warning\nThe mathematical definition of \"relative gap\", and its allowed range, are solver-dependent. Typically, solvers expect a value between 0.0 and 1.0.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.AutomaticDifferentiationBackend","page":"Models","title":"MathOptInterface.AutomaticDifferentiationBackend","text":"AutomaticDifferentiationBackend() <: AbstractOptimizerAttribute\n\nAn AbstractOptimizerAttribute for setting the automatic differentiation backend used by the solver.\n\nThe value must be a subtype of Nonlinear.AbstractAutomaticDifferentiation.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/","page":"Models","title":"Models","text":"List of attributes useful for optimizers","category":"page"},{"location":"reference/models/","page":"Models","title":"Models","text":"TerminationStatus\nTerminationStatusCode\nOPTIMIZE_NOT_CALLED\nOPTIMAL\nINFEASIBLE\nDUAL_INFEASIBLE\nLOCALLY_SOLVED\nLOCALLY_INFEASIBLE\nINFEASIBLE_OR_UNBOUNDED\nALMOST_OPTIMAL\nALMOST_INFEASIBLE\nALMOST_DUAL_INFEASIBLE\nALMOST_LOCALLY_SOLVED\nITERATION_LIMIT\nTIME_LIMIT\nNODE_LIMIT\nSOLUTION_LIMIT\nMEMORY_LIMIT\nOBJECTIVE_LIMIT\nNORM_LIMIT\nOTHER_LIMIT\nSLOW_PROGRESS\nNUMERICAL_ERROR\nINVALID_MODEL\nINVALID_OPTION\nINTERRUPTED\nOTHER_ERROR\nPrimalStatus\nDualStatus\nRawStatusString\nResultCount\nObjectiveValue\nDualObjectiveValue\nObjectiveBound\nRelativeGap\nSolveTimeSec\nSimplexIterations\nBarrierIterations\nNodeCount","category":"page"},{"location":"reference/models/#MathOptInterface.TerminationStatus","page":"Models","title":"MathOptInterface.TerminationStatus","text":"TerminationStatus()\n\nA model attribute for the TerminationStatusCode explaining why the optimizer stopped.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.TerminationStatusCode","page":"Models","title":"MathOptInterface.TerminationStatusCode","text":"TerminationStatusCode\n\nAn Enum of possible values for the TerminationStatus attribute. This attribute is meant to explain the reason why the optimizer stopped executing in the most recent call to optimize!.\n\nValues\n\nPossible values are:\n\nOPTIMIZE_NOT_CALLED: The algorithm has not started.\nOPTIMAL: The algorithm found a globally optimal solution.\nINFEASIBLE: The algorithm concluded that no feasible solution exists.\nDUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.\nLOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.\nLOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.\nINFEASIBLE_OR_UNBOUNDED: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.\nALMOST_OPTIMAL: The algorithm found a globally optimal solution to relaxed tolerances.\nALMOST_INFEASIBLE: The algorithm concluded that no feasible solution exists within relaxed tolerances.\nALMOST_DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.\nALMOST_LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.\nITERATION_LIMIT: An iterative algorithm stopped after conducting the maximum number of iterations.\nTIME_LIMIT: The algorithm stopped after a user-specified computation time.\nNODE_LIMIT: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.\nSOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.\nMEMORY_LIMIT: The algorithm stopped because it ran out of memory.\nOBJECTIVE_LIMIT: The algorithm stopped because it found a solution better than a minimum limit set by the user.\nNORM_LIMIT: The algorithm stopped because the norm of an iterate became too large.\nOTHER_LIMIT: The algorithm stopped due to a limit not covered by one of the _LIMIT_ statuses above.\nSLOW_PROGRESS: The algorithm stopped because it was unable to continue making progress towards the solution.\nNUMERICAL_ERROR: The algorithm stopped because it encountered unrecoverable numerical error.\nINVALID_MODEL: The algorithm stopped because the model is invalid.\nINVALID_OPTION: The algorithm stopped because it was provided an invalid option.\nINTERRUPTED: The algorithm stopped because of an interrupt signal.\nOTHER_ERROR: The algorithm stopped because of an error not covered by one of the statuses defined above.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.OPTIMIZE_NOT_CALLED","page":"Models","title":"MathOptInterface.OPTIMIZE_NOT_CALLED","text":"OPTIMIZE_NOT_CALLED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOPTIMIZE_NOT_CALLED: The algorithm has not started.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OPTIMAL","page":"Models","title":"MathOptInterface.OPTIMAL","text":"OPTIMAL::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOPTIMAL: The algorithm found a globally optimal solution.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBLE","page":"Models","title":"MathOptInterface.INFEASIBLE","text":"INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINFEASIBLE: The algorithm concluded that no feasible solution exists.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.DUAL_INFEASIBLE","page":"Models","title":"MathOptInterface.DUAL_INFEASIBLE","text":"DUAL_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nDUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.LOCALLY_SOLVED","page":"Models","title":"MathOptInterface.LOCALLY_SOLVED","text":"LOCALLY_SOLVED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nLOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.LOCALLY_INFEASIBLE","page":"Models","title":"MathOptInterface.LOCALLY_INFEASIBLE","text":"LOCALLY_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nLOCALLY_INFEASIBLE: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBLE_OR_UNBOUNDED","page":"Models","title":"MathOptInterface.INFEASIBLE_OR_UNBOUNDED","text":"INFEASIBLE_OR_UNBOUNDED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINFEASIBLE_OR_UNBOUNDED: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_OPTIMAL","page":"Models","title":"MathOptInterface.ALMOST_OPTIMAL","text":"ALMOST_OPTIMAL::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_OPTIMAL: The algorithm found a globally optimal solution to relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_INFEASIBLE","page":"Models","title":"MathOptInterface.ALMOST_INFEASIBLE","text":"ALMOST_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_INFEASIBLE: The algorithm concluded that no feasible solution exists within relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_DUAL_INFEASIBLE","page":"Models","title":"MathOptInterface.ALMOST_DUAL_INFEASIBLE","text":"ALMOST_DUAL_INFEASIBLE::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_DUAL_INFEASIBLE: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ALMOST_LOCALLY_SOLVED","page":"Models","title":"MathOptInterface.ALMOST_LOCALLY_SOLVED","text":"ALMOST_LOCALLY_SOLVED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nALMOST_LOCALLY_SOLVED: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.ITERATION_LIMIT","page":"Models","title":"MathOptInterface.ITERATION_LIMIT","text":"ITERATION_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nITERATION_LIMIT: An iterative algorithm stopped after conducting the maximum number of iterations.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.TIME_LIMIT","page":"Models","title":"MathOptInterface.TIME_LIMIT","text":"TIME_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nTIME_LIMIT: The algorithm stopped after a user-specified computation time.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NODE_LIMIT","page":"Models","title":"MathOptInterface.NODE_LIMIT","text":"NODE_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nNODE_LIMIT: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.SOLUTION_LIMIT","page":"Models","title":"MathOptInterface.SOLUTION_LIMIT","text":"SOLUTION_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nSOLUTION_LIMIT: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.MEMORY_LIMIT","page":"Models","title":"MathOptInterface.MEMORY_LIMIT","text":"MEMORY_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nMEMORY_LIMIT: The algorithm stopped because it ran out of memory.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OBJECTIVE_LIMIT","page":"Models","title":"MathOptInterface.OBJECTIVE_LIMIT","text":"OBJECTIVE_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOBJECTIVE_LIMIT: The algorithm stopped because it found a solution better than a minimum limit set by the user.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NORM_LIMIT","page":"Models","title":"MathOptInterface.NORM_LIMIT","text":"NORM_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nNORM_LIMIT: The algorithm stopped because the norm of an iterate became too large.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OTHER_LIMIT","page":"Models","title":"MathOptInterface.OTHER_LIMIT","text":"OTHER_LIMIT::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOTHER_LIMIT: The algorithm stopped due to a limit not covered by one of the _LIMIT_ statuses above.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.SLOW_PROGRESS","page":"Models","title":"MathOptInterface.SLOW_PROGRESS","text":"SLOW_PROGRESS::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nSLOW_PROGRESS: The algorithm stopped because it was unable to continue making progress towards the solution.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NUMERICAL_ERROR","page":"Models","title":"MathOptInterface.NUMERICAL_ERROR","text":"NUMERICAL_ERROR::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nNUMERICAL_ERROR: The algorithm stopped because it encountered unrecoverable numerical error.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INVALID_MODEL","page":"Models","title":"MathOptInterface.INVALID_MODEL","text":"INVALID_MODEL::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINVALID_MODEL: The algorithm stopped because the model is invalid.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INVALID_OPTION","page":"Models","title":"MathOptInterface.INVALID_OPTION","text":"INVALID_OPTION::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINVALID_OPTION: The algorithm stopped because it was provided an invalid option.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INTERRUPTED","page":"Models","title":"MathOptInterface.INTERRUPTED","text":"INTERRUPTED::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nINTERRUPTED: The algorithm stopped because of an interrupt signal.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OTHER_ERROR","page":"Models","title":"MathOptInterface.OTHER_ERROR","text":"OTHER_ERROR::TerminationStatusCode\n\nAn instance of the TerminationStatusCode enum.\n\nOTHER_ERROR: The algorithm stopped because of an error not covered by one of the statuses defined above.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.PrimalStatus","page":"Models","title":"MathOptInterface.PrimalStatus","text":"PrimalStatus(result_index::Int = 1)\n\nA model attribute for the ResultStatusCode of the primal result result_index. If result_index is omitted, it defaults to 1.\n\nSee ResultCount for information on how the results are ordered.\n\nIf result_index is larger than the value of ResultCount then NO_SOLUTION is returned.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.DualStatus","page":"Models","title":"MathOptInterface.DualStatus","text":"DualStatus(result_index::Int = 1)\n\nA model attribute for the ResultStatusCode of the dual result result_index. If result_index is omitted, it defaults to 1.\n\nSee ResultCount for information on how the results are ordered.\n\nIf result_index is larger than the value of ResultCount then NO_SOLUTION is returned.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RawStatusString","page":"Models","title":"MathOptInterface.RawStatusString","text":"RawStatusString()\n\nA model attribute for a solver specific string explaining why the optimizer stopped.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ResultCount","page":"Models","title":"MathOptInterface.ResultCount","text":"ResultCount()\n\nA model attribute for the number of results available.\n\nOrder of solutions\n\nA number of attributes contain an index, result_index, which is used to refer to one of the available results. Thus, result_index must be an integer between 1 and the number of available results.\n\nAs a general rule, the first result (result_index=1) is the most important result (for example, an optimal solution or an infeasibility certificate). Other results will typically be alternate solutions that the solver found during the search for the first result.\n\nIf a (local) optimal solution is available, that is, TerminationStatus is OPTIMAL or LOCALLY_SOLVED, the first result must correspond to the (locally) optimal solution. Other results may be alternative optimal solutions, or they may be other suboptimal solutions; use ObjectiveValue to distinguish between them.\n\nIf a primal or dual infeasibility certificate is available, that is, TerminationStatus is INFEASIBLE or DUAL_INFEASIBLE and the corresponding PrimalStatus or DualStatus is INFEASIBILITY_CERTIFICATE, then the first result must be a certificate. Other results may be alternate certificates, or infeasible points.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveValue","page":"Models","title":"MathOptInterface.ObjectiveValue","text":"ObjectiveValue(result_index::Int = 1)\n\nA model attribute for the objective value of the primal solution result_index.\n\nIf the solver does not have a primal value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check PrimalStatus before accessing the ObjectiveValue attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.DualObjectiveValue","page":"Models","title":"MathOptInterface.DualObjectiveValue","text":"DualObjectiveValue(result_index::Int = 1)\n\nA model attribute for the value of the objective function of the dual problem for the result_indexth dual result.\n\nIf the solver does not have a dual value for the objective because the result_index is beyond the available solutions (whose number is indicated by the ResultCount attribute), getting this attribute must throw a ResultIndexBoundsError. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check DualStatus before accessing the DualObjectiveValue attribute.\n\nSee ResultCount for information on how the results are ordered.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ObjectiveBound","page":"Models","title":"MathOptInterface.ObjectiveBound","text":"ObjectiveBound()\n\nA model attribute for the best known bound on the optimal objective value.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.RelativeGap","page":"Models","title":"MathOptInterface.RelativeGap","text":"RelativeGap()\n\nA model attribute for the final relative optimality gap.\n\nwarning: Warning\nThe definition of this gap is solver-dependent. However, most solvers implementing this attribute define the relative gap as some variation of fracb-ff, where b is the best bound and f is the best feasible objective value.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SolveTimeSec","page":"Models","title":"MathOptInterface.SolveTimeSec","text":"SolveTimeSec()\n\nA model attribute for the total elapsed solution time (in seconds) as reported by the optimizer.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.SimplexIterations","page":"Models","title":"MathOptInterface.SimplexIterations","text":"SimplexIterations()\n\nA model attribute for the cumulative number of simplex iterations during the optimization process.\n\nFor a mixed-integer program (MIP), the return value is the total simplex iterations for all nodes.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.BarrierIterations","page":"Models","title":"MathOptInterface.BarrierIterations","text":"BarrierIterations()\n\nA model attribute for the cumulative number of barrier iterations while solving a problem.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NodeCount","page":"Models","title":"MathOptInterface.NodeCount","text":"NodeCount()\n\nA model attribute for the total number of branch-and-bound nodes explored while solving a mixed-integer program (MIP).\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#ResultStatusCode","page":"Models","title":"ResultStatusCode","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"ResultStatusCode\nNO_SOLUTION\nFEASIBLE_POINT\nNEARLY_FEASIBLE_POINT\nINFEASIBLE_POINT\nINFEASIBILITY_CERTIFICATE\nNEARLY_INFEASIBILITY_CERTIFICATE\nREDUCTION_CERTIFICATE\nNEARLY_REDUCTION_CERTIFICATE\nUNKNOWN_RESULT_STATUS\nOTHER_RESULT_STATUS","category":"page"},{"location":"reference/models/#MathOptInterface.ResultStatusCode","page":"Models","title":"MathOptInterface.ResultStatusCode","text":"ResultStatusCode\n\nAn Enum of possible values for the PrimalStatus and DualStatus attributes.\n\nThe values indicate how to interpret the result vector.\n\nValues\n\nPossible values are:\n\nNO_SOLUTION: the result vector is empty.\nFEASIBLE_POINT: the result vector is a feasible point.\nNEARLY_FEASIBLE_POINT: the result vector is feasible if some constraint tolerances are relaxed.\nINFEASIBLE_POINT: the result vector is an infeasible point.\nINFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.\nNEARLY_INFEASIBILITY_CERTIFICATE: the result satisfies a relaxed criterion for a certificate of infeasibility.\nREDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.\nNEARLY_REDUCTION_CERTIFICATE: the result satisfies a relaxed criterion for an ill-posed certificate.\nUNKNOWN_RESULT_STATUS: the result vector contains a solution with an unknown interpretation.\nOTHER_RESULT_STATUS: the result vector contains a solution with an interpretation not covered by one of the statuses defined above\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NO_SOLUTION","page":"Models","title":"MathOptInterface.NO_SOLUTION","text":"NO_SOLUTION::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNO_SOLUTION: the result vector is empty.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.FEASIBLE_POINT","page":"Models","title":"MathOptInterface.FEASIBLE_POINT","text":"FEASIBLE_POINT::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nFEASIBLE_POINT: the result vector is a feasible point.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NEARLY_FEASIBLE_POINT","page":"Models","title":"MathOptInterface.NEARLY_FEASIBLE_POINT","text":"NEARLY_FEASIBLE_POINT::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNEARLY_FEASIBLE_POINT: the result vector is feasible if some constraint tolerances are relaxed.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBLE_POINT","page":"Models","title":"MathOptInterface.INFEASIBLE_POINT","text":"INFEASIBLE_POINT::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nINFEASIBLE_POINT: the result vector is an infeasible point.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.INFEASIBILITY_CERTIFICATE","page":"Models","title":"MathOptInterface.INFEASIBILITY_CERTIFICATE","text":"INFEASIBILITY_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nINFEASIBILITY_CERTIFICATE: the result vector is an infeasibility certificate. If the PrimalStatus is INFEASIBILITY_CERTIFICATE, then the primal result vector is a certificate of dual infeasibility. If the DualStatus is INFEASIBILITY_CERTIFICATE, then the dual result vector is a proof of primal infeasibility.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NEARLY_INFEASIBILITY_CERTIFICATE","page":"Models","title":"MathOptInterface.NEARLY_INFEASIBILITY_CERTIFICATE","text":"NEARLY_INFEASIBILITY_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNEARLY_INFEASIBILITY_CERTIFICATE: the result satisfies a relaxed criterion for a certificate of infeasibility.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.REDUCTION_CERTIFICATE","page":"Models","title":"MathOptInterface.REDUCTION_CERTIFICATE","text":"REDUCTION_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nREDUCTION_CERTIFICATE: the result vector is an ill-posed certificate; see this article for details. If the PrimalStatus is REDUCTION_CERTIFICATE, then the primal result vector is a proof that the dual problem is ill-posed. If the DualStatus is REDUCTION_CERTIFICATE, then the dual result vector is a proof that the primal is ill-posed.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.NEARLY_REDUCTION_CERTIFICATE","page":"Models","title":"MathOptInterface.NEARLY_REDUCTION_CERTIFICATE","text":"NEARLY_REDUCTION_CERTIFICATE::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nNEARLY_REDUCTION_CERTIFICATE: the result satisfies a relaxed criterion for an ill-posed certificate.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.UNKNOWN_RESULT_STATUS","page":"Models","title":"MathOptInterface.UNKNOWN_RESULT_STATUS","text":"UNKNOWN_RESULT_STATUS::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nUNKNOWN_RESULT_STATUS: the result vector contains a solution with an unknown interpretation.\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.OTHER_RESULT_STATUS","page":"Models","title":"MathOptInterface.OTHER_RESULT_STATUS","text":"OTHER_RESULT_STATUS::ResultStatusCode\n\nAn instance of the ResultStatusCode enum.\n\nOTHER_RESULT_STATUS: the result vector contains a solution with an interpretation not covered by one of the statuses defined above\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#Conflict-Status","page":"Models","title":"Conflict Status","text":"","category":"section"},{"location":"reference/models/","page":"Models","title":"Models","text":"compute_conflict!\nConflictStatus\nConstraintConflictStatus\nConflictStatusCode\nConflictParticipationStatusCode\nNOT_IN_CONFLICT\nIN_CONFLICT\nMAYBE_IN_CONFLICT","category":"page"},{"location":"reference/models/#MathOptInterface.compute_conflict!","page":"Models","title":"MathOptInterface.compute_conflict!","text":"compute_conflict!(optimizer::AbstractOptimizer)\n\nComputes a minimal subset of constraints such that the model with the other constraint removed is still infeasible.\n\nSome solvers call a set of conflicting constraints an Irreducible Inconsistent Subsystem (IIS).\n\nSee also ConflictStatus and ConstraintConflictStatus.\n\nNote\n\nIf the model is modified after a call to compute_conflict!, the implementor is not obliged to purge the conflict. Any calls to the above attributes may return values for the original conflict without a warning. Similarly, when modifying the model, the conflict can be discarded.\n\n\n\n\n\n","category":"function"},{"location":"reference/models/#MathOptInterface.ConflictStatus","page":"Models","title":"MathOptInterface.ConflictStatus","text":"ConflictStatus()\n\nA model attribute for the ConflictStatusCode explaining why the conflict refiner stopped when computing the conflict.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ConstraintConflictStatus","page":"Models","title":"MathOptInterface.ConstraintConflictStatus","text":"ConstraintConflictStatus()\n\nA constraint attribute indicating whether the constraint participates in the conflict. Its type is ConflictParticipationStatusCode.\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ConflictStatusCode","page":"Models","title":"MathOptInterface.ConflictStatusCode","text":"ConflictStatusCode\n\nAn Enum of possible values for the ConflictStatus attribute. This attribute is meant to explain the reason why the conflict finder stopped executing in the most recent call to compute_conflict!.\n\nPossible values are:\n\nCOMPUTE_CONFLICT_NOT_CALLED: the function compute_conflict! has not yet been called\nNO_CONFLICT_EXISTS: there is no conflict because the problem is feasible\nNO_CONFLICT_FOUND: the solver could not find a conflict\nCONFLICT_FOUND: at least one conflict could be found\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.ConflictParticipationStatusCode","page":"Models","title":"MathOptInterface.ConflictParticipationStatusCode","text":"ConflictParticipationStatusCode\n\nAn Enum of possible values for the ConstraintConflictStatus attribute. This attribute is meant to indicate whether a given constraint participates or not in the last computed conflict.\n\nValues\n\nPossible values are:\n\nNOT_IN_CONFLICT: the constraint does not participate in the conflict\nIN_CONFLICT: the constraint participates in the conflict\nMAYBE_IN_CONFLICT: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict\n\n\n\n\n\n","category":"type"},{"location":"reference/models/#MathOptInterface.NOT_IN_CONFLICT","page":"Models","title":"MathOptInterface.NOT_IN_CONFLICT","text":"NOT_IN_CONFLICT::ConflictParticipationStatusCode\n\nAn instance of the ConflictParticipationStatusCode enum.\n\nNOT_IN_CONFLICT: the constraint does not participate in the conflict\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.IN_CONFLICT","page":"Models","title":"MathOptInterface.IN_CONFLICT","text":"IN_CONFLICT::ConflictParticipationStatusCode\n\nAn instance of the ConflictParticipationStatusCode enum.\n\nIN_CONFLICT: the constraint participates in the conflict\n\n\n\n\n\n","category":"constant"},{"location":"reference/models/#MathOptInterface.MAYBE_IN_CONFLICT","page":"Models","title":"MathOptInterface.MAYBE_IN_CONFLICT","text":"MAYBE_IN_CONFLICT::ConflictParticipationStatusCode\n\nAn instance of the ConflictParticipationStatusCode enum.\n\nMAYBE_IN_CONFLICT: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict\n\n\n\n\n\n","category":"constant"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Utilities/overview/#The-Utilities-submodule","page":"Overview","title":"The Utilities submodule","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The Utilities submodule provides a variety of functions and datastructures for managing MOI.ModelLike objects.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.Model","page":"Overview","title":"Utilities.Model","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Utilities.Model provides an implementation of a ModelLike that efficiently supports all functions and sets defined within MOI. However, given the extensibility of MOI, this might not cover all use cases.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Create a model as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.UniversalFallback","page":"Overview","title":"Utilities.UniversalFallback","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Utilities.UniversalFallback is a layer that sits on top of any ModelLike and provides non-specialized (slower) fallbacks for constraints and attributes that the underlying ModelLike does not support.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For example, Utilities.Model doesn't support some variable attributes like VariablePrimalStart, so JuMP uses a combination of Universal fallback and Utilities.Model as a generic problem cache:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nMOIU.UniversalFallback{MOIU.Model{Float64}}\nfallback for MOIU.Model{Float64}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nAdding a UniversalFallback means that your model will now support all constraints, even if the inner-model does not. This can lead to unexpected behavior.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.@model","page":"Overview","title":"Utilities.@model","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For advanced use cases that need efficient support for functions and sets defined outside of MOI (but still known at compile time), we provide the Utilities.@model macro.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The @model macro takes a name (for a new type, which must not exist yet), eight tuples specifying the types of constraints that are supported, and then a Bool indicating the type is a subtype of MOI.AbstractOptimizer (if true) or MOI.ModelLike (if false).","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The eight tuples are in the following order:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Un-typed scalar sets, for example, Integer\nTyped scalar sets, for example, LessThan\nUn-typed vector sets, for example, Nonnegatives\nTyped vector sets, for example, PowerCone\nUn-typed scalar functions, for example, VariableIndex\nTyped scalar functions, for example, ScalarAffineFunction\nUn-typed vector functions, for example, VectorOfVariables\nTyped vector functions, for example, VectorAffineFunction","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The tuples can contain more than one element. Typed-sets must be specified without their type parameter, for example, MOI.LessThan, not MOI.LessThan{Float64}.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Here is an example:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.@model(\n MyNewModel,\n (MOI.Integer,), # Un-typed scalar sets\n (MOI.GreaterThan,), # Typed scalar sets\n (MOI.Nonnegatives,), # Un-typed vector sets\n (MOI.PowerCone,), # Typed vector sets\n (MOI.VariableIndex,), # Un-typed scalar functions\n (MOI.ScalarAffineFunction,), # Typed scalar functions\n (MOI.VectorOfVariables,), # Un-typed vector functions\n (MOI.VectorAffineFunction,), # Typed vector functions\n true, # <:MOI.AbstractOptimizer?\n )\nMathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MyNewModelFunctionConstraints{T}} where T\n\njulia> model = MyNewModel{Float64}()\nMOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MyNewModelFunctionConstraints{Float64}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nMyNewModel supports every VariableIndex-in-Set constraint, as well as VariableIndex, ScalarAffineFunction, and ScalarQuadraticFunction objective functions. Implement MOI.supports as needed to forbid constraint and objective function combinations.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"As another example, PATHSolver, which only supports VectorAffineFunction-in-Complements defines its optimizer as:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.@model(\n PathOptimizer,\n (), # Scalar sets\n (), # Typed scalar sets\n (MOI.Complements,), # Vector sets\n (), # Typed vector sets\n (), # Scalar functions\n (), # Typed scalar functions\n (), # Vector functions\n (MOI.VectorAffineFunction,), # Typed vector functions\n true, # is_optimizer\n )\nMathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{T}, MathOptInterface.Complements}} where T","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"However, PathOptimizer does not support some VariableIndex-in-Set constraints, so we must explicitly define:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> function MOI.supports_constraint(\n ::PathOptimizer,\n ::Type{MOI.VariableIndex},\n ::Type{Union{<:MOI.Semiinteger,MOI.Semicontinuous,MOI.ZeroOne,MOI.Integer}}\n )\n return false\n end","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Finally, PATH doesn't support an objective function, so we need to add:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.supports(::PathOptimizer, ::MOI.ObjectiveFunction) = false","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nThis macro creates a new type, so it must be called from the top-level of a module, for example, it cannot be called from inside a function.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.CachingOptimizer","page":"Overview","title":"Utilities.CachingOptimizer","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"A [Utilities.CachingOptimizer] is an MOI layer that abstracts the difference between solvers that support incremental modification (for example, they support adding variables one-by-one), and solvers that require the entire problem in a single API call (for example, they only accept the A, b and c matrices of a linear program).","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"It has two parts:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"A cache, where the model can be built and modified incrementally\nAn optimizer, which is used to solve the problem","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.CachingOptimizer(\n MOI.Utilities.Model{Float64}(),\n PathOptimizer{Float64}(),\n )\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"A Utilities.CachingOptimizer may be in one of three possible states:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"NO_OPTIMIZER: The CachingOptimizer does not have any optimizer.\nEMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer, and it is not synchronized with the cached model. Modifications are forwarded to the cache, but not to the optimizer.\nATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model. Modifications are forwarded to the optimizer. If the optimizer does not support modifications, and error will be thrown.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.attach_optimizer to go from EMPTY_OPTIMIZER to ATTACHED_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.attach_optimizer(model)\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state ATTACHED_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"info: Info\nYou must be in ATTACHED_OPTIMIZER to use optimize!.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.reset_optimizer to go from ATTACHED_OPTIMIZER to EMPTY_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.reset_optimizer(model)\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"info: Info\nCalling MOI.empty!(model) also resets the state to EMPTY_OPTIMIZER. So after emptying a model, the modification will only be applied to the cache.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.drop_optimizer to go from any state to NO_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.drop_optimizer(model)\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state NO_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer nothing","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Pass an empty optimizer to Utilities.reset_optimizer to go from NO_OPTIMIZER to EMPTY_OPTIMIZER:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())\n\njulia> model\nMOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode AUTOMATIC\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Deciding when to attach and reset the optimizer is tedious, and you will often write code like this:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"try\n # modification\ncatch\n MOI.Utilities.reset_optimizer(model)\n # Re-try modification\nend","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"To make this easier, Utilities.CachingOptimizer has two modes of operation:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"AUTOMATIC: The CachingOptimizer changes its state when necessary. Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.\nMANUAL: The user must change the state of the CachingOptimizer. Attempting to perform an operation in the incorrect state results in an error.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"By default, AUTOMATIC mode is chosen. However, you can create a CachingOptimizer in MANUAL mode as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.CachingOptimizer(\n MOI.Utilities.Model{Float64}(),\n MOI.Utilities.MANUAL,\n )\nMOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}\nin state NO_OPTIMIZER\nin mode MANUAL\nwith model cache MOIU.Model{Float64}\nwith optimizer nothing\n\njulia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())\n\njulia> model\nMOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}\nin state EMPTY_OPTIMIZER\nin mode MANUAL\nwith model cache MOIU.Model{Float64}\nwith optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}","category":"page"},{"location":"submodules/Utilities/overview/#Printing","page":"Overview","title":"Printing","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use print to print the formulation of the model.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.set(model, MOI.VariableName(), x, \"x_var\")\n\njulia> MOI.add_constraint(model, x, MOI.ZeroOne())\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)\n\njulia> MOI.set(model, MOI.ObjectiveFunction{typeof(x)}(), x)\n\njulia> MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)\n\njulia> print(model)\nMaximize VariableIndex:\n x_var\n\nSubject to:\n\nVariableIndex-in-ZeroOne\n x_var ∈ {0, 1}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Use Utilities.latex_formulation to display the model in LaTeX form:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> MOI.Utilities.latex_formulation(model)\n$$ \\begin{aligned}\n\\max\\quad & x\\_var \\\\\n\\text{Subject to}\\\\\n & \\text{VariableIndex-in-ZeroOne} \\\\\n & x\\_var \\in \\{0, 1\\} \\\\\n\\end{aligned} $$","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"tip: Tip\nIn IJulia, calling print or ending a cell with Utilities.latex_formulation will render the model in LaTeX.","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.PenaltyRelaxation","page":"Overview","title":"Utilities.PenaltyRelaxation","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Pass Utilities.PenaltyRelaxation to modify to relax the problem by adding penalized slack variables to the constraints. This is helpful when debugging sources of infeasible models.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> MOI.set(model, MOI.VariableName(), x, \"x\")\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 2.0)));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 x - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> map[c]\n0.0 + 1.0 MOI.VariableIndex(2)","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"You can also modify a single constraint using Utilities.ScalarPenaltyRelaxation:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"julia> model = MOI.Utilities.Model{Float64}();\n\njulia> x = MOI.add_variable(model);\n\njulia> MOI.set(model, MOI.VariableName(), x, \"x\")\n\njulia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));\n\njulia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));\n\njulia> print(model)\nMinimize ScalarAffineFunction{Float64}:\n 0.0 + 2.0 v[2]\n\nSubject to:\n\nScalarAffineFunction{Float64}-in-LessThan{Float64}\n 0.0 + 1.0 x - 1.0 v[2] <= 2.0\n\nVariableIndex-in-GreaterThan{Float64}\n v[2] >= 0.0\n\njulia> f\n0.0 + 1.0 MOI.VariableIndex(2)","category":"page"},{"location":"submodules/Utilities/overview/#Utilities.MatrixOfConstraints","page":"Overview","title":"Utilities.MatrixOfConstraints","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The constraints of Utilities.Model are stored as a vector of tuples of function and set in a Utilities.VectorOfConstraints. Other representations can be used by parameterizing the type Utilities.GenericModel (resp. Utilities.GenericOptimizer). For instance, if all non-VariableIndex constraints are affine, the coefficients of all the constraints can be stored in a single sparse matrix using Utilities.MatrixOfConstraints. The constraints storage can even be customized up to a point where it exactly matches the storage of the solver of interest, in which case copy_to can be implemented for the solver by calling copy_to to this custom model.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For instance, Clp defines the following model:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"MOI.Utilities.@product_of_scalar_sets(LP, MOI.EqualTo{T}, MOI.LessThan{T}, MOI.GreaterThan{T})\nconst Model = MOI.Utilities.GenericModel{\n Float64,\n MOI.Utilities.MatrixOfConstraints{\n Float64,\n MOI.Utilities.MutableSparseMatrixCSC{Float64,Cint,MOI.Utilities.ZeroBasedIndexing},\n MOI.Utilities.Hyperrectangle{Float64},\n LP{Float64},\n },\n}","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The copy_to operation can now be implemented as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"function _copy_to(dest::Optimizer, src::Model)\n @assert MOI.is_empty(dest)\n A = src.constraints.coefficients\n row_bounds = src.constraints.constants\n Clp_loadProblem(\n dest,\n A.n,\n A.m,\n A.colptr,\n A.rowval,\n A.nzval,\n src.lower_bound,\n src.upper_bound,\n # (...) objective vector (omitted),\n row_bounds.lower,\n row_bounds.upper,\n )\n # Set objective sense and constant (omitted)\n return\nend\n\nfunction MOI.copy_to(dest::Optimizer, src::Model)\n _copy_to(dest, src)\n return MOI.Utilities.identity_index_map(src)\nend\n\nfunction MOI.copy_to(\n dest::Optimizer,\n src::MOI.Utilities.UniversalFallback{Model},\n)\n # Copy attributes from `src` to `dest` and error in case any unsupported\n # constraints or attributes are set in `UniversalFallback`.\n return MOI.copy_to(dest, src.model)\nend\n\nfunction MOI.copy_to(\n dest::Optimizer,\n src::MOI.ModelLike,\n)\n model = Model()\n index_map = MOI.copy_to(model, src)\n _copy_to(dest, model)\n return index_map\nend","category":"page"},{"location":"submodules/Utilities/overview/#ModelFilter","page":"Overview","title":"ModelFilter","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"Utilities provides Utilities.ModelFilter as a useful tool to copy a subset of a model. For example, given an infeasible model, we can copy the irreducible infeasible subsystem (for models implementing ConstraintConflictStatus) as follows:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"my_filter(::Any) = true\nfunction my_filter(ci::MOI.ConstraintIndex)\n status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)\n return status != MOI.NOT_IN_CONFLICT\nend\nfiltered_src = MOI.Utilities.ModelFilter(my_filter, src)\nindex_map = MOI.copy_to(dest, filtered_src)","category":"page"},{"location":"submodules/Utilities/overview/#Fallbacks","page":"Overview","title":"Fallbacks","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The value of some attributes can be inferred from the value of other attributes.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"For example, the value of ObjectiveValue can be computed using ObjectiveFunction and VariablePrimal.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"When a solver gives direct access to an attribute, it is better to return this value. However, if this is not the case, Utilities.get_fallback can be used instead. For example:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"function MOI.get(model::Optimizer, attr::MOI.ObjectiveFunction)\n return MOI.Utilities.get_fallback(model, attr)\nend","category":"page"},{"location":"submodules/Utilities/overview/#DoubleDicts","page":"Overview","title":"DoubleDicts","text":"","category":"section"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"When writing MOI interfaces, we often need to handle situations in which we map ConstraintIndexs to different values. For example, to a string for ConstraintName.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"One option is to use a dictionary like Dict{MOI.ConstraintIndex,String}. However, this incurs a performance cost because the key is not a concrete type.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The DoubleDicts submodule helps this situation by providing two types main types Utilities.DoubleDicts.DoubleDict and Utilities.DoubleDicts.IndexDoubleDict. These types act like normal dictionaries, but internally they use more efficient dictionaries specialized to the type of the function-set pair.","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"The most common usage of a DoubleDict is in the index_map returned by copy_to. Performance can be improved, by using a function barrier. That is, instead of code like:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"index_map = MOI.copy_to(dest, src)\nfor (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())\n for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())\n dest_ci = index_map[ci]\n # ...\n end\nend","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"use instead:","category":"page"},{"location":"submodules/Utilities/overview/","page":"Overview","title":"Overview","text":"function function_barrier(\n dest,\n src,\n index_map::MOI.Utilities.DoubleDicts.IndexDoubleDictInner{F,S},\n) where {F,S}\n for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())\n dest_ci = index_map[ci]\n # ...\n end\n return\nend\n\nindex_map = MOI.copy_to(dest, src)\nfor (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())\n function_barrier(dest, src, index_map[F, S])\nend","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Nonlinear/overview/#nonlinear_developers","page":"Overview","title":"Nonlinear","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nThe Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The Nonlinear submodule contains data structures and functions for working with a nonlinear optimization problem in the form of an expression graph. This page explains the API and describes the rationale behind its design.","category":"page"},{"location":"submodules/Nonlinear/overview/#Standard-form","page":"Overview","title":"Standard form","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear programs (NLPs) are a class of optimization problems in which some of the constraints or the objective function are nonlinear:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"beginalign\n min_x in mathbbR^n f_0(x) \n textst l_j le f_j(x) le u_j j = 1 ldots m\nendalign","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"There may be additional constraints, as well as things like variable bounds and integrality restrictions, but we do not consider them here because they are best dealt with by other components of MathOptInterface.","category":"page"},{"location":"submodules/Nonlinear/overview/#API-overview","page":"Overview","title":"API overview","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The core element of the Nonlinear submodule is Nonlinear.Model:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> const Nonlinear = MOI.Nonlinear;\n\njulia> model = Nonlinear.Model()\nA Nonlinear.Model with:\n 0 objectives\n 0 parameters\n 0 expressions\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Model is a mutable struct that stores all of the nonlinear information added to the model.","category":"page"},{"location":"submodules/Nonlinear/overview/#Decision-variables","page":"Overview","title":"Decision variables","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Decision variables are represented by VariableIndexes. The user is responsible for creating these using MOI.VariableIndex(i), where i is the column associated with the variable.","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Expressions","page":"Overview","title":"Expressions","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The input data structure is a Julia Expr. The input expressions can incorporate VariableIndexes, but these must be interpolated into the expression with $:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> input = :(1 + sin($x)^2)\n:(1 + sin(MathOptInterface.VariableIndex(1)) ^ 2)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"There are a number of restrictions on the input Expr:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"It cannot contain macros\nIt cannot contain broadcasting\nIt cannot contain splatting (except in limited situations)\nIt cannot contain linear algebra, such as matrix-vector products\nIt cannot contain generator expressions, including sum(i for i in S)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Given an input expression, add an expression using Nonlinear.add_expression:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> expr = Nonlinear.add_expression(model, input)\nMathOptInterface.Nonlinear.ExpressionIndex(1)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The return value, expr, is a Nonlinear.ExpressionIndex that can then be interpolated into other input expressions.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Looking again at model, we see:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> model\nA Nonlinear.Model with:\n 0 objectives\n 0 parameters\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Parameters","page":"Overview","title":"Parameters","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In addition to constant literals like 1 or 1.23, you can create parameters. Parameters are placeholders whose values can change before passing the expression to the solver. Create a parameter using Nonlinear.add_parameter, which accepts a default value:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> p = Nonlinear.add_parameter(model, 1.23)\nMathOptInterface.Nonlinear.ParameterIndex(1)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The return value, p, is a Nonlinear.ParameterIndex that can then be interpolated into other input expressions.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Looking again at model, we see:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> model\nA Nonlinear.Model with:\n 0 objectives\n 1 parameter\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Update a parameter as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> model[p]\n1.23\n\njulia> model[p] = 4.56\n4.56\n\njulia> model[p]\n4.56","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Objectives","page":"Overview","title":"Objectives","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Set a nonlinear objective using Nonlinear.set_objective:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.set_objective(model, :($p + $expr + $x))\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Clear a nonlinear objective by passing nothing:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.set_objective(model, nothing)\n\njulia> model\nA Nonlinear.Model with:\n 0 objectives\n 1 parameter\n 1 expression\n 0 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"But we'll re-add the objective for later:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.set_objective(model, :($p + $expr + $x));","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_Constraints","page":"Overview","title":"Constraints","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Add a constraint using Nonlinear.add_constraint:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> c = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.LessThan(2.0))\nMathOptInterface.Nonlinear.ConstraintIndex(1)\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 1 constraint","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The return value, c, is a Nonlinear.ConstraintIndex that is a unique identifier for the constraint. Interval constraints are also supported:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> c2 = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.Interval(-1.0, 2.0))\nMathOptInterface.Nonlinear.ConstraintIndex(2)\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 2 constraints","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Delete a constraint using Nonlinear.delete:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> Nonlinear.delete(model, c2)\n\njulia> model\nA Nonlinear.Model with:\n 1 objective\n 1 parameter\n 1 expression\n 1 constraint","category":"page"},{"location":"submodules/Nonlinear/overview/#User-defined-operators","page":"Overview","title":"User-defined operators","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"By default, Nonlinear supports a wide range of univariate and multivariate operators. However, you can also define your own operators by registering them.","category":"page"},{"location":"submodules/Nonlinear/overview/#Univariate-operators","page":"Overview","title":"Univariate operators","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Register a univariate user-defined operator using Nonlinear.register_operator:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> f(x) = 1 + sin(x)^2\nf (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_f, 1, f)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Now, you can use :my_f in expressions:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> new_expr = Nonlinear.add_expression(model, :(my_f($x + 1)))\nMathOptInterface.Nonlinear.ExpressionIndex(2)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"By default, Nonlinear will compute first- and second-derivatives of the registered operator using ForwardDiff.jl. Override this by passing functions which compute the respective derivative:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> f′(x) = 2 * sin(x) * cos(x)\nf′ (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_f2, 1, f, f′)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"or","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> f′′(x) = 2 * (cos(x)^2 - sin(x)^2)\nf′′ (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_f3, 1, f, f′, f′′)","category":"page"},{"location":"submodules/Nonlinear/overview/#Multivariate-operators","page":"Overview","title":"Multivariate operators","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Register a multivariate user-defined operator using Nonlinear.register_operator:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> g(x...) = x[1]^2 + x[1] * x[2] + x[2]^2\ng (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_g, 2, g)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Now, you can use :my_g in expressions:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> new_expr = Nonlinear.add_expression(model, :(my_g($x + 1, $x)))\nMathOptInterface.Nonlinear.ExpressionIndex(3)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"By default, Nonlinear will compute the gradient of the registered operator using ForwardDiff.jl. (Hessian information is not supported.) Override this by passing a function to compute the gradient:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> function ∇g(ret, x...)\n ret[1] = 2 * x[1] + x[2]\n ret[2] = x[1] + 2 * x[2]\n return\n end\n∇g (generic function with 1 method)\n\njulia> Nonlinear.register_operator(model, :my_g2, 2, g, ∇g)","category":"page"},{"location":"submodules/Nonlinear/overview/#Nonlinear_MOI_interface","page":"Overview","title":"MathOptInterface","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"MathOptInterface communicates the nonlinear portion of an optimization problem to solvers using concrete subtypes of AbstractNLPEvaluator, which implement the Nonlinear programming API.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Create an AbstractNLPEvaluator from Nonlinear.Model using Nonlinear.Evaluator.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Evaluator requires an Nonlinear.AbstractAutomaticDifferentiation backend and an ordered list of the variables that are included in the model.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"There following backends are available to choose from within MOI, although other packages may add more options by sub-typing Nonlinear.AbstractAutomaticDifferentiation:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.ExprGraphOnly\nNonlinear.SparseReverseMode.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> evaluator = Nonlinear.Evaluator(model, Nonlinear.ExprGraphOnly(), [x])\nNonlinear.Evaluator with available features:\n * :ExprGraph","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The functions of the Nonlinear programming API implemented by Nonlinear.Evaluator depends upon the chosen Nonlinear.AbstractAutomaticDifferentiation backend.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The :ExprGraph feature means we can call objective_expr and constraint_expr to retrieve the expression graph of the problem. However, we cannot call gradient terms such as eval_objective_gradient because Nonlinear.ExprGraphOnly does not have the capability to differentiate a nonlinear expression.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"If, instead, we pass Nonlinear.SparseReverseMode, then we get access to :Grad, the gradient of the objective function, :Jac, the Jacobian matrix of the constraints, :JacVec, the ability to compute Jacobian-vector products, and :ExprGraph.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> evaluator = Nonlinear.Evaluator(\n model,\n Nonlinear.SparseReverseMode(),\n [x],\n )\nNonlinear.Evaluator with available features:\n * :Grad\n * :Jac\n * :JacVec\n * :ExprGraph","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"However, before using the evaluator, we need to call initialize:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> MOI.initialize(evaluator, [:Grad, :Jac, :JacVec, :ExprGraph])","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Now we can call methods like eval_objective:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> x = [1.0]\n1-element Vector{Float64}:\n 1.0\n\njulia> MOI.eval_objective(evaluator, x)\n7.268073418273571","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"and eval_objective_gradient:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> grad = [0.0]\n1-element Vector{Float64}:\n 0.0\n\njulia> MOI.eval_objective_gradient(evaluator, grad, x)\n\njulia> grad\n1-element Vector{Float64}:\n 1.909297426825682","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Instead of passing Nonlinear.Evaluator directly to solvers, solvers query the NLPBlock attribute, which returns an NLPBlockData. This object wraps an Nonlinear.Evaluator and includes other information such as constraint bounds and whether the evaluator has a nonlinear objective. Create and set NLPBlockData as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> block = MOI.NLPBlockData(evaluator);\n\njulia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}());\n\njulia> MOI.set(model, MOI.NLPBlock(), block);","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nOnly call NLPBlockData once you have finished modifying the problem in model.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Putting everything together, you can create a nonlinear optimization problem in MathOptInterface as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"import MathOptInterface as MOI\n\nfunction build_model(\n model::MOI.ModelLike;\n backend::MOI.Nonlinear.AbstractAutomaticDifferentiation,\n)\n x = MOI.add_variable(model)\n y = MOI.add_variable(model)\n MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n nl_model = MOI.Nonlinear.Model()\n MOI.Nonlinear.set_objective(nl_model, :($x^2 + $y^2))\n evaluator = MOI.Nonlinear.Evaluator(nl_model, backend, [x, y])\n MOI.set(model, MOI.NLPBlock(), MOI.NLPBlockData(evaluator))\n return\nend\n\n# Replace `model` and `backend` with your optimizer and backend of choice.\nmodel = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nbuild_model(model; backend = MOI.Nonlinear.SparseReverseMode())","category":"page"},{"location":"submodules/Nonlinear/overview/#Expression-graph-representation","page":"Overview","title":"Expression-graph representation","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Model stores nonlinear expressions in Nonlinear.Expressions. This section explains the design of the expression graph data structure in Nonlinear.Expression.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Given a nonlinear function like f(x) = sin(x)^2 + x, a conceptual aid for thinking about the graph representation of the expression is to convert it into Polish prefix notation:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"f(x, y) = (+ (^ (sin x) 2) x)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This format identifies each operator (function), as well as a list of arguments. Operators can be univariate, like sin, or multivariate, like +.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"A common way of representing Polish prefix notation in code is as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> x = MOI.VariableIndex(1);\n\njulia> struct ExprNode\n op::Symbol\n children::Vector{Union{ExprNode,Float64,MOI.VariableIndex}}\n end\n\njulia> expr = ExprNode(:+, [ExprNode(:^, [ExprNode(:sin, [x]), 2.0]), x]);","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This data structure follows our Polish prefix notation very closely, and we can easily identify the arguments to an operator. However, it has a significant draw-back: each node in the graph requires a Vector, which is heap-allocated and tracked by Julia's garbage collector (GC). For large models, we can expect to have millions of nodes in the expression graph, so this overhead quickly becomes prohibitive for computation.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"An alternative is to record the expression as a linear tape:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> expr = Any[:+, 2, :^, 2, :sin, 1, x, 2.0, x]\n9-element Vector{Any}:\n :+\n 2\n :^\n 2\n :sin\n 1\n MOI.VariableIndex(1)\n 2.0\n MOI.VariableIndex(1)","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The Int after each operator Symbol specifies the number of arguments.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This data-structure is a single vector, which resolves our problem with the GC, but each element is the abstract type, Any, and so any operations on it will lead to slower dynamic dispatch. It's also hard to identify the children of each operation without reading the entire tape.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"To summarize, representing expression graphs in Julia has the following challenges:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nodes in the expression graph should not contain a heap-allocated object\nAll data-structures should be concretely typed\nIt should be easy to identify the children of a node","category":"page"},{"location":"submodules/Nonlinear/overview/#Sketch-of-the-design-in-Nonlinear","page":"Overview","title":"Sketch of the design in Nonlinear","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear overcomes these problems by decomposing the data structure into a number of different concrete-typed vectors.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"First, we create vectors of the supported uni- and multivariate operators.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> const UNIVARIATE_OPERATORS = [:sin];\n\njulia> const MULTIVARIATE_OPERATORS = [:+, :^];","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In practice, there are many more supported operations than the ones listed here.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Second, we create an enum to represent the different types of nodes present in the expression graph:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> @enum(\n NodeType,\n NODE_CALL_MULTIVARIATE,\n NODE_CALL_UNIVARIATE,\n NODE_VARIABLE,\n NODE_VALUE,\n )","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In practice, there are node types other than the ones listed here.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Third, we create two concretely typed structs as follows:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> struct Node\n type::NodeType\n parent::Int\n index::Int\n end\n\njulia> struct Expression\n nodes::Vector{Node}\n values::Vector{Float64}\n end","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"For each node node in the .nodes field, if node.type is:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"NODE_CALL_MULTIVARIATE, we look up MULTIVARIATE_OPERATORS[node.index] to retrieve the operator\nNODE_CALL_UNIVARIATE, we look up UNIVARIATE_OPERATORS[node.index] to retrieve the operator\nNODE_VARIABLE, we create MOI.VariableIndex(node.index)\nNODE_VALUE, we look up values[node.index]","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The .parent field of each node is the integer index of the parent node in .nodes. For the first node, the parent is -1 by convention.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Therefore, we can represent our function as:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"julia> expr = Expression(\n [\n Node(NODE_CALL_MULTIVARIATE, -1, 1),\n Node(NODE_CALL_MULTIVARIATE, 1, 2),\n Node(NODE_CALL_UNIVARIATE, 2, 1),\n Node(NODE_VARIABLE, 3, 1),\n Node(NODE_VALUE, 2, 1),\n Node(NODE_VARIABLE, 1, 1),\n ],\n [2.0],\n );","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The ordering of the nodes in the tape must satisfy two rules:","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The children of a node must appear after the parent. This means that the tape is ordered topologically, so that a reverse pass of the nodes evaluates all children nodes before their parent\nThe arguments for a CALL node are ordered in the tape based on the order in which they appear in the function call.","category":"page"},{"location":"submodules/Nonlinear/overview/#Design-goals","page":"Overview","title":"Design goals","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This is less readable than the other options, but does this data structure meet our design goals?","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Instead of a heap-allocated object for each node, we only have two Vectors for each expression, nodes and values, as well as two constant vectors for the OPERATORS. In addition, all fields are concretely typed, and there are no Union or Any types.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"For our third goal, it is not easy to identify the children of a node, but it is easy to identify the parent of any node. Therefore, we can use Nonlinear.adjacency_matrix to compute a sparse matrix that maps parents to their children.","category":"page"},{"location":"submodules/Nonlinear/overview/#The-design-in-practice","page":"Overview","title":"The design in practice","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"In practice, Node and Expression are exactly Nonlinear.Node and Nonlinear.Expression. However, Nonlinear.NodeType has more fields to account for comparison operators such as :>= and :<=, logic operators such as :&& and :||, nonlinear parameters, and nested subexpressions.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Moreover, instead of storing the operators as global constants, they are stored in Nonlinear.OperatorRegistry, and it also stores a vector of logic operators and a vector of comparison operators. In addition to Nonlinear.DEFAULT_UNIVARIATE_OPERATORS and Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS, you can register user-defined functions using Nonlinear.register_operator.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.Model is a struct that stores the Nonlinear.OperatorRegistry, as well as a list of parameters and subexpressions in the model.","category":"page"},{"location":"submodules/Nonlinear/overview/#ReverseAD","page":"Overview","title":"ReverseAD","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Nonlinear.ReverseAD is a submodule for computing derivatives of a nonlinear optimization problem using sparse reverse-mode automatic differentiation (AD).","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"This section does not attempt to explain how sparse reverse-mode AD works, but instead explains why MOI contains its own implementation, and highlights notable differences from similar packages.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"warning: Warning\nDon't use the API in ReverseAD to compute derivatives. Instead, create a Nonlinear.Evaluator object with Nonlinear.SparseReverseMode as the backend, and then query the MOI API methods.","category":"page"},{"location":"submodules/Nonlinear/overview/#Design-goals-2","page":"Overview","title":"Design goals","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"The JuliaDiff organization maintains a list of packages for doing AD in Julia. At last count, there were at least ten packages——not including ReverseAD——for reverse-mode AD in Julia. ReverseAD exists because it has a different set of design goals.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Goal: handle scale and sparsity. The types of nonlinear optimization problems that MOI represents can be large scale (10^5 or more functions across 10^5 or more variables) with very sparse derivatives. The ability to compute a sparse Hessian matrix is essential. To the best of our knowledge, ReverseAD is the only reverse-mode AD system in Julia that handles sparsity by default.\nGoal: limit the scope to improve robustness. Most other AD packages accept arbitrary Julia functions as input and then trace an expression graph using operator overloading. This means they must deal (or detect and ignore) with control flow, I/O, and other vagaries of Julia. In contrast, ReverseAD only accepts functions in the form of Nonlinear.Expression, which greatly limits the range of syntax that it must deal with. By reducing the scope of what we accept as input to functions relevant for mathematical optimization, we can provide a simpler implementation with various performance optimizations.\nGoal: provide outputs which match what solvers expect. Other AD packages focus on differentiating individual Julia functions. In contrast, ReverseAD has a very specific use-case: to generate outputs needed by the MOI nonlinear API. This means it needs to efficiently compute sparse Hessians, and it needs subexpression handling to avoid recomputing subexpressions that are shared between functions.","category":"page"},{"location":"submodules/Nonlinear/overview/#History","page":"Overview","title":"History","text":"","category":"section"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"ReverseAD started life as ReverseDiffSparse.jl, development of which began in early 2014(!). This was well before the other AD packages started development. Because we had a well-tested, working AD in JuMP, there was less motivation to contribute to and explore other AD packages. The lack of historical interaction also meant that other packages were not optimized for the types of problems that JuMP is built for (that is, large-scale sparse problems). When we first created MathOptInterface, we kept the AD in JuMP to simplify the transition, and post-poned the development of a first-class nonlinear interface in MathOptInterface.","category":"page"},{"location":"submodules/Nonlinear/overview/","page":"Overview","title":"Overview","text":"Prior to the introduction of Nonlinear, JuMP's nonlinear implementation was a confusing mix of functions and types spread across the code base and in the private _Derivatives submodule. This made it hard to swap the AD system for another. The main motivation for refactoring JuMP to create the Nonlinear submodule in MathOptInterface was to abstract the interface between JuMP and the AD system, allowing us to swap-in and test new AD systems in the future.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/implementation/#Implementing-a-bridge","page":"Implementation","title":"Implementing a bridge","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"The easiest way to implement a bridge is to follow an existing example. There are three locations of bridges in the source code:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Constraint bridges are stored in src/Bridges/Constraint/bridges\nObjective bridges are stored in src/Bridges/Objective/bridges\nVariable bridges are stored in src/Bridges/Variable/bridges","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"The Implementing a constraint bridge tutorial has a more detailed guide on what is required to implement a bridge.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"When opening a pull request that adds a new bridge, use the checklist Adding a new bridge.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"If you need help or advice, please contact the Developer Chatroom.","category":"page"},{"location":"submodules/Bridges/implementation/#SetMap-bridges","page":"Implementation","title":"SetMap bridges","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"For constraint and variable bridges, a common reformulation is that f(x) in F is reformulated to g(x) in G. In this case, no additional variables and constraints are added, and the bridge needs only a way to map between the functions f and g and the sets F and G.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"To implementation a bridge of this form, subtype the abstract type Bridges.Constraint.SetMapBridge or Bridges.Variable.SetMapBridge and implement the API described in the docstring of each type.","category":"page"},{"location":"submodules/Bridges/implementation/#final_touch","page":"Implementation","title":"final_touch","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Some bridges require information from other parts of the model. One set of examples are the various combinatorial ToMILP bridges, such as Bridges.Constraint.SOS1ToMILPBridge, which require knowledge of the variable bounds.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Bridges requiring information from other parts of the model should implement Bridges.final_touch and Bridges.needs_final_touch.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"During the bridge's construction, store the function and set and make no changes to the underlying model. Then, in Bridges.final_touch, query the additional information and add the reformulated problem to the model.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"When implementing, you must consider that:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Bridges.final_touch may be called multiple times, so that your reformulation should be applied only if necessary. Sometimes the additional data will be the same, and sometimes it may be different.\nWe do not currently support final_touch bridges that introduce constraints which also require a final_touch bridge. Therefore, you should implement final_touch only if necessary, and we recommend that you contact the Developer Chatroom for advice before doing so.","category":"page"},{"location":"submodules/Bridges/implementation/#Testing","page":"Implementation","title":"Testing","text":"","category":"section"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Use the Bridges.runtests function to test a bridge. It takes three arguments: the type of the bridge, the input model as a string, and the output model as a string.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Here is an example:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"julia> MOI.Bridges.runtests(\n MOI.Bridges.Constraint.GreaterToLessBridge,\n \"\"\"\n variables: x\n x >= 1.0\n \"\"\",\n \"\"\"\n variables: x\n -1.0 * x <= -1.0\n \"\"\",\n )","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"There are a number of other useful keyword arguments.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"eltype can be used to specify the element type of the model (and bridge). It defaults to Float64.\nvariable_start and constraint_start are used as the values to set the VariablePrimalStart and ConstraintPrimalStart attributes to. They default to 1.2. If you use a different eltype, you must set appropriate starting values of the same type. The default 1.2 was chosen to minimize the risk that the starting point is undefined, which could happen for common situations like 0.0 and 1.0. The tests associated with the starting values do not necessarily check for correctness, only that they can be set and get to produce the same result.\nprint_inner_model can be used to print the reformulated output model from the bridge. This is especially helpful during debugging to see what the bridge is doing, and to spot mistakes. It defaults to false.","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"Here is an example:","category":"page"},{"location":"submodules/Bridges/implementation/","page":"Implementation","title":"Implementation","text":"julia> MOI.Bridges.runtests(\n MOI.Bridges.Constraint.GreaterToLessBridge,\n \"\"\"\n variables: x\n x >= 1\n \"\"\",\n \"\"\"\n variables: x\n ::Int: -1 * x <= -1\n \"\"\";\n eltype = Int,\n print_inner_model = true,\n variable_start = 2,\n constraint_start = 2,\n )\nFeasibility\n\nSubject to:\n\nScalarAffineFunction{Int64}-in-LessThan{Int64}\n (0) - (1) x <= (-1)","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"CurrentModule = MathOptInterface","category":"page"},{"location":"release_notes/#Release-notes","page":"Release notes","title":"Release notes","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.","category":"page"},{"location":"release_notes/#[v1.25.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.25.2)-(January-29,-2024)","page":"Release notes","title":"v1.25.2 (January 29, 2024)","text":"","category":"section"},{"location":"release_notes/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed getting ConstraintPrimal if variable bridges are present (#2396)\nFixed modify_function! for ScalarQuadraticCoefficientChange (#2408)\nFixed writing FileFormats.MOF files if ScalarNonlinearFunction contains ScalarAffineFunction or ScalarQuadraticFunction (#2409)","category":"page"},{"location":"release_notes/#Other","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Clarified ordering of nonlinear tape in documentation (#2401)\nUpdated vale.sh (#2403) (#2404)\nTidied `src/Utilities/results.jl (#2411)","category":"page"},{"location":"release_notes/#[v1.25.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.25.1)-(January-11,-2024)","page":"Release notes","title":"v1.25.1 (January 11, 2024)","text":"","category":"section"},{"location":"release_notes/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed map_indices for AbstractAutomaticDifferentiation (#2394)\nFixed deleting a variable in Bridges.Variable.VectorizeBridge (#2393)\nFixed super type of LowerBoundAlreadySet and UpperBoundAlreadySet (#2397)","category":"page"},{"location":"release_notes/#Other-2","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Removed a duplicated test (#2395)","category":"page"},{"location":"release_notes/#[v1.25.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.25.0)-(January-5,-2024)","page":"Release notes","title":"v1.25.0 (January 5, 2024)","text":"","category":"section"},{"location":"release_notes/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added the AutomaticDifferentiationBackend attribute (#2386)","category":"page"},{"location":"release_notes/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed initialize for Nonlinear.ExprGraphOnly (#2387)\nFixed converting 0-valued ScalarAffineFunction and ScalarQuadraticFunction to ScalarNonlinearFunction (#2388)\nFixed reading .nl files with non-empty variable and constraint names (#2390)\nFixed reading .nl files with no objective (#2391)\nFixed reading .nl files with free ranged constraints (#2392)","category":"page"},{"location":"release_notes/#[v1.24.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.24.0)-(January-2,-2024)","page":"Release notes","title":"v1.24.0 (January 2, 2024)","text":"","category":"section"},{"location":"release_notes/#Added-2","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added get_fallback for ConstraintDual of variable bounds (#2373)","category":"page"},{"location":"release_notes/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed RSOCtoPSDBridge for dimension 2 (#2359)\nFixed getting ConstraintFunction in conversion bridge (#2360)\nFixed map_indices (#2367)\nFixed SlackBridgePrimalDualStart for non-slack bridges (#2365)\nFixed test_attribute_TimeLimitSec (#2370)\nFixed order of model attributes during copy_to (#2372)\nFixed ConstraintIndex conflicts between variable and constraint bridges (#2362)\nFixed corner-case deletion in bridges (#2377)\nFixed ListOfVariablesWithAttributeSet for variable bridges (#2380)\nFixed SlackBridge if scalar constant is not zero (#2382)\nFixed setting multiple bounds on a bridged variable (#2383)","category":"page"},{"location":"release_notes/#Other-3","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Minor documentation improvements (#2355), (#2374)\nImproved side_dimension_for_vectorized_dimension (#2356)\nAdded DiffOpt and ParametricOptInterface to solver-tests.yml (#2368)\nRefactored SDPAModel into a separate test file and test more widely (#2364), (#2357)","category":"page"},{"location":"release_notes/#[v1.23.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.23.0)-(November-29,-2023)","page":"Release notes","title":"v1.23.0 (November 29, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-3","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added ConstraintPrimalStart for Bridges.Constraint.GeoMeanBridge (#2348)\nAdded verbose keyword argument to Test.runtests (#2347)\nAdded Bridges.FirstBridge attribute (#2211)","category":"page"},{"location":"release_notes/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed Test.test_model_Name_VariableName_ConstraintName (#2349)\nFixed errors thrown when querying an attribute is not supported, like when Utilities.CachingOptimizer is not attached to an optimizer (#2350)","category":"page"},{"location":"release_notes/#[v1.22.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.22.0)-(November-6,-2023)","page":"Release notes","title":"v1.22.0 (November 6, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-4","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new bridges (#2318)\nBridges.Constraint.SOS1ToMILPBridge\nBridges.Constraint.SOS2ToMILPBridge\nBridges.Constraint.IndicatorToMILPBridge\nAdded starting values for bridges (#2330) (#2337) (#2338) (#2339)\nBridges.Constraint.NumberConversionBridge\nBridges.Constraint.SquareBridge\nBridges.Variable.HermitianToSymmetricPSDBridge\nBridges.Variable.ParameterToEqualToBridge\nBridges.Variable.RSOCtoPSDBridge\nAdded ListOfVariablesWithAttributeSet and ListOfConstraintsWithAttributeSet (#2331) (#2342)\nAdded support for printing ConstraintName when models are printed (#2336)","category":"page"},{"location":"release_notes/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"ScalarFunctionConstantNotZero errors are now skipped in Test.runtests (#2325)\nFixed VectorNonlinearFunction support in Bridges.Constraint.NormOneBridge and Bridges.Constraint.NormInfinityBridge (#2324)\nFixed various get for ConstraintFunction to return a copy, and added tests (#2328)\nFixed supports of ConstraintPrimalStart and VariablePrimalStart for some bridges (#2340)","category":"page"},{"location":"release_notes/#Other-4","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed typo in docstring of ScalarAffineFunction (#2326)\nAdded Gurobi to solver-tests.yml (#2332)\nImproved the error message when a bridge does not support an attribute (#2329)\nImproved documentation for implementing a bridge (#2334)\nUpdated [compat] bounds in Project.toml (#2344)","category":"page"},{"location":"release_notes/#[v1.21.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.21.0)-(October-25,-2023)","page":"Release notes","title":"v1.21.0 (October 25, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-5","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added SolutionLimit attribute (#2291)\nAdded support for MathOptFormat v1.6 and v1.7 (#2293) (#2298) (#2299) (#2321)\nAdded ScalarQuadraticCoefficientChange (#2296) (#2320) (#2322)\nAdded Utilities.modify_constants (#2300)\nAdded support for is_empty and empty! of Nonlinear.Model (#2305)\nAdded Bridges.Objective.FunctionConversionBridge (#2303)\nAdded Bridges.ModifyBridgeNotAllowed (#2307)\nAdded more sets for Utilities.distance_to_set (#2314)","category":"page"},{"location":"release_notes/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed test_attribute_TimeLimitSec (#2256)\nFixed conversion cost in objective bridges (#2309)","category":"page"},{"location":"release_notes/#Other-5","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed flakey link checking in documentation (#2297)\nMinor documentation fixes (#2304) (#2313)\nFixed [compat] section of Project.toml (#2310)\nAdded MultiObjectiveAlgorithms to solver-tests.yml (#2312)","category":"page"},{"location":"release_notes/#[v1.20.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.20.1)-(September-24,-2023)","page":"Release notes","title":"v1.20.1 (September 24, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-8","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Removed incorrect kwargs in some copy_to methods (#2272)\nFixed ConstraintDualStart for Bridges.Constraint.SplitIntervalBridge (#2275)\nFixed MethodError when trying to modify a variable objective (#2278)\nFixed stack-overflow in Utilities.operate(+,...) with many arguments (#2285) (#2290)","category":"page"},{"location":"release_notes/#Other-6","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added MathOptSetDistances to solver-tests.yml (#2265)\nUpdated Documenter (#2266)\nFixed various JET errors (#2267) (#2269) (#2270) (#2271) (#2276) (#2277) (#2289)\nVarious style improvements\nReplaced using Package with import Package where possible (#2274)\nRemoved Utilities.EMPTYSTRING (#2283)\nRemoved unnecessary const acronyms in Utilities (#2280) (#2281)\nRemoved invalid and unused method (#2286)\nRefactored src/Utilities/model.jl (#2287)","category":"page"},{"location":"release_notes/#[v1.20.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.20.0)-(September-7,-2023)","page":"Release notes","title":"v1.20.0 (September 7, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-6","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Scaled set (#2237) (#2263) (#2264)\nAdded ObjectiveLimit attribute (#2257)","category":"page"},{"location":"release_notes/#Other-7","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Updated dependencies (#2258)\nImproved performance of ScalarNonlinearFunction utilities (#2259)\nFixed docstrings (#2261)","category":"page"},{"location":"release_notes/#[v1.19.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.19.0)-(August-15,-2023)","page":"Release notes","title":"v1.19.0 (August 15, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-7","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added VectorNonlinearFunction (#2201)\nAdded new bridges\nBridges.Constraint.IntegerToZeroOneBridge (#2205)\nBridges.Constraint.ToScalarQuadraticBridge (#2235)\nBridges.Constraint.ToVectorQuadraticBridge (#2235)\nBridges.Constraint.ToScalarNonlinearBridge (#2233) (#2235)\nBridges.Constraint.FunctionConversionBridge (#2235)\nAdded Bridges.bridging_cost for setting a bridge-specific cost in the bridging graph (#2235)\nAdded Utilities.eval_variables support for ScalarNonlinearFunction (#2218) (#2219)\nAdded support for ScalarNonlinearFunction in FileFormats.NL (#2228) (#2231)\nAdded support for writing non-Float64 functions in FileFormats.MOF\nAdded Utilities.lazy_map (#2254)","category":"page"},{"location":"release_notes/#Fixed-9","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed method ambiguities in operate (#2224)\nFixed reading LP file with a -infinity <= x <= +infinity variable (#2225)\nFixed missing require in Test.test_nonlinear_duals (#2230)\nFixed bug in ConstraintPrimal of Bridges.Constraint.QuadtoSOCBridge (#2240)","category":"page"},{"location":"release_notes/#Other-8","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added extensions to solver-tests.yml (#2229)\nRefactored test/Benchmarks (#2234)\nFixed warnings in tests (#2241) (#2243)\nSmall refactoring of bridges for upcoming VectorNonlinearFunction (#2244) (#2245)\nFixed various typos (#2251) (#2255)\nPartitioned how we run the tests on GitHub actions (#2252) (#2253)","category":"page"},{"location":"release_notes/#[v1.18.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.18.0)-(June-23,-2023)","page":"Release notes","title":"v1.18.0 (June 23, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-8","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.SlackBridgePrimalDualStart (#2194)\nAdded constraint_gradient_structure and eval_constraint_gradient (#2200)","category":"page"},{"location":"release_notes/#Fixed-10","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a missing @require in MOI.Test (#2195) (#2196)\nFixed incorrect usage of Utilities.operate! in bridges (#2207) (#2216)\nFixed splatting nonlinear expression with univariate operator (#2221)","category":"page"},{"location":"release_notes/#Other-9","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Removed unused argument names (#2199)\nReduced memory requirement for tests (#2204)\nRefactored Utilities.promote_operation (#2206)\nImproved code style in Utilities/mutable_arithmetics.jl (#2209)\nRefactored various methods in Utilities/functions.jl (#2208) (#2212) (#2213) (#2214) (#2215)","category":"page"},{"location":"release_notes/#[v1.17.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.17.1)-(June-6,-2023)","page":"Release notes","title":"v1.17.1 (June 6, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-11","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed comparison of ScalarFunctionConstantNotZero (#2190)","category":"page"},{"location":"release_notes/#Other-10","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added documentation for enum instances (#2186)\nUpdated chatroom links in documentation (#2188)\nChanged the documentation to build on Julia v1.9 (#2191)","category":"page"},{"location":"release_notes/#[v1.17.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.17.0)-(June-1,-2023)","page":"Release notes","title":"v1.17.0 (June 1, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-9","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added ScalarNonlinearFunction (#2059)\nAdded a variety of tests for NormSpectralCone, NormNuclearCone, and HermitianPositiveSemidefiniteConeTriangle (#2174)\nAdded Utilities.value_type for computing the value type of a function (#2176)","category":"page"},{"location":"release_notes/#Fixed-12","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed support for external sets in Utilities.loadfromstring! (#2177)\nFixed promote_operation for ScalarNonlinearFunction (#2179)\nFixed two issues in FileFormats.LP when reading files with quadratic functions (#2182) (#2184)","category":"page"},{"location":"release_notes/#[v1.16.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.16.0)-(May-16,-2023)","page":"Release notes","title":"v1.16.0 (May 16, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-10","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for MathOptFormat v1.3 and v1.4 (#2158) (#2169)\nAdded new method to the nonlinear API (#2162) (#2164)\neval_hessian_constraint\neval_hessian_objective\nhessian_constraint_structure\nhessian_objective_structure\nAdded new sets\nNormCone (#2119)\nScaledPositiveSemidefiniteConeTriangle (#2154)","category":"page"},{"location":"release_notes/#Fixed-13","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed support for Julia v1.9 to work around a bug in the upstream Julia compiler (#2161) (#2163)\nFixed a correctness bug in Bridges.Constraint.HermitianToSymmetricPSDBridge (#2171)\nFixed convert(::VariableIndex, ::ScalarAffineFunction) when the function has terms with 0coefficients (#2173)","category":"page"},{"location":"release_notes/#Other-11","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed solver-tests.yml (#2157)\nUpdated documentation links to developer chatroom (#2160)\nAdded various tests for bridges (#2156)\nAdded checklists to the developer documentation (#2167) (#2168)","category":"page"},{"location":"release_notes/#[v1.15.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.15.1)-(April-25,-2023)","page":"Release notes","title":"v1.15.1 (April 25, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-14","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed deleting a variable in a bridged objective (#2150)","category":"page"},{"location":"release_notes/#[v1.15.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.15.0)-(April-19,-2023)","page":"Release notes","title":"v1.15.0 (April 19, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-11","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.Objective.VectorFunctionizeBridge (#2139)","category":"page"},{"location":"release_notes/#Fixed-15","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed support for Rational in Bridges.Constraint.SplitIntervalBridge (#2137)\nFixed printing of LaTeX models (#2141)\nFixed modify in Bridges.Objective.VectorSlackBridge (#2144)\nFixed NAME record with spaces in FileFormats.MPS (#2146)\nFixed deleting a variable in a bridged objective (#2147)","category":"page"},{"location":"release_notes/#Other-12","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add a test for variables in one-sided open Interval sets (#2133)\nMinor style fixes in the source code (#2148)","category":"page"},{"location":"release_notes/#[v1.14.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.14.1)-(April-6,-2023)","page":"Release notes","title":"v1.14.1 (April 6, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-16","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Bridges.print_active_bridges (#2135)","category":"page"},{"location":"release_notes/#Other-13","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added a warning when an ambiguous string is passed to exclude in Test.runtests (#2136)","category":"page"},{"location":"release_notes/#[v1.14.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.14.0)-(April-4,-2023)","page":"Release notes","title":"v1.14.0 (April 4, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-12","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for starting values in Bridges.Constraint.QuadtoSOCBridge (#2115)\nAdded support for Regex in the include and exclude arguments to Test.runtests (#2129)\nAdded Bridges.print_active_bridges methods for individual objectives and constraints (#2128)","category":"page"},{"location":"release_notes/#Fixed-17","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed ResultCount when parsing .sol files in FileFormats.NL (#2130)","category":"page"},{"location":"release_notes/#[v1.13.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.13.2)-(March-21,-2023)","page":"Release notes","title":"v1.13.2 (March 21, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-18","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed splatting of containers in MOI.Nonlinear (#2120)\nFixed a bug reading LP files with default bounds (#2121)\nFixed a bug in which Bridges.Constraint.HermitianToSymmetricPSDBridge was not enabled by default (#2123)","category":"page"},{"location":"release_notes/#Other-14","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed typos in the documentation (#2114)\nFunctions now print to the REPL in algebraic form. This is potentially breaking if you have tests which rely on a specific String form of MOI functions. (#2112) (#2126)","category":"page"},{"location":"release_notes/#[v1.13.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.13.1)-(March-3,-2023)","page":"Release notes","title":"v1.13.1 (March 3, 2023)","text":"","category":"section"},{"location":"release_notes/#Other-15","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added the Google style guide to the documentation linter Vale, and fixed the resulting warnings (#2110)\nImproved the docstrings in src/functions.jl (#2108)","category":"page"},{"location":"release_notes/#[v1.13.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.13.0)-(February-28,-2023)","page":"Release notes","title":"v1.13.0 (February 28, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-13","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.Constraint.NumberConversionBridge (#2091)\nAdded Parameter set (#2095) (#2105) (#2106) (#2109)\nAdded with_cache_type argument to instantiate (#2097)\nAdded support for HermitianPositiveSemidefiniteConeTriangle in Utilities.Model (#2100)","category":"page"},{"location":"release_notes/#Fixed-19","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed bug when Utilities.@product_of_sets is empty (#2101)\nFixed Bridges.print_active_bridges when variable bridge is an AbstractScalarSet (#2107)","category":"page"},{"location":"release_notes/#Other-16","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added tests for vector-valued objective functions in FileFormats.MOF (#2093)\nUsed and documented preference for import MathOptInterface as MOI (#2096)\nFix and test links in the documentation with linkcheck = true (#2098)\nImproved docstrings of sets in src/sets.jl (#2099)\nSkip checking flakey links in documentation with linkcheck_ignore (#2103)","category":"page"},{"location":"release_notes/#[v1.12.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.12.0)-(February-10,-2023)","page":"Release notes","title":"v1.12.0 (February 10, 2023)","text":"","category":"section"},{"location":"release_notes/#Added-14","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for vector-valued objective functions (#2070)\nAdded a Utilities.distance_to_set method for SecondOrderCone (#2060)","category":"page"},{"location":"release_notes/#Fixed-20","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a number of constraint bridges so that Bridges.final_touch can be called multiple times without forcing a rebuild of the reformulation (#2089)","category":"page"},{"location":"release_notes/#Other-17","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new tests that a set ObjectiveFunction appears in ListOfModelAttributesSet (#2085)\nImproved the docstrings of a number of constraint-programming related sets (#2087)","category":"page"},{"location":"release_notes/#[v1.11.5](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.5)-(January-24,-2023)","page":"Release notes","title":"v1.11.5 (January 24, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-21","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug writing .lp files with an off-diagonal quadratic objective (#2082)","category":"page"},{"location":"release_notes/#Other-18","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added SnoopPrecompile directives for reduced time-to-first-X in Julia v1.9 (#2080)","category":"page"},{"location":"release_notes/#[v1.11.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.4)-(January-12,-2023)","page":"Release notes","title":"v1.11.4 (January 12, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-22","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .lp files with an Integer section (#2078)","category":"page"},{"location":"release_notes/#[v1.11.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.3)-(January-12,-2023)","page":"Release notes","title":"v1.11.3 (January 12, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-23","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a performance bug when deleting a vector of constraints (#2072)\nFixed a bug reading .lp files with terms like x -1 y (#2076)","category":"page"},{"location":"release_notes/#Other-19","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Documented the two-argument method of optimize! (#2074)","category":"page"},{"location":"release_notes/#[v1.11.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.2)-(January-2,-2023)","page":"Release notes","title":"v1.11.2 (January 2, 2023)","text":"","category":"section"},{"location":"release_notes/#Fixed-24","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with ConstraintName set for VariableIndex constraints (#2066)\nFixed a bug reading .mof.json files with nonlinear objectives and no constraints (#2068)","category":"page"},{"location":"release_notes/#[v1.11.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.1)-(December-22,-2022)","page":"Release notes","title":"v1.11.1 (December 22, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-25","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug reading .mof.json files with integer coefficients for affine and quadratic functions (#2063)","category":"page"},{"location":"release_notes/#[v1.11.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.11.0)-(December-2,-2022)","page":"Release notes","title":"v1.11.0 (December 2, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-15","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Utilities.PenaltyRelaxation and Utilities.ScalarPenaltyRelaxation (#1995)\nAdded Utilities.distance_to_set (#2048)\nAdded support for ConstraintPrimalStart and ConstraintDualStart in FileFormats.MOF (#2056)","category":"page"},{"location":"release_notes/#Other-20","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Tidied these release notes (#2055)","category":"page"},{"location":"release_notes/#[v1.10.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.10.0)-(November-22,-2022)","page":"Release notes","title":"v1.10.0 (November 22, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-16","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new methods set(::OptimizerWithAttributes, ::RawOptimizerAttribute, value) and get(::OptimizerWithAttributes, ::RawOptimizerAttribute) (#2049)\nAdded new methods Utilities.DoubleDicts.outer_keys and Utilities.DoubleDicts.nonempty_outer_keys (#2052)","category":"page"},{"location":"release_notes/#Fixed-26","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed Bridges.Objective.SlackBridge when the objective function is complex-valued (#2036) (#2038)\nFixed docstring of Test.runtests to clarify the warn_unsupported argument (#2037)\nFixed reading of free variables in FileFormats.LP (#2044)\nFixed numerous edge cases reading files from QPLIB using FileFormats.LP (#2042) (#2044)\nFixed situations in which x^y returns a complex value in Nonlinear (#2050)","category":"page"},{"location":"release_notes/#Other-21","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved the error message thrown when a user-defined nonlinear function does not accept splatted input (#2032)\nRemoved specialized iterators for keys and values in Utilities.CleverDicts (#2051)","category":"page"},{"location":"release_notes/#[v1.9.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.9.0)-(October-29,-2022)","page":"Release notes","title":"v1.9.0 (October 29, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-17","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added default fallback for getting ListOfConstraintIndices and NumberOfConstraints when the constraint type is unsupported by the model (#2021)\nAdded support for min and max in nonlinear expressions (#2023)\nAdded support for Indicator{EqualTo{T}} constraints in FileFormats.MPS (#2022)\nAdded default fallback for write_to_file and read_from_file (#2029)","category":"page"},{"location":"release_notes/#Fixed-27","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed Constraint.ZeroOneBridge by adding new bounds as affine constraints instead of variable bounds (#1879)\nFixed reading free rows in FileFormats.MPS files (#2009)\nFixed parsing of OBJSENSE blocks in FileFormats.MPS files (#2016) (#2019)\nFixed the parsing of deeply nested nonlinear expressions by removing the use of recursion (#2020)\nFixed the requirements check in Test.test_constraint_get_ConstraintIndex (#2024)","category":"page"},{"location":"release_notes/#[v1.8.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.8.2)-(September-20,-2022)","page":"Release notes","title":"v1.8.2 (September 20, 2022)","text":"","category":"section"},{"location":"release_notes/#Documentation","page":"Release notes","title":"Documentation","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added vale as a documentation linter (#2002)\nImproved styling of code blocks in the PDF (#1999) (#2000)\nFixed a number of typos in the documentation (#2001) (#2003)","category":"page"},{"location":"release_notes/#[v1.8.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.8.1)-(September-12,-2022)","page":"Release notes","title":"v1.8.1 (September 12, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-28","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in supports(::AbstractBridgeOptimizer for constraint attributes (#1991) (#1992)","category":"page"},{"location":"release_notes/#[v1.8.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.8.0)-(September-1,-2022)","page":"Release notes","title":"v1.8.0 (September 1, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-18","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new sets\nHyperRectangle (#1961)\nReified (#1955)\nAdded new bridges (#1955)\nBridges.Constraint.ReifiedAllDifferentToCountDistinctBridge\nBridges.Constraint.ReifiedCountDistinctToMILPBridge\nBridges.Constraint.SplitHyperRectangleBridge\nAdded support for atan(y, x) in Nonlinear (#1987)","category":"page"},{"location":"release_notes/#Fixed-29","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Lazily construct expressions in Nonlinear so that expressions are updated when Nonlinear.Parameter values are updated (#1984)\nAllow NORM_LIMIT as a TerminationStatus for unbounded problems in Test (#1990)","category":"page"},{"location":"release_notes/#[v1.7.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.7.0)-(August-16,-2022)","page":"Release notes","title":"v1.7.0 (August 16, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-19","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new sets\nHermitianPositiveSemidefiniteConeTriangle\nAdded new optimizer-independent options\nRelativeGapTolerance\nAbsoluteGapTolerance\nAdded new bridges\nBridges.Constraint.GeoMeanToPowerBridge\nBridges.Constraint.HermitianToSymmetricPSDBridge\nBridges.Constraint.IndicatorGreaterToLessThanBridge\nBridges.Constraint.IndicatorLessToGreaterThanBridge\nBridges.Constraint.SplitComplexZerosBridge\nBridges.Constraint.SplitComplexEqualToBridge\nBridges.Objective.QuadratizeBridge\nAdded support for generic number types in Utilities.loadfromstring!\nUpdated FileFormats.MOF to MathOptFormat v1.1, enabling support for constraint programming sets in the MOF file format\nAdded support in various FileFormats for\nindicator constraints in FileFormats.MPS\nquadratic constraints and an objective in FileFormats.LP\nquadratic constraints and an objective in FileFormats.MPS","category":"page"},{"location":"release_notes/#Fixed-30","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed some missing promotion rules","category":"page"},{"location":"release_notes/#Other-22","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved the performance of Jacobian products in Nonlinear\nRemoved an un-needed copy in Utilities.modify_function\nVarious clean-ups in Bridges/bridge_optimizer.jl","category":"page"},{"location":"release_notes/#[v1.6.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.6.1)-(July-23,-2022)","page":"Release notes","title":"v1.6.1 (July 23, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-31","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added support for ExponentialCone in MatrixOfConstraints\nFix PSDSquare_3 test to reflect a previously fixed bug getting the ConstraintDual of a PositiveSemidefiniteConeSquare constraint","category":"page"},{"location":"release_notes/#[v1.6.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.6.0)-(July-2,-2022)","page":"Release notes","title":"v1.6.0 (July 2, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-20","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Bridges.needs_final_touch and Bridges.final_touch\nAdded new bridges from constraint programming sets to mixed-integer linear programs:\nAllDifferentToCountDistinctBridge\nCountAtLeastToCountBelongsBridge\nCountBelongsToMILPBridge\nCountDistinctToMILPBridge\nCountGreaterThanToMILPBridge\nCircuitToMILPBridge","category":"page"},{"location":"release_notes/#Fixed-32","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Relax an instance of ::Vector to ::AbstractVector in MOI.Nonlinear\nFix BinPackingToMILPBridge to respect variable bounds\nFix SemiToBinaryBridge to throw error if other bounds are set","category":"page"},{"location":"release_notes/#[v1.5.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.5.0)-(June-27,-2022)","page":"Release notes","title":"v1.5.0 (June 27, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-21","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added GetAttributeNotAllowed for solvers to indicate when getting an attribute encounters an error\nAdded Utilities.get_fallback support for ObjectiveValue and DualObjectiveValue\nAdded new bridges:\nRootDetConeSquare to RootDetConeTriangle\nLogDetConeSquare to LogDetConeTriangle\nBinPacking to a mixed-integer linear program\nTable to a mixed-integer linear program\nAdded Bridges.print_active_bridges to display the current optimal hyper-path in a Bridges.LazyBridgeOptimizer","category":"page"},{"location":"release_notes/#Fixed-33","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed ZeroOne tests with lower and upper bounds\nFixed error in FileFormats.LP when reading a malformed file\nFixed reading of nonlinear programs in FileFormats.MOF\nFixed bug in ConstraintDual when using SquareBridge","category":"page"},{"location":"release_notes/#Other-23","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved documentation of nonlinear API\nDocumented duality convention for PositiveSemidefiniteConeSquare sets\nFixed typo in Bridges.Constraint.QuadToSOCBridge docstring","category":"page"},{"location":"release_notes/#[v1.4.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.4.0)-(June-9,-2022)","page":"Release notes","title":"v1.4.0 (June 9, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-22","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added a number of sets for constraint programming:\nAllDifferent\nBinPacking\nCircuit\nCountAtLeast\nCountBelongs\nCountDistinct\nCountGreaterThan\nCumulative\nPath\nTable\nAdded support for user-defined hessians in Nonlinear\nAdded Bridges.runtests to simplify the testing of bridge implementations","category":"page"},{"location":"release_notes/#Fixed-34","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in FileFormats.NL when writing univariate *","category":"page"},{"location":"release_notes/#Other-24","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Began a large refactoring of the Bridges submodule, with greatly improved documentation.","category":"page"},{"location":"release_notes/#[v1.3.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.3.0)-(May-27,-2022)","page":"Release notes","title":"v1.3.0 (May 27, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-23","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add MOI.Nonlinear submodule. This is a large new submodule that has been refactored from code that was in JuMP. For now, it should be considered experimental.\nAdd FileFormats.NL.SolFileResults(::IO, ::Model)\nAdd FileFormats.NL.read!(::IO, ::Model)\nAdd MOI.modify that accepts a vector of modifications","category":"page"},{"location":"release_notes/#Fixed-35","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in Test which attempted to include non-.jl files\nFixed a bug in FileFormats for models with open interval constraints","category":"page"},{"location":"release_notes/#Other-25","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a performance issue in Utilities.DoubleDict\nVarious minor improvements to the documentation","category":"page"},{"location":"release_notes/#[v1.2.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.2.0)-(April-25,-2022)","page":"Release notes","title":"v1.2.0 (April 25, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-24","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add support for the FORMAT_REW/.rew file format in FileFormats.","category":"page"},{"location":"release_notes/#Fixed-36","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix bug handling of default variable bounds in FileFormats.LP\nFix FileFormats.MPS to not write OBJSENSE by default since this is only supported by some readers.","category":"page"},{"location":"release_notes/#[v1.1.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.1.2)-(March-31,-2022)","page":"Release notes","title":"v1.1.2 (March 31, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-37","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix a range of bugs in FileFormats.LP\nFix reading of problem dimensions in FileFormats.SDPA","category":"page"},{"location":"release_notes/#[v1.1.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.1.1)-(March-23,-2022)","page":"Release notes","title":"v1.1.1 (March 23, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-38","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix bug in test_model_UpperBoundAlreadySet\nFix bug in test_infeasible_ tests\nFix bug in test_objective_ObjectiveFunction_blank\nRelax restriction of MOI.AbstractOptimizer to MOI.ModelLike in Utilities.CachingOptimizer and instantiate.","category":"page"},{"location":"release_notes/#New-tests","page":"Release notes","title":"New tests","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add test_conic_empty_matrix that checks conic solvers support problems with no variables.","category":"page"},{"location":"release_notes/#[v1.1.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.1.0)-(March-2,-2022)","page":"Release notes","title":"v1.1.0 (March 2, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-25","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.throw_unsupported(::UniversalFallback) for simplifying solver wrappers which copy from a UniversalFallback.","category":"page"},{"location":"release_notes/#[v1.0.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.0.2)-(March-1,-2022)","page":"Release notes","title":"v1.0.2 (March 1, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-39","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in the test_model_ScalarFunctionConstantNotZero test\nFixed the error type when an AbstractFunctionConversionBridge cannot get or set an attribute\nIdentified a correctness bug in RSOCtoPSDBridge. We now thrown an error instead of returning an incorrect result.","category":"page"},{"location":"release_notes/#[v1.0.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.0.1)-(February-25,-2022)","page":"Release notes","title":"v1.0.1 (February 25, 2022)","text":"","category":"section"},{"location":"release_notes/#Fixed-40","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in which OptimizerAttributes were not copied in CachingOptimizer\nFixed a bug in which shift_constant did not promote mixed types of coefficients\nFixed a bug in which deleting a constraint of a bridged variable threw ErrorException instead of MOI.DeleteNotAllowed\nFixed a bug in which add_constraint in MatrixOfConstraints did not canonicalize the function\nFixed a bug when modifying scalar constants of a function containing a bridged variable\nFixed a bug in which final_touch was not always called with a CachingOptimizer","category":"page"},{"location":"release_notes/#[v1.0.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v1.0.0)-(February-17,-2022)","page":"Release notes","title":"v1.0.0 (February 17, 2022)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Although tagged as a breaking release, v1.0.0 is v0.10.9 with deprecations removed, similar to how Julia 1.0 was Julia 0.7 with deprecations removed.","category":"page"},{"location":"release_notes/#Breaking","page":"Release notes","title":"Breaking","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Julia 1.6 is now the minimum supported version\nAll deprecations have been removed","category":"page"},{"location":"release_notes/#Troubleshooting-problems-when-updating","page":"Release notes","title":"Troubleshooting problems when updating","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"If you experience problems when updating, you are likely using previously deprecated features. (By default, Julia does not warn when you use deprecated features.)","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"To find the deprecated features you are using, start Julia with --depwarn=yes:","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"$ julia --depwarn=yes","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Then install MathOptInterface v0.10.9:","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"julia> using Pkg\njulia> pkg\"add MathOptInterface@0.10\"","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"And then run your code. Apply any suggestions, or search the release notes below for advice on updating a specific deprecated feature.","category":"page"},{"location":"release_notes/#[v0.10.9](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.9)-(February-16,-2022)","page":"Release notes","title":"v0.10.9 (February 16, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-26","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added MOI.Utilities.FreeVariables as a new VariablesConstrainer for conic solvers\nAdded MOI.default_cache for specifying the model used in CachingOptimizer","category":"page"},{"location":"release_notes/#Fixed-41","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed LaTeX printing of MOI.Interval sets","category":"page"},{"location":"release_notes/#Other-26","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added Aqua.jl as a CI check, and fixed suggested issues\nThe constructors of GeoMeanBridge, StructOfConstraints, and CachingOptimizer were changed from outer to inner constructors. This change is technically breaking, but does not impact users who followed the documented API.","category":"page"},{"location":"release_notes/#[v0.10.8](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.8)-(February-3,-2022)","page":"Release notes","title":"v0.10.8 (February 3, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-27","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added a Base.read! for FileFormats.LP.","category":"page"},{"location":"release_notes/#Fixed-42","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a bug in MutableSparseMatrix\nFixed a bug when calling operate!(vcat, ...) with Number arguments\nRemoved unintended export of deprecated symbols\nFixed a bug with PowerCone and DualPowerCone in MatrixOfConstraints.","category":"page"},{"location":"release_notes/#[v0.10.7](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.7)-(January-5,-2022)","page":"Release notes","title":"v0.10.7 (January 5, 2022)","text":"","category":"section"},{"location":"release_notes/#Added-28","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added test for modifying the constant vector in a VectorAffineFunction-in-Zeros constraint.","category":"page"},{"location":"release_notes/#Fixed-43","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed the order in which sets are added to a LazyBridgeOptimizer. Compared to v0.10.6, this may result in bridged models being created with a different number (and order) of variables and constraints. However, it was necessary to fix cases which were previously rejected as unsupported, even though there was a valid bridge transformation.\nFixed an error message in FileFormats.CBF\nFixed comparison in test_linear_integration_Interval\nFixed errors for ConstraintPrimal in a CachingOptimizer\nFixed printing of models with non-Float64 coefficients.","category":"page"},{"location":"release_notes/#Other-27","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various improvements to reduce time-to-first-solve latency\nImproved error message when an optimizer does not support compute_conflict!","category":"page"},{"location":"release_notes/#[v0.10.6](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.6)-(November-30,-2021)","page":"Release notes","title":"v0.10.6 (November 30, 2021)","text":"","category":"section"},{"location":"release_notes/#Added-29","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added new documentation and tests for infeasibility certificates\nAdded a version control system for the tests in MOI.Test.runtests. Pass exclude_tests_after = v\"0.10.5\" to run tests added in v0.10.5 and earlier.\nMOI.Test.runtests now supports generic number types. To specify the number type T, pass MOI.Test.Config(T).\nAdded infeasible_status to MOI.Test.Config for solvers which return LOCALLY_INFEASIBLE\nCachingOptimizers now use a fallback for ConstraintPrimal. This should enable solvers using a CachingOptimizer to pass tests requiring ConstraintPrimal.","category":"page"},{"location":"release_notes/#Fixed-44","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed a StackOverflow bug in copy_to\nFixed error thrown when nonconvex quadratic constraints cannot be bridged\nFixed a bug in copy_to for FileFormats.NL.Model\nFixed a bug in FileFormats.NL when printing large integers\nRemove a common test failure for LowerBoundAlreadySet tests\nUtilities.num_rows is now exported\nRemove parts of failing test_model_copy_to_xxx tests due to bridges","category":"page"},{"location":"release_notes/#[v0.10.5](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.5)-(November-7,-2021)","page":"Release notes","title":"v0.10.5 (November 7, 2021)","text":"","category":"section"},{"location":"release_notes/#Fixed-45","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed getter in UniversalFallback\nFixed test_solve_conflict_zeroone_ii","category":"page"},{"location":"release_notes/#Other-28","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Make normalize_and_add_constraint more flexible\nUpdate paper BibTeX","category":"page"},{"location":"release_notes/#[v0.10.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.4)-(October-26,-2021)","page":"Release notes","title":"v0.10.4 (October 26, 2021)","text":"","category":"section"},{"location":"release_notes/#Added-30","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add SolverVersion attribute\nAdd new tests:\ntest_solve_conflict_zeroone_ii\ntest_nonlinear_objective\nUtilities.VariablesContainer now supports ConstraintFunction and ConstraintSet\nThe documentation is now available as a PDF","category":"page"},{"location":"release_notes/#Other-29","page":"Release notes","title":"Other","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Update to MutableArithmetics 0.3\nVarious improvements to the documentation","category":"page"},{"location":"release_notes/#[v0.10.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.3)-(September-18,-2021)","page":"Release notes","title":"v0.10.3 (September 18, 2021)","text":"","category":"section"},{"location":"release_notes/#Fixed-46","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed bug which prevented callbacks from working through a CachingOptimizer\nFixed bug in Test submodule","category":"page"},{"location":"release_notes/#[v0.10.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.2)-(September-16,-2021)","page":"Release notes","title":"v0.10.2 (September 16, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Updated MathOptFormat to v1.0\nUpdated JSONSchema to v1.0\nAdded Utilities.set_with_dimension\nAdded two-argument optimize!(::AbstractOptimizer, ::ModelLike)\nThe experimental feature copy_to_and_optimize! has been removed\nDet bridges now support getting ConstraintFunction and ConstraintSet\nVarious minor bug fixes identified by improved testing","category":"page"},{"location":"release_notes/#[v0.10.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.1)-(September-8,-2021)","page":"Release notes","title":"v0.10.1 (September 8, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various fixes to MOI.Test","category":"page"},{"location":"release_notes/#[v0.10.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.10.0)-(September-6,-2021)","page":"Release notes","title":"v0.10.0 (September 6, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"MOI v0.10 is a significant breaking release. There are a large number of user-visible breaking changes and code refactors, as well as a substantial number of new features.","category":"page"},{"location":"release_notes/#Breaking-in-MOI","page":"Release notes","title":"Breaking in MOI","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"SingleVariable has been removed; use VariableIndex instead\nSingleVariableConstraintNameError has been renamed to VariableIndexConstraintNameError\nSettingSingleVariableFunctionNotAllowed has been renamed to SettingVariableIndexFunctionNotAllowed\nVariableIndex constraints should not support ConstraintName\nVariableIndex constraints should not support ConstraintBasisStatus; implement VariableBasisStatus instead\nListOfConstraints has been renamed to ListOfConstraintTypesPresent\nListOfConstraintTypesPresent should now return Tuple{Type,Type} instead of Tuple{DataType,DataType}\nSolveTime has been renamed to SolveTimeSec\nIndicatorSet has been renamed to Indicator\nRawParameter has been renamed to RawOptimizerAttribute and now takes String instead of Any as the only argument\nThe .N field in result attributes has been renamed to .result_index\nThe .variable_index field in ScalarAffineTerm has been renamed to .variable\nThe .variable_index_1 field in ScalarQuadraticTerm has been renamed to .variable_1\nThe .variable_index_2 field in ScalarQuadraticTerm has been renamed to .variable_2\nThe order of affine_terms and quadratic_terms in ScalarQuadraticFunction and VectorQuadraticFunction have been reversed. Both functions now accept quadratic, affine, and constant terms in that order.\nThe index_value function has been removed. Use .value instead.\nisapprox has been removed for SOS1 and SOS2.\nThe dimension argument to Complements(dimension::Int) should now be the length of the corresponding function, instead of half the length. An ArgumentError is thrown if dimension is not even.\ncopy_to no longer takes keyword arguments:\ncopy_names: now copy names if they are supported by the destination solver\nfilter_constraints: use Utilities.ModelFilter instead\nwarn_attributes: never warn about optimizer attributes","category":"page"},{"location":"release_notes/#Breaking-in-Bridges","page":"Release notes","title":"Breaking in Bridges","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Constraint.RSOCBridge has been renamed to Constraint.RSOCtoSOCBridge\nConstraint.SOCRBridge has been renamed to Constraint.SOCtoRSOCBridge\nBridges now return vectors that can be modified by the user. Previously, some bridges returned views instead of copies.\nBridges.IndexInVector has been unified into a single type. Previously, there was a different type for each submodule within Bridges\nThe signature of indicator bridges has been fixed. Use MOI.Bridges.Constraint.IndicatortoSOS1{Float64}(model).","category":"page"},{"location":"release_notes/#Breaking-in-FileFormats","page":"Release notes","title":"Breaking in FileFormats","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"FileFormats.MOF.Model no longer accepts validate argument. Use the JSONSchema package to validate the MOF file. See the documentation for more information.","category":"page"},{"location":"release_notes/#Breaking-in-Utilities","page":"Release notes","title":"Breaking in Utilities","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"The datastructure of Utilities.Model (and models created with Utilities.@model) has been significantly refactored in a breaking way. This includes the way that objective functions and variable-related information is stored.\nUtilities.supports_default_copy has been renamed to supports_incremental_interface\nUtilities.automatic_copy_to has been renamed to Utilities.default_copy_to\nThe allocate-load API has been removed\nCachingOptimizers are now initialized as EMPTY_OPTIMIZER instead of ATTACHED_OPTIMIZER. If your code relies on the optimizer being attached, call MOIU.attach_optimizer(model) after creation.\nThe field names of Utilities.IndexMap have been renamed to var_map and con_map. Accessing these fields directly is considered a private detail that may change. Use the public getindex and setindex! API instead.\nThe size argument to Utilities.CleverDicts.CleverDict(::Integer) has been removed.\nThe size argument to Utilities.IndexMap(::Integer) has been removed.\nUtilities.DoubleDicts have been significantly refactored. Consult the source code for details.\nUtilities.test_models_equal has been moved to MOI.Test","category":"page"},{"location":"release_notes/#Breaking-in-Test","page":"Release notes","title":"Breaking in Test","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"MOI.Test has been renamed to MOI.DeprecatedTest\nAn entirely new MOI.Test submodule has been written. See the documentation for details. The new MOI.Test submodule may find many bugs in the implementations of existing solvers that were previously untested.","category":"page"},{"location":"release_notes/#Other-changes:","page":"Release notes","title":"Other changes:","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"attribute_value_type has been added\ncopy_to_and_optimize! has been added\nVariableBasisStatus has been added\nprint(model) now prints a human-readable description of the model\nVarious improvements to the FileFormats submodule\nFileFormats.CBF was refactored and received bugfixes\nSupport for MathOptFormat v0.6 was added in FileFormats.MOF\nFileFormats.MPS has had bugfixes and support for more features such as OBJSENSE and objective constants.\nFileFormats.NL has been added to support nonlinear files\nImproved type inference throughout to reduce latency","category":"page"},{"location":"release_notes/#Updating","page":"Release notes","title":"Updating","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"A helpful script when updating is:","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"for (root, dirs, files) in walkdir(\".\")\n for file in files\n if !endswith(file, \".jl\")\n continue\n end\n path = joinpath(root, file)\n s = read(path, String)\n for pair in [\n \".variable_index\" => \".variable\",\n \"RawParameter\" => \"RawOptimizerAttribute\",\n \"ListOfConstraints\" => \"ListOfConstraintTypesPresent\",\n \"TestConfig\" => \"Config\",\n \"attr.N\" => \"attr.result_index\",\n \"SolveTime\" => \"SolveTimeSec\",\n \"DataType\" => \"Type\",\n \"Utilities.supports_default_copy_to\" =>\n \"supports_incremental_interface\",\n \"SingleVariableConstraintNameError\" =>\n \"VariableIndexConstraintNameError\",\n \"SettingSingleVariableFunctionNotAllowed\" =>\n \"SettingVariableIndexFunctionNotAllowed\",\n \"automatic_copy_to\" => \"default_copy_to\",\n ]\n s = replace(s, pair)\n end\n write(path, s)\n end\nend","category":"page"},{"location":"release_notes/#[v0.9.22](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.22)-(May-22,-2021)","page":"Release notes","title":"v0.9.22 (May 22, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"This release contains backports from the ongoing development of the v0.10 release.","category":"page"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved type inference in Utilities, Bridges and FileFormats submodules to reduce latency.\nImproved performance of Utilities.is_canonical.\nFixed Utilities.pass_nonvariable_constraints with bridged variables.\nFixed performance regression of Utilities.Model.\nFixed ordering of objective setting in parser.","category":"page"},{"location":"release_notes/#[v0.9.21](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.21)-(April-23,-2021)","page":"Release notes","title":"v0.9.21 (April 23, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added supports_shift_constant.\nImprove performance of bridging quadratic constraints.\nAdd precompilation statements.\nLarge improvements to the documentation.\nFix a variety of inference issues, benefiting precompilation and reducing initial latency.\nRawParameters are now ignored when resetting a CachingOptimizer. Previously, changing the underlying optimizer after RawParameters were set would throw an error.\nUtilities.AbstractModel is being refactored. This may break users interacting with private fields of a model generated using @model.","category":"page"},{"location":"release_notes/#[v0.9.20](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.20)-(February-20,-2021)","page":"Release notes","title":"v0.9.20 (February 20, 2021)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improved performance of Utilities.ScalarFunctionIterator\nAdded support for compute_conflict to MOI layers\nAdded test with zero off-diagonal quadratic term in objective\nFixed double deletion of nested bridged SingleVariable/VectorOfVariables constraints\nFixed modification of un-set objective\nFixed function modification with duplicate terms\nMade unit tests abort without failing if the problem class is not supported\nFormatted code with JuliaFormatter\nClarified BasisStatusCode's docstring","category":"page"},{"location":"release_notes/#[v0.9.19](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.19)-(December-1,-2020)","page":"Release notes","title":"v0.9.19 (December 1, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added CallbackNodeStatus attribute\nAdded bridge from GreaterThan or LessThan to Interval\nAdded tests for infeasibility certificates and double optimize\nFixed support for Julia v1.6\nRe-organized MOI docs and added documentation for adding a test","category":"page"},{"location":"release_notes/#[v0.9.18](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.18)-(November-3,-2020)","page":"Release notes","title":"v0.9.18 (November 3, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various improvements for working with complex numbers\nAdded GeoMeantoRelEntrBridge to bridge a GeometricMeanCone constraint to a relative entropy constraint","category":"page"},{"location":"release_notes/#[v0.9.17](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.17)-(September-21,-2020)","page":"Release notes","title":"v0.9.17 (September 21, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed CleverDict with variable of negative index value\nImplement supports_add_constrained_variable for MockOptimizer","category":"page"},{"location":"release_notes/#[v0.9.16](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.16)-(September-17,-2020)","page":"Release notes","title":"v0.9.16 (September 17, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Various fixes:\n32-bit support\nCleverDict with abstract value type\nChecks in test suite","category":"page"},{"location":"release_notes/#[v0.9.15](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.15)-(September-14,-2020)","page":"Release notes","title":"v0.9.15 (September 14, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Bridges improvements:\n(R)SOCtoNonConvexQuad bridge\nZeroOne bridge\nUse supports_add_constrained_variable in LazyBridgeOptimizer\nExposed VariableBridgeCost and ConstraintBridgeCost attributes\nPrioritize constraining variables on creation according to these costs\nRefactor bridge debugging\nLarge performance improvements across all submodules\nLots of documentation improvements\nFileFormats improvements:\nUpdate MathOptFormat to v0.5\nFix supported objectives in FileFormats\nTesting improvements:\nAdd name option for basic_constraint_test\nBug fixes and missing methods\nAdd length for iterators\nFix bug with duplicate terms\nFix order of LinearOfConstraintIndices","category":"page"},{"location":"release_notes/#[v0.9.14](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.14)-(May-30,-2020)","page":"Release notes","title":"v0.9.14 (May 30, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add a solver-independent interface for accessing the set of conflicting constraints an Irreducible Inconsistent Subsystem (#1056).\nBump JSONSchema dependency from v0.2 to v0.3 (#1090).\nDocumentation improvements:\nFix typos (#1054, #1060, #1061, #1064, #1069, #1070).\nRemove the outdated recommendation for a package implementing MOI for a solver XXX to be called MathOptInterfaceXXX (#1087).\nUtilities improvements:\nFix is_canonical for quadratic functions (#1081, #1089).\nImplement add_constrained_variable[s] for CachingOptimizer so that it is added as constrained variables to the underlying optimizer (#1084).\nAdd support for custom objective functions for UniversalFallback (#1086).\nDeterministic ordering of constraints in UniversalFallback (#1088).\nTesting improvements:\nAdd NormOneCone/NormInfinityCone tests (#1045).\nBridges improvements:\nAdd bridges from Semiinteger and Semicontinuous (#1059).\nImplement getting ConstraintSet for Variable.FlipSignBridge (#1066).\nFix setting ConstraintFunction for Constraint.ScalarizeBridge (#1093).\nFix NormOne/NormInf bridges with nonzero constants (#1045).\nFix StackOverflow in debug (#1063).\nFileFormats improvements:\n[SDPA] Implement the extension for integer variables (#1079).\n[SDPA] Ignore comments after m and nblocks and detect dat-s extension (#1077).\n[SDPA] No scaling of off-diagonal coefficient (#1076).\n[SDPA] Add missing negation of constant (#1075).","category":"page"},{"location":"release_notes/#[v0.9.13](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.13)-(March-24,-2020)","page":"Release notes","title":"v0.9.13 (March 24, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added tests for Semicontinuous and Semiinteger variables (#1033).\nAdded tests for using ExprGraphs from NLP evaluators (#1043).\nUpdate version compatibilities of dependencies (#1034, #1051, #1052).\nFixed typos in documentation (#1044).","category":"page"},{"location":"release_notes/#[v0.9.12](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.12)-(February-28,-2020)","page":"Release notes","title":"v0.9.12 (February 28, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed writing NLPBlock in MathOptFormat (#1037).\nFixed MockOptimizer for result attributes with non-one result index (#1039).\nUpdated test template with instantiate (#1032).","category":"page"},{"location":"release_notes/#[v0.9.11](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.11)-(February-21,-2020)","page":"Release notes","title":"v0.9.11 (February 21, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add an option for the model created by Utilities.@model to be a subtype of AbstractOptimizer (#1031).\nDescribed dual cone in docstrings of GeoMeanCone and RelativeEntropyCone (#1018, #1028).\nFixed typos in documentation (#1022, #1024).\nFixed warning of unsupported attribute (#1027).\nAdded more rootdet/logdet conic tests (#1026).\nImplemented ConstraintDual for Constraint.GeoMeanBridge, Constraint.RootDetBridge and Constraint.LogDetBridge and test duals in tests with GeoMeanCone and RootDetConeTriangle and LogDetConeTriangle cones (#1025, #1026).","category":"page"},{"location":"release_notes/#[v0.9.10](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.10)-(January-31,-2020)","page":"Release notes","title":"v0.9.10 (January 31, 2020)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added OptimizerWithAttributes grouping an optimizer constructor and a list of optimizer attributes (#1008).\nAdded RelativeEntropyCone with corresponding bridge into exponential cone constraints (#993).\nAdded NormSpectralCone and NormNuclearCone with corresponding bridges into positive semidefinite constraints (#976).\nAdded supports_constrained_variable(s) (#1004).\nAdded dual_set_type (#1002).\nAdded tests for vector specialized version of delete (#989, #1011).\nAdded PSD3 test (#1007).\nClarified dual solution of Tests.pow1v and Tests.pow1f (#1013).\nAdded support for EqualTo and Zero in Bridges.Constraint.SplitIntervalBridge (#1005).\nFixed Utilities.vectorize for empty vector (#1003).\nFixed free variables in LP writer (#1006).","category":"page"},{"location":"release_notes/#[v0.9.9](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.9)-(December-29,-2019)","page":"Release notes","title":"v0.9.9 (December 29, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Incorporated MathOptFormat.jl as the FileFormats submodule. FileFormats provides readers and writers for a number of standard file formats and MOF, a file format specialized for MOI (#969).\nImproved performance of deletion of vector of variables in MOI.Utilities.Model (#983).\nUpdated to MutableArithmetics v0.2 (#981).\nAdded MutableArithmetics.promote_operation allocation tests (#975).\nFixed inference issue on Julia v1.1 (#982).","category":"page"},{"location":"release_notes/#[v0.9.8](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.8)-(December-19,-2019)","page":"Release notes","title":"v0.9.8 (December 19, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Implemented MutableArithmetics API (#924).\nFixed callbacks with CachingOptimizer (#959).\nFixed MOI.dimension for MOI.Complements (#948).\nAdded fallback for add_variables (#972).\nAdded is_diagonal_vectorized_index utility (#965).\nImproved linear constraints display in manual (#963, #964).\nBridges improvements:\nAdded IndicatorSet to SOS1 bridge (#877).\nAdded support for starting values for Variable.VectorizeBridge (#944).\nFixed MOI.add_constraints with non-bridged variable constraint on bridged variable (#951).\nFixed corner cases and docstring of GeoMeanBridge (#961, #962, #966).\nFixed choice between variable or constraint bridges for constrained variables (#973).\nImprove performance of bridge shortest path (#945, #946, #956).\nAdded docstring for test_delete_bridge (#954).\nAdded Variable bridge tests (#952).","category":"page"},{"location":"release_notes/#[v0.9.7](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.7)-(October-30,-2019)","page":"Release notes","title":"v0.9.7 (October 30, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Implemented _result_index_field for NLPBlockDual (#934).\nFixed copy of model with starting values for vector constraints (#941).\nBridges improvements:\nImproved performance of add_bridge and added has_bridge (#935).\nAdded AbstractSetMapBridge for bridges between sets S1, S2 such that there is a linear map A such that A*S1 = S2 (#933).\nAdded support for starting values for FlipSignBridge, VectorizeBridge, ScalarizeBridge, SlackBridge, SplitIntervalBridge, RSOCBridge, SOCRBridge NormInfinityBridge, SOCtoPSDBridge and RSOCtoPSDBridge (#933, #936, #937, #938, #939).","category":"page"},{"location":"release_notes/#[v0.9.6](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.6)-(October-25,-2019)","page":"Release notes","title":"v0.9.6 (October 25, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added complementarity constraints (#913).\nAllowed ModelLike objects as value of attributes (#928).\nTesting improvements:\nAdded dual_objective_value option to MOI.Test.TestConfig (#922).\nAdded InvalidIndex tests in basic_constraint_tests (#921).\nAdded tests for the constant term in indicator constraint (#929).\nBridges improvements:\nAdded support for starting values for Functionize bridges (#923).\nAdded variable indices context to variable bridges (#920).\nFixed a typo in printing o debug_supports (#927).","category":"page"},{"location":"release_notes/#[v0.9.5](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.5)-(October-9,-2019)","page":"Release notes","title":"v0.9.5 (October 9, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Clarified PrimalStatus/DualStatus to be NO_SOLUTION if result_index is out of bounds (#912).\nAdded tolerance for checks and use ResultCount + 1 for the result_index in MOI.Test.solve_result_status (#910, #917).\nUse 0.5 instead of 2.0 for power in PowerCone in basic_constraint_test (#916).\nBridges improvements:\nAdded debug utilities for unsupported variable/constraint/objective (#861).\nFixed deletion of variables in bridged VectorOfVariables constraints (#909).\nFixed result_index with objective bridges (#911).","category":"page"},{"location":"release_notes/#[v0.9.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.4)-(October-2,-2019)","page":"Release notes","title":"v0.9.4 (October 2, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Added solver-independent MIP callbacks (#782).\nImplements submit for Utilities.CachingOptimizer and Bridges.AbstractBridgeOptimizer (#906).\nAdded tests for result count of solution attributes (#901, #904).\nAdded NumberOfThreads attribute (#892).\nAdded Utilities.get_bounds to get the bounds on a variable (#890).\nAdded a note on duplicate coefficients in documentation (#581).\nAdded result index in ConstraintBasisStatus (#898).\nAdded extension dictionary to Utilities.Model (#884, #895).\nFixed deletion of constrained variables for CachingOptimizer (#905).\nImplemented Utilities.shift_constraint for Test.UnknownScalarSet (#896).\nBridges improvements:\nAdded Variable.RSOCtoSOCBridge (#907).\nImplemented MOI.get for ConstraintFunction/ConstraintSet for Bridges.Constraint.SquareBridge (#899).","category":"page"},{"location":"release_notes/#[v0.9.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.3)-(September-20,-2019)","page":"Release notes","title":"v0.9.3 (September 20, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixed ambiguity detected in Julia v1.3 (#891, #893).\nFixed missing sets from ListOfSupportedConstraints (#880).\nFixed copy of VectorOfVariables constraints with duplicate indices (#886).\nAdded extension dictionary to MOIU.Model (#884).\nImplemented MOI.get for function and set for GeoMeanBridge (#888).\nUpdated documentation for SingleVariable indices and bridges (#885).\nTesting improvements:\nAdded more comprehensive tests for names (#882).\nAdded tests for SingleVariable duals (#883).\nAdded tests for DualExponentialCone and DualPowerCone (#873).\nImprovements for arbitrary coefficient type:\nFixed == for sets with mutable fields (#887).\nRemoved some Float64 assumptions in bridges (#878).\nAutomatic selection of Constraint.[Scalar|Vector]FunctionizeBridge (#889).","category":"page"},{"location":"release_notes/#[v0.9.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.2)-(September-5,-2019)","page":"Release notes","title":"v0.9.2 (September 5, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Implemented model printing for MOI.ModelLike and specialized it for models defined in MOI (864).\nGeneralized contlinear tests for arbitrary coefficient type (#855).\nFixed supports_constraint for Semiinteger and Semicontinuous and supports for ObjectiveFunction (#859).\nFixed Allocate-Load copy for single variable constraints (#856).\nBridges improvements:\nAdd objective bridges (#789).\nFixed Variable.RSOCtoPSDBridge for dimension 2 (#869).\nAdded Variable.SOCtoRSOCBridge (#865).\nAdded Constraint.SOCRBridge and disable MOI.Bridges.Constraint.SOCtoPSDBridge (#751).\nFixed added_constraint_types for Contraint.LogDetBridge and Constraint.RootDetBridge (#870).","category":"page"},{"location":"release_notes/#[v0.9.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.1)-(August-22,-2019)","page":"Release notes","title":"v0.9.1 (August 22, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix support for Julia v1.2 (#834).\nL1 and L∞ norm epigraph cones and corresponding bridges to LP were added (#818).\nAdded tests to MOI.Test.nametest (#833).\nFix MOI.Test.soc3test for solvers not supporting infeasibility certificates (#839).\nImplements operate for operators * and / between vector function and constant (#837).\nImplements show for MOI.Utilities.IndexMap (#847).\nFix corner cases for mapping of variables in MOI.Utilities.CachingOptimizer and substitution of variables in MOI.Bridges.AbstractBridgeOptimizer (#848).\nFix transformation of constant terms for MOI.Bridges.Constraint.SOCtoPSDBridge and MOI.Bridges.Constraint.RSOCtoPSDBridge (#840).","category":"page"},{"location":"release_notes/#[v0.9.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.9.0)-(August-13,-2019)","page":"Release notes","title":"v0.9.0 (August 13, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Support for Julia v0.6 and v0.7 was dropped (#714, #717).\nA MOI.Utilities.Model implementation of ModelLike, this should replace most use cases of MOI.Utilities.@model (#781).\nadd_constrained_variable and add_constrained_variables were added (#759).\nSupport for indicator constraints was added (#709, #712).\nDualObjectiveValue attribute was added (#473).\nRawParameter attribute was added (#733).\nA dual_set function was added (#804).\nA Benchmarks submodule was added to facilitate solver benchmarking (#769).\nA submit function was added, this may for instance allow the user to submit solutions or cuts to the solver from a callback (#775).\nThe field of ObjectiveValue was renamed to result_index (#729).\nThe _constant and Utilities.getconstant function were renamed to constant\nREDUCTION_CERTIFICATE result status was added (#734).\nAbstract matrix sets were added (#731).\nTesting improvements:\nThe testing guideline was updated (#728).\nQuadratic tests were added (#697).\nUnit tests for RawStatusString, SolveTime, Silent and SolverName were added (#726, #741).\nA rotated second-order cone test was added (#759).\nA power cone test was added (#768).\nTests for ZeroOne variables with variable bounds were added (#772).\nAn unbounded test was added (#773).\nExisting tests had a few updates (#702, #703, #763).\nDocumentation improvements:\nAdded a section on CachingOptimizer (#777).\nAdded a section on UniversalFallback, Model and @model (#762).\nTransition the knapsack example to a doctest with MockOptimizer (#786).\nUtilities improvements:\nA CleverDict utility was added for a vector that automatically transform into a dictionary once a first index is removed (#767).\nThe Utilities.constant function was renamed to Utilities.constant_vector (#740).\nImplement optimizer attributes for CachingOptimizer (#745).\nRename Utilities.add_scalar_constraint to Utilities.normalize_and_add_constraint (#801).\noperate with vcat, SingleVariable and VectorOfVariables now returns a VectorOfVariables (#616).\nFix a type piracy of operate (#784).\nThe load_constraint fallback signature was fixed (#760).\nThe set_dot function was extended to work with sparse arrays (#805).\nBridges improvements:\nThe bridges no longer store the constraint function and set before it is bridged, the bridges now have to implement ConstraintFunction and ConstraintSet if the user wants to recover them. As a consequence, the @bridge macro was removed (#722).\nBridge are now instantiated with a bridge_constraint function instead of using a constructor (#730).\nFix constraint attributes for bridges (#699).\nConstraint bridges were moved to the Bridges/Constraint submodule so they should now inherit from MOI.Bridges.Constraint.Abstract and should implement MOI.Bridges.Constraint.concrete_bridge_type instead of MOI.Bridges.concrete_bridge_type (#756).\nVariable bridges were added in (#759).\nVarious improvements (#746, #747).","category":"page"},{"location":"release_notes/#[v0.8.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.4)-(March-13,-2019)","page":"Release notes","title":"v0.8.4 (March 13, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Performance improvement in default_copy_to and bridge optimizer (#696).\nAdd Silent and implement setting optimizer attributes in caching and mock optimizers (#695).\nAdd Functionize bridges (SingleVariable and VectorOfVariables) (#659).\nMinor typo fixes (#694).","category":"page"},{"location":"release_notes/#[v0.8.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.3)-(March-6,-2019)","page":"Release notes","title":"v0.8.3 (March 6, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Use zero constant in scalar constraint function of MOI.Test.copytest (#691).\nFix variable deletion with SingleVariable objective function (#690).\nFix LazyBridgeOptimizer with bridges that add no constraints (#689).\nError message improvements (#673, #685, #686, #688).\nDocumentation improvements (#682, #683, #687).\nBasis status:\nRemove VariableBasisStatus (#679).\nTest ConstraintBasisStatus and implement it in bridges (#678).\nFix inference of NumberOfVariables and NumberOfConstraints (#677).\nImplement division between a quadratic function and a number (#675).","category":"page"},{"location":"release_notes/#[v0.8.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.2)-(February-7,-2019)","page":"Release notes","title":"v0.8.2 (February 7, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add RawStatusString attribute (#629).\nDo not set names to the optimizer but only to the cache in CachingOptimizer (#638).\nMake scalar MOI functions act as scalars in broadcast (#646).\nAdd function utilities:\nImplement Base.zero (#634), Base.iszero (#643), add missing arithmetic operations (#644, #645) and fix division (#648).\nAdd a vectorize function that turns a vector of ScalarAffineFunction into a VectorAffineFunction (#642).\nImprove support for starting values:\nShow a warning in copy when starting values are not supported instead of throwing an error (#630).\nFix UniversalFallback for getting an variable or constraint attribute set to no indices (#623).\nAdd a test in contlineartest with partially set VariablePrimalStart.\nBridges improvements:\nFix StackOverFlow in LazyBridgeOptimizer when there is a cycle in the graph of bridges.\nAdd Slack bridges (#610, #650).\nAdd FlipSign bridges (#658).\nAdd tests with duplicate coefficients in ScalarAffineFunction and VectorAffineFunction (#639).\nUse tolerance to compare VariablePrimal in rotatedsoc1 test (#632).\nUse a zero constant in ScalarAffineFunction of constraints in psdt2 (#622).","category":"page"},{"location":"release_notes/#[v0.8.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.1)-(January-7,-2019)","page":"Release notes","title":"v0.8.1 (January 7, 2019)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Adding an NLP objective now overrides any objective set using the ObjectiveFunction attribute (#619).\nRename fullbridgeoptimizer into full_bridge_optimizer (#621).\nAllow custom constraint types with full_bridge_optimizer (#617).\nAdd Vectorize bridge which transforms scalar linear constraints into vector linear constraints (#615).","category":"page"},{"location":"release_notes/#[v0.8.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.8.0)-(December-18,-2018)","page":"Release notes","title":"v0.8.0 (December 18, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Rename all enum values to follow the JuMP naming guidelines for constants, for example, Optimal becomes OPTIMAL, and DualInfeasible becomes DUAL_INFEASIBLE.\nRename CachingOptimizer methods for style compliance.\nAdd an MOI.TerminationStatusCode called ALMOST_DUAL_INFEASIBLE.","category":"page"},{"location":"release_notes/#[v0.7.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.7.0)-(December-13,-2018)","page":"Release notes","title":"v0.7.0 (December 13, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Test that MOI.TerminationStatus is MOI.OptimizeNotCalled before MOI.optimize! is called.\nCheck supports_default_copy_to in tests (#594).\nKey pieces of information like optimality, infeasibility, etc., are now reported through TerminationStatusCode. It is typically no longer necessary to check the result statuses in addition to the termination status.\nAdd perspective dimension to log-det cone (#593).","category":"page"},{"location":"release_notes/#[v0.6.4](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.4)-(November-27,-2018)","page":"Release notes","title":"v0.6.4 (November 27, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Add OptimizeNotCalled termination status (#577) and improve documentation of other statuses (#575).\nAdd a solver naming guideline (#578).\nMake FeasibilitySense the default ObjectiveSense (#579).\nFix Utilities.@model and Bridges.@bridge macros for functions and sets defined outside MOI (#582).\nDocument solver-specific attributes (#580) and implement them in Utilities.CachingOptimizer (#565).","category":"page"},{"location":"release_notes/#[v0.6.3](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.3)-(November-16,-2018)","page":"Release notes","title":"v0.6.3 (November 16, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Variables and constraints are now allowed to have duplicate names. An error is thrown only on lookup. This change breaks some existing tests. (#549)\nAttributes may now be partially set (some values could be nothing). (#563)\nPerformance improvements in Utilities.Model (#549, #567, #568)\nFix bug in QuadtoSOC (#558).\nNew supports_default_copy_to method that optimizers should implement to control caching behavior.\nDocumentation improvements.","category":"page"},{"location":"release_notes/#[v0.6.2](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.2)-(October-26,-2018)","page":"Release notes","title":"v0.6.2 (October 26, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improve hygiene of @model macro (#544).\nFix bug in copy tests (#543).\nFix bug in UniversalFallback attribute getter (#540).\nAllow all correct solutions for solve_blank_obj unit test (#537).\nAdd errors for Allocate-Load and bad constraints (#534).\n[performance] Add specialized implementation of hash for VariableIndex (#533).\n[performance] Construct the name to object dictionaries lazily in model (#535).\nAdd the QuadtoSOC bridge which transforms ScalarQuadraticFunction constraints into RotatedSecondOrderCone (#483).","category":"page"},{"location":"release_notes/#[v0.6.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.1)-(September-22,-2018)","page":"Release notes","title":"v0.6.1 (September 22, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Enable PositiveSemidefiniteConeSquare set and quadratic functions in MOIB.fullbridgeoptimizer (#524).\nAdd warning in the bridge between PositiveSemidefiniteConeSquare and PositiveSemidefiniteConeTriangle when the matrix is almost symmetric (#522).\nModify MOIT.copytest to not add multiples constraints on the same variable (#521).\nAdd missing keyword argument in one of MOIU.add_scalar_constraint methods (#520).","category":"page"},{"location":"release_notes/#[v0.6.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.6.0)-(August-30,-2018)","page":"Release notes","title":"v0.6.0 (August 30, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"The MOIU.@model and MOIB.@bridge macros now support functions and sets defined in external modules. As a consequence, function and set names in the macro arguments need to be prefixed by module name.\nRename functions according to the JuMP style guide:\ncopy! with keyword arguments copynames and warnattributes -> copy_to with keyword arguments copy_names and warn_attributes;\nset! -> set;\naddvariable[s]! -> add_variable[s];\nsupportsconstraint -> supports_constraint;\naddconstraint[s]! -> add_constraint[s];\nisvalid -> is_valid;\nisempty -> is_empty;\nBase.delete! -> delete;\nmodify! -> modify;\ntransform! -> transform;\ninitialize! -> initialize;\nwrite -> write_to_file; and\nread! -> read_from_file.\nRemove free! (use Base.finalize instead).\nAdd the SquarePSD bridge which transforms PositiveSemidefiniteConeTriangle constraints into PositiveSemidefiniteConeTriangle.\nAdd result fallback for ConstraintDual of variable-wise constraint, ConstraintPrimal and ObjectiveValue.\nAdd tests for ObjectiveBound.\nAdd test for empty rows in vector linear constraint.\nRework errors: CannotError has been renamed NotAllowedError and the distinction between UnsupportedError and NotAllowedError is now about whether the element is not supported (for example, it cannot be copied a model containing this element) or the operation is not allowed (either because it is not implemented, because it cannot be performed in the current state of the model, or because it cannot be performed for a specific index)\ncanget is removed. NoSolution is added as a result status to indicate that the solver does not have either a primal or dual solution available (See #479).","category":"page"},{"location":"release_notes/#[v0.5.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.5.0)-(August-5,-2018)","page":"Release notes","title":"v0.5.0 (August 5, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fix names with CachingOptimizer.\nCleanup thanks to @mohamed82008.\nAdded a universal fallback for constraints.\nFast utilities for function canonicalization thanks to @rdeits.\nRenamed dimension field to side_dimension in the context of matrix-like sets.\nNew and improved tests for cases like duplicate terms and ObjectiveBound.\nRemoved cantransform, canaddconstraint, canaddvariable, canset, canmodify, and candelete functions from the API. They are replaced by a new set of errors that are thrown: Subtypes of UnsupportedError indicate unsupported operations, while subtypes of CannotError indicate operations that cannot be performed in the current state.\nThe API for copy! is updated to remove the CopyResult type.\nUpdates for the new JuMP style guide.","category":"page"},{"location":"release_notes/#[v0.4.1](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.4.1)-(June-28,-2018)","page":"Release notes","title":"v0.4.1 (June 28, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Fixes vector function modification on 32 bits.\nFixes Bellman-Ford algorithm for bridges.\nAdded an NLP test with FeasibilitySense.\nUpdate modification documentation.","category":"page"},{"location":"release_notes/#[v0.4.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.4.0)-(June-23,-2018)","page":"Release notes","title":"v0.4.0 (June 23, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Helper constructors for VectorAffineTerm and VectorQuadraticTerm.\nAdded modify_lhs to TestConfig.\nAdditional unit tests for optimizers.\nAdded a type parameter to CachingOptimizer for the optimizer field.\nNew API for problem modification (#388)\nTests pass without deprecation warnings on Julia 0.7.\nSmall fixes and documentation updates.","category":"page"},{"location":"release_notes/#[v0.3.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.3.0)-(May-25,-2018)","page":"Release notes","title":"v0.3.0 (May 25, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Functions have been redefined to use arrays-of-structs instead of structs-of-arrays.\nImprovements to MockOptimizer.\nSignificant changes to Bridges.\nNew and improved unit tests.\nFixes for Julia 0.7.","category":"page"},{"location":"release_notes/#[v0.2.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.2.0)-(April-24,-2018)","page":"Release notes","title":"v0.2.0 (April 24, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Improvements to and better coverage of Tests.\nDocumentation fixes.\nSolverName attribute.\nChanges to the NLP interface (new definition of variable order and arrays of structs for bound pairs and sparsity patterns).\nAddition of NLP tests.\nIntroduction of UniversalFallback.\ncopynames keyword argument to MOI.copy!.\nAdd Bridges submodule.","category":"page"},{"location":"release_notes/#[v0.1.0](https://github.com/jump-dev/MathOptInterface.jl/releases/tag/v0.1.0)-(February-28,-2018)","page":"Release notes","title":"v0.1.0 (February 28, 2018)","text":"","category":"section"},{"location":"release_notes/","page":"Release notes","title":"Release notes","text":"Initial public release.\nThe framework for MOI was developed at the JuMP-dev workshop at MIT in June 2017 as a sorely needed replacement for MathProgBase.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/constraints/#Constraints","page":"Constraints","title":"Constraints","text":"","category":"section"},{"location":"manual/constraints/#Add-a-constraint","page":"Constraints","title":"Add a constraint","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use add_constraint to add a single constraint.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> c = MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(2))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"add_constraint returns a ConstraintIndex type, which is used to refer to the added constraint in other calls.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Check if a ConstraintIndex is valid using is_valid.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.is_valid(model, c)\ntrue","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use add_constraints to add a number of constraints of the same type.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> c = MOI.add_constraints(\n model,\n [x[1], x[2]],\n [MOI.GreaterThan(0.0), MOI.GreaterThan(1.0)]\n )\n2-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(2)","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"This time, a vector of ConstraintIndex are returned.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use supports_constraint to check if the model supports adding a constraint type.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.supports_constraint(\n model,\n MOI.VariableIndex,\n MOI.GreaterThan{Float64},\n )\ntrue","category":"page"},{"location":"manual/constraints/#Delete-a-constraint","page":"Constraints","title":"Delete a constraint","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Use delete to delete a constraint.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.delete(model, c)\n\njulia> MOI.is_valid(model, c)\nfalse","category":"page"},{"location":"manual/constraints/#Constraint-attributes","page":"Constraints","title":"Constraint attributes","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"The following attributes are available for constraints:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"ConstraintName\nConstraintPrimalStart\nConstraintDualStart\nConstraintPrimal\nConstraintDual\nConstraintBasisStatus\nConstraintFunction\nCanonicalConstraintFunction\nConstraintSet","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Get and set these attributes using get and set.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"julia> MOI.set(model, MOI.ConstraintName(), c, \"con_c\")\n\njulia> MOI.get(model, MOI.ConstraintName(), c)\n\"con_c\"","category":"page"},{"location":"manual/constraints/#Constraints-by-function-set-pairs","page":"Constraints","title":"Constraints by function-set pairs","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Below is a list of common constraint types and how they are represented as function-set pairs in MOI. In the notation below, x is a vector of decision variables, x_i is a scalar decision variable, alpha beta are scalar constants, a b are constant vectors, A is a constant matrix and mathbbR_+ (resp. mathbbR_-) is the set of non-negative (resp. non-positive) real numbers.","category":"page"},{"location":"manual/constraints/#Linear-constraints","page":"Constraints","title":"Linear constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\na^Tx le beta ScalarAffineFunction LessThan\na^Tx ge alpha ScalarAffineFunction GreaterThan\na^Tx = beta ScalarAffineFunction EqualTo\nalpha le a^Tx le beta ScalarAffineFunction Interval\nx_i le beta VariableIndex LessThan\nx_i ge alpha VariableIndex GreaterThan\nx_i = beta VariableIndex EqualTo\nalpha le x_i le beta VariableIndex Interval\nAx + b in mathbbR_+^n VectorAffineFunction Nonnegatives\nAx + b in mathbbR_-^n VectorAffineFunction Nonpositives\nAx + b = 0 VectorAffineFunction Zeros","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"By convention, solvers are not expected to support nonzero constant terms in the ScalarAffineFunctions the first four rows of the preceding table because they are redundant with the parameters of the sets. For example, encode 2x + 1 le 2 as 2x le 1.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Constraints with VariableIndex in LessThan, GreaterThan, EqualTo, or Interval sets have a natural interpretation as variable bounds. As such, it is typically not natural to impose multiple lower- or upper-bounds on the same variable, and the solver interfaces will throw respectively LowerBoundAlreadySet or UpperBoundAlreadySet.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Moreover, adding two VariableIndex constraints on the same variable with the same set is impossible because they share the same index as it is the index of the variable, see ConstraintIndex.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"It is natural, however, to impose upper- and lower-bounds separately as two different constraints on a single variable. The difference between imposing bounds by using a single Interval constraint and by using separate LessThan and GreaterThan constraints is that the latter will allow the solver to return separate dual multipliers for the two bounds, while the former will allow the solver to return only a single dual for the interval constraint.","category":"page"},{"location":"manual/constraints/#Conic-constraints","page":"Constraints","title":"Conic constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\nlVert Ax + brVert_2 le c^Tx + d VectorAffineFunction SecondOrderCone\ny ge lVert x rVert_2 VectorOfVariables SecondOrderCone\n2yz ge lVert x rVert_2^2 yz ge 0 VectorOfVariables RotatedSecondOrderCone\n(a_1^Tx + b_1a_2^Tx + b_2a_3^Tx + b_3) in mathcalE VectorAffineFunction ExponentialCone\nA(x) in mathcalS_+ VectorAffineFunction PositiveSemidefiniteConeTriangle\nB(x) in mathcalS_+ VectorAffineFunction PositiveSemidefiniteConeSquare\nx in mathcalS_+ VectorOfVariables PositiveSemidefiniteConeTriangle\nx in mathcalS_+ VectorOfVariables PositiveSemidefiniteConeSquare","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"where mathcalE is the exponential cone (see ExponentialCone), mathcalS_+ is the set of positive semidefinite symmetric matrices, A is an affine map that outputs symmetric matrices and B is an affine map that outputs square matrices.","category":"page"},{"location":"manual/constraints/#Quadratic-constraints","page":"Constraints","title":"Quadratic constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\nfrac12x^TQx + a^Tx + b ge 0 ScalarQuadraticFunction GreaterThan\nfrac12x^TQx + a^Tx + b le 0 ScalarQuadraticFunction LessThan\nfrac12x^TQx + a^Tx + b = 0 ScalarQuadraticFunction EqualTo\nBilinear matrix inequality VectorQuadraticFunction PositiveSemidefiniteCone...","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"note: Note\nFor more details on the internal format of the quadratic functions see ScalarQuadraticFunction or VectorQuadraticFunction.","category":"page"},{"location":"manual/constraints/#Discrete-and-logical-constraints","page":"Constraints","title":"Discrete and logical constraints","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Mathematical Constraint MOI Function MOI Set\nx_i in mathbbZ VariableIndex Integer\nx_i in 01 VariableIndex ZeroOne\nx_i in 0 cup lu VariableIndex Semicontinuous\nx_i in 0 cup ll+1ldotsu-1u VariableIndex Semiinteger\nAt most one component of x can be nonzero VectorOfVariables SOS1\nAt most two components of x can be nonzero, and if so they must be adjacent components VectorOfVariables SOS2\ny = 1 implies a^T x in S VectorAffineFunction Indicator","category":"page"},{"location":"manual/constraints/#JuMP-mapping","page":"Constraints","title":"JuMP mapping","text":"","category":"section"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"The following bullet points show examples of how JuMP constraints are translated into MOI function-set pairs:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"@constraint(m, 2x + y <= 10) becomes ScalarAffineFunction-in-LessThan\n@constraint(m, 2x + y >= 10) becomes ScalarAffineFunction-in-GreaterThan\n@constraint(m, 2x + y == 10) becomes ScalarAffineFunction-in-EqualTo\n@constraint(m, 0 <= 2x + y <= 10) becomes ScalarAffineFunction-in-Interval\n@constraint(m, 2x + y in ArbitrarySet()) becomes ScalarAffineFunction-in-ArbitrarySet.","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"Variable bounds are handled in a similar fashion:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"@variable(m, x <= 1) becomes VariableIndex-in-LessThan\n@variable(m, x >= 1) becomes VariableIndex-in-GreaterThan","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"One notable difference is that a variable with an upper and lower bound is translated into two constraints, rather than an interval, that is:","category":"page"},{"location":"manual/constraints/","page":"Constraints","title":"Constraints","text":"@variable(m, 0 <= x <= 1) becomes VariableIndex-in-LessThan and VariableIndex-in-GreaterThan.","category":"page"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/nonlinear/#Nonlinear-programming","page":"Nonlinear programming","title":"Nonlinear programming","text":"","category":"section"},{"location":"reference/nonlinear/#Types","page":"Nonlinear programming","title":"Types","text":"","category":"section"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"AbstractNLPEvaluator\nNLPBoundsPair\nNLPBlockData","category":"page"},{"location":"reference/nonlinear/#MathOptInterface.AbstractNLPEvaluator","page":"Nonlinear programming","title":"MathOptInterface.AbstractNLPEvaluator","text":"AbstractNLPEvaluator\n\nAbstract supertype for the callback object that is used to query function values, derivatives, and expression graphs.\n\nIt is used in NLPBlockData.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBoundsPair","page":"Nonlinear programming","title":"MathOptInterface.NLPBoundsPair","text":"NLPBoundsPair(lower::Float64, upper::Float64)\n\nA struct holding a pair of lower and upper bounds.\n\n-Inf and Inf can be used to indicate no lower or upper bound, respectively.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlockData","page":"Nonlinear programming","title":"MathOptInterface.NLPBlockData","text":"struct NLPBlockData\n constraint_bounds::Vector{NLPBoundsPair}\n evaluator::AbstractNLPEvaluator\n has_objective::Bool\nend\n\nA struct encoding a set of nonlinear constraints of the form lb le g(x) le ub and, if has_objective == true, a nonlinear objective function f(x).\n\nNonlinear objectives override any objective set by using the ObjectiveFunction attribute.\n\nThe evaluator is a callback object that is used to query function values, derivatives, and expression graphs. If has_objective == false, then it is an error to query properties of the objective function, and in Hessian-of-the-Lagrangian queries, σ must be set to zero.\n\nnote: Note\nThroughout the evaluator, all variables are ordered according to ListOfVariableIndices. Hence, MOI copies of nonlinear problems must not re-order variables.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#Attributes","page":"Nonlinear programming","title":"Attributes","text":"","category":"section"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"NLPBlock\nNLPBlockDual\nNLPBlockDualStart","category":"page"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlock","page":"Nonlinear programming","title":"MathOptInterface.NLPBlock","text":"NLPBlock()\n\nAn AbstractModelAttribute that stores an NLPBlockData, representing a set of nonlinear constraints, and optionally a nonlinear objective.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlockDual","page":"Nonlinear programming","title":"MathOptInterface.NLPBlockDual","text":"NLPBlockDual(result_index::Int = 1)\n\nAn AbstractModelAttribute for the Lagrange multipliers on the constraints from the NLPBlock in result result_index.\n\nIf result_index is omitted, it is 1 by default.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#MathOptInterface.NLPBlockDualStart","page":"Nonlinear programming","title":"MathOptInterface.NLPBlockDualStart","text":"NLPBlockDualStart()\n\nAn AbstractModelAttribute for the initial assignment of the Lagrange multipliers on the constraints from the NLPBlock that the solver may use to warm-start the solve.\n\n\n\n\n\n","category":"type"},{"location":"reference/nonlinear/#Functions","page":"Nonlinear programming","title":"Functions","text":"","category":"section"},{"location":"reference/nonlinear/","page":"Nonlinear programming","title":"Nonlinear programming","text":"initialize\nfeatures_available\neval_objective\neval_constraint\neval_objective_gradient\njacobian_structure\neval_constraint_gradient\nconstraint_gradient_structure\neval_constraint_jacobian\neval_constraint_jacobian_product\neval_constraint_jacobian_transpose_product\nhessian_lagrangian_structure\nhessian_objective_structure\nhessian_constraint_structure\neval_hessian_objective\neval_hessian_constraint\neval_hessian_lagrangian\neval_hessian_lagrangian_product\nobjective_expr\nconstraint_expr","category":"page"},{"location":"reference/nonlinear/#MathOptInterface.initialize","page":"Nonlinear programming","title":"MathOptInterface.initialize","text":"initialize(\n d::AbstractNLPEvaluator,\n requested_features::Vector{Symbol},\n)::Nothing\n\nInitialize d with the set of features in requested_features. Check features_available before calling initialize to see what features are supported by d.\n\nwarning: Warning\nThis method must be called before any other methods.\n\nFeatures\n\nThe following features are defined:\n\n:Grad: enables eval_objective_gradient\n:Jac: enables eval_constraint_jacobian\n:JacVec: enables eval_constraint_jacobian_product and eval_constraint_jacobian_transpose_product\n:Hess: enables eval_hessian_lagrangian\n:HessVec: enables eval_hessian_lagrangian_product\n:ExprGraph: enables objective_expr and constraint_expr.\n\nIn all cases, including when requested_features is empty, eval_objective and eval_constraint are supported.\n\nExamples\n\nMOI.initialize(d, Symbol[])\nMOI.initialize(d, [:ExprGraph])\nMOI.initialize(d, MOI.features_available(d))\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.features_available","page":"Nonlinear programming","title":"MathOptInterface.features_available","text":"features_available(d::AbstractNLPEvaluator)::Vector{Symbol}\n\nReturns the subset of features available for this problem instance.\n\nSee initialize for the list of defined features.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_objective","page":"Nonlinear programming","title":"MathOptInterface.eval_objective","text":"eval_objective(d::AbstractNLPEvaluator, x::AbstractVector{T})::T where {T}\n\nEvaluate the objective f(x), returning a scalar value.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint","text":"eval_constraint(d::AbstractNLPEvaluator,\n g::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nGiven a set of vector-valued constraints l le g(x) le u, evaluate the constraint function g(x), storing the result in the vector g.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_objective_gradient","page":"Nonlinear programming","title":"MathOptInterface.eval_objective_gradient","text":"eval_objective_gradient(\n d::AbstractNLPEvaluator,\n grad::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nEvaluate the gradient of the objective function grad = nabla f(x) as a dense vector, storing the result in the vector grad.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that grad is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.jacobian_structure","page":"Nonlinear programming","title":"MathOptInterface.jacobian_structure","text":"jacobian_structure(d::AbstractNLPEvaluator)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Jacobian matrix: J_g(x) = left beginarrayc nabla g_1(x) nabla g_2(x) vdots nabla g_m(x) endarrayright where g_i is the itextth component of the nonlinear constraints g(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_gradient","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_gradient","text":"eval_constraint_gradient(\n d::AbstractNLPEvaluator,\n ∇g::AbstractVector{T},\n x::AbstractVector{T},\n i::Int,\n)::Nothing where {T}\n\nEvaluate the gradient of constraint i, nabla g_i(x), and store the non-zero values in ∇g, corresponding to the structure returned by constraint_gradient_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that ∇g is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.constraint_gradient_structure","page":"Nonlinear programming","title":"MathOptInterface.constraint_gradient_structure","text":"constraint_gradient_structure(d::AbstractNLPEvaluator, i::Int)::Vector{Int64}\n\nReturns a vector of indices, where each element indicates the position of a structurally nonzero element in the gradient of constraint nabla g_i(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_jacobian","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_jacobian","text":"eval_constraint_jacobian(d::AbstractNLPEvaluator,\n J::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nEvaluates the sparse Jacobian matrix J_g(x) = left beginarrayc nabla g_1(x) nabla g_2(x) vdots nabla g_m(x) endarrayright.\n\nThe result is stored in the vector J in the same order as the indices returned by jacobian_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that J is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_jacobian_product","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_jacobian_product","text":"eval_constraint_jacobian_product(\n d::AbstractNLPEvaluator,\n y::AbstractVector{T},\n x::AbstractVector{T},\n w::AbstractVector{T},\n)::Nothing where {T}\n\nComputes the Jacobian-vector product y = J_g(x)w, storing the result in the vector y.\n\nThe vectors have dimensions such that length(w) == length(x), and length(y) is the number of nonlinear constraints.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_constraint_jacobian_transpose_product","page":"Nonlinear programming","title":"MathOptInterface.eval_constraint_jacobian_transpose_product","text":"eval_constraint_jacobian_transpose_product(\n d::AbstractNLPEvaluator,\n y::AbstractVector{T},\n x::AbstractVector{T},\n w::AbstractVector{T},\n)::Nothing where {T}\n\nComputes the Jacobian-transpose-vector product y = J_g(x)^Tw, storing the result in the vector y.\n\nThe vectors have dimensions such that length(y) == length(x), and length(w) is the number of nonlinear constraints.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that y is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.hessian_lagrangian_structure","page":"Nonlinear programming","title":"MathOptInterface.hessian_lagrangian_structure","text":"hessian_lagrangian_structure(\n d::AbstractNLPEvaluator,\n)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian-of-the-Lagrangian matrix: nabla^2 f(x) + sum_i=1^m nabla^2 g_i(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nAny mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.hessian_objective_structure","page":"Nonlinear programming","title":"MathOptInterface.hessian_objective_structure","text":"hessian_objective_structure(\n d::AbstractNLPEvaluator,\n)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: nabla^2 f(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nAny mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.hessian_constraint_structure","page":"Nonlinear programming","title":"MathOptInterface.hessian_constraint_structure","text":"hessian_constraint_structure(\n d::AbstractNLPEvaluator,\n i::Int64,\n)::Vector{Tuple{Int64,Int64}}\n\nReturns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element in the Hessian matrix: nabla^2 g_i(x).\n\nThe indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.\n\nAny mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.\n\nThe sparsity structure is assumed to be independent of the point x.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_objective","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_objective","text":"eval_hessian_objective(\n d::AbstractNLPEvaluator,\n H::AbstractVector{T},\n x::AbstractVector{T},\n)::Nothing where {T}\n\nThis function computes the sparse Hessian matrix: nabla^2 f(x), storing the result in the vector H in the same order as the indices returned by hessian_objective_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_constraint","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_constraint","text":"eval_hessian_constraint(\n d::AbstractNLPEvaluator,\n H::AbstractVector{T},\n x::AbstractVector{T},\n i::Int64,\n)::Nothing where {T}\n\nThis function computes the sparse Hessian matrix: nabla^2 g_i(x), storing the result in the vector H in the same order as the indices returned by hessian_constraint_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_lagrangian","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_lagrangian","text":"eval_hessian_lagrangian(\n d::AbstractNLPEvaluator,\n H::AbstractVector{T},\n x::AbstractVector{T},\n σ::T,\n μ::AbstractVector{T},\n)::Nothing where {T}\n\nGiven scalar weight σ and vector of constraint weights μ, this function computes the sparse Hessian-of-the-Lagrangian matrix: sigmanabla^2 f(x) + sum_i=1^m mu_i nabla^2 g_i(x), storing the result in the vector H in the same order as the indices returned by hessian_lagrangian_structure.\n\nImplementation notes\n\nWhen implementing this method, you must not assume that H is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.eval_hessian_lagrangian_product","page":"Nonlinear programming","title":"MathOptInterface.eval_hessian_lagrangian_product","text":"eval_hessian_lagrangian_product(\n d::AbstractNLPEvaluator,\n h::AbstractVector{T},\n x::AbstractVector{T},\n v::AbstractVector{T},\n σ::T,\n μ::AbstractVector{T},\n)::Nothing where {T}\n\nGiven scalar weight σ and vector of constraint weights μ, computes the Hessian-of-the-Lagrangian-vector product h = left(sigmanabla^2 f(x) + sum_i=1^m mu_i nabla^2 g_i(x)right)v, storing the result in the vector h.\n\nThe vectors have dimensions such that length(h) == length(x) == length(v).\n\nImplementation notes\n\nWhen implementing this method, you must not assume that h is Vector{Float64}, but you may assume that it supports setindex! and length. For example, it may be the view of a vector.\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.objective_expr","page":"Nonlinear programming","title":"MathOptInterface.objective_expr","text":"objective_expr(d::AbstractNLPEvaluator)::Expr\n\nReturns a Julia Expr object representing the expression graph of the objective function.\n\nFormat\n\nThe expression has a number of limitations, compared with arbitrary Julia expressions:\n\nAll sums and products are flattened out as simple Expr(:+, ...) and Expr(:*, ...) objects.\nAll decision variables must be of the form Expr(:ref, :x, MOI.VariableIndex(i)), where i is the ith variable in ListOfVariableIndices.\nThere are currently no restrictions on recognized functions; typically these will be built-in Julia functions like ^, exp, log, cos, tan, sqrt, etc., but modeling interfaces may choose to extend these basic functions, or error if they encounter unsupported functions.\n\nExamples\n\nThe expression x_1+sin(x_2exp(x_3)) is represented as\n\n:(x[MOI.VariableIndex(1)] + sin(x[MOI.VariableIndex(2)] / exp(x[MOI.VariableIndex[3]])))\n\nor equivalently\n\nExpr(\n :call,\n :+,\n Expr(:ref, :x, MOI.VariableIndex(1)),\n Expr(\n :call,\n :/,\n Expr(:call, :sin, Expr(:ref, :x, MOI.VariableIndex(2))),\n Expr(:call, :exp, Expr(:ref, :x, MOI.VariableIndex(3))),\n ),\n)\n\n\n\n\n\n","category":"function"},{"location":"reference/nonlinear/#MathOptInterface.constraint_expr","page":"Nonlinear programming","title":"MathOptInterface.constraint_expr","text":"constraint_expr(d::AbstractNLPEvaluator, i::Integer)::Expr\n\nReturns a Julia Expr object representing the expression graph for the itextth nonlinear constraint.\n\nFormat\n\nThe format is the same as objective_expr, with an additional comparison operator indicating the sense of and bounds on the constraint.\n\nFor single-sided comparisons, the body of the constraint must be on the left-hand side, and the right-hand side must be a constant.\n\nFor double-sided comparisons (that is, l le f(x) le u), the body of the constraint must be in the middle, and the left- and right-hand sides must be constants.\n\nThe bounds on the constraints must match the NLPBoundsPairs passed to NLPBlockData.\n\nExamples\n\n:(x[MOI.VariableIndex(1)]^2 <= 1.0)\n:(x[MOI.VariableIndex(1)]^2 >= 2.0)\n:(x[MOI.VariableIndex(1)]^2 == 3.0)\n:(4.0 <= x[MOI.VariableIndex(1)]^2 <= 5.0)\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"reference/standard_form/#Standard-form","page":"Standard form","title":"Standard form","text":"","category":"section"},{"location":"reference/standard_form/#Functions","page":"Standard form","title":"Functions","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractFunction\noutput_dimension\nconstant","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractFunction","page":"Standard form","title":"MathOptInterface.AbstractFunction","text":"AbstractFunction\n\nAbstract supertype for function objects.\n\nRequired methods\n\nAll functions must implement:\n\nBase.copy\nBase.isapprox\nconstant\n\nAbstract subtypes of AbstractFunction may require additional methods to be implemented.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.output_dimension","page":"Standard form","title":"MathOptInterface.output_dimension","text":"output_dimension(f::AbstractFunction)\n\nReturn 1 if f is an AbstractScalarFunction, or the number of output components if f is an AbstractVectorFunction.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.constant","page":"Standard form","title":"MathOptInterface.constant","text":"constant(f::AbstractFunction[, ::Type{T}]) where {T}\n\nReturns the constant term of a scalar-valued function, or the constant vector of a vector-valued function.\n\nIf f is untyped and T is provided, returns zero(T).\n\n\n\n\n\nconstant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})\n\nReturns the constant term of the set set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.constant(MOI.GreaterThan(1.0))\n1.0\n\njulia> MOI.constant(MOI.LessThan(2.5))\n2.5\n\njulia> MOI.constant(MOI.EqualTo(3))\n3\n\njulia> MOI.constant(MOI.Parameter(4.5))\n4.5\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#Scalar-functions","page":"Standard form","title":"Scalar functions","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractScalarFunction\nVariableIndex\nScalarAffineTerm\nScalarAffineFunction\nScalarQuadraticTerm\nScalarQuadraticFunction\nScalarNonlinearFunction","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractScalarFunction","page":"Standard form","title":"MathOptInterface.AbstractScalarFunction","text":"abstract type AbstractScalarFunction <: AbstractFunction\n\nAbstract supertype for scalar-valued AbstractFunctions.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VariableIndex","page":"Standard form","title":"MathOptInterface.VariableIndex","text":"VariableIndex\n\nA type-safe wrapper for Int64 for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarAffineTerm","page":"Standard form","title":"MathOptInterface.ScalarAffineTerm","text":"ScalarAffineTerm{T}(coefficient::T, variable::VariableIndex) where {T}\n\nRepresents the scalar-valued term coefficient * variable.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> MOI.ScalarAffineTerm(2.0, x)\nMathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarAffineFunction","page":"Standard form","title":"MathOptInterface.ScalarAffineFunction","text":"ScalarAffineFunction{T}(\n terms::Vector{ScalarAffineTerm{T}},\n constant::T,\n) where {T}\n\nRepresents the scalar-valued affine function a^top x + b, where:\n\na^top x is represented by the vector of ScalarAffineTerms\nb is a scalar constant::T\n\nDuplicates\n\nDuplicate variable indices in terms are accepted, and the corresponding coefficients are summed together.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> terms = [MOI.ScalarAffineTerm(2.0, x), MOI.ScalarAffineTerm(3.0, x)]\n2-element Vector{MathOptInterface.ScalarAffineTerm{Float64}}:\n MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))\n MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1))\n\njulia> f = MOI.ScalarAffineFunction(terms, 4.0)\n4.0 + 2.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarQuadraticTerm","page":"Standard form","title":"MathOptInterface.ScalarQuadraticTerm","text":"ScalarQuadraticTerm{T}(\n coefficient::T,\n variable_1::VariableIndex,\n variable_2::VariableIndex,\n) where {T}\n\nRepresents the scalar-valued term c x_i x_j where c is coefficient, x_i is variable_1 and x_j is variable_2.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> MOI.ScalarQuadraticTerm(2.0, x, x)\nMathOptInterface.ScalarQuadraticTerm{Float64}(2.0, MOI.VariableIndex(1), MOI.VariableIndex(1))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarQuadraticFunction","page":"Standard form","title":"MathOptInterface.ScalarQuadraticFunction","text":"ScalarQuadraticFunction{T}(\n quadratic_terms::Vector{ScalarQuadraticTerm{T}},\n affine_terms::Vector{ScalarAffineTerm{T}},\n constant::T,\n) wher {T}\n\nThe scalar-valued quadratic function frac12x^top Q x + a^top x + b, where:\n\nQ is the symmetric matrix given by the vector of ScalarQuadraticTerms\na^top x is a sparse vector given by the vector of ScalarAffineTerms\nb is the scalar constant::T.\n\nDuplicates\n\nDuplicate indices in quadratic_terms or affine_terms are accepted, and the corresponding coefficients are summed together.\n\nIn quadratic_terms, \"mirrored\" indices, (q, r) and (r, q) where r and q are VariableIndexes, are considered duplicates; only one needs to be specified.\n\nThe 0.5 factor\n\nCoupled with the interpretation of mirrored indices, the 0.5 factor in front of the Q matrix is a common source of bugs.\n\nAs a rule, to represent a * x^2 + b * x * y:\n\nThe coefficient a in front of squared variables (diagonal elements in Q) must be doubled when creating a ScalarQuadraticTerm\nThe coefficient b in front of off-diagonal elements in Q should be left as b, be cause the mirrored index b * y * x will be implicitly added.\n\nExample\n\nTo represent the function f(x y) = 2 * x^2 + 3 * x * y + 4 * x + 5, do:\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> y = MOI.VariableIndex(2);\n\njulia> constant = 5.0;\n\njulia> affine_terms = [MOI.ScalarAffineTerm(4.0, x)];\n\njulia> quadratic_terms = [\n MOI.ScalarQuadraticTerm(4.0, x, x), # Note the changed coefficient\n MOI.ScalarQuadraticTerm(3.0, x, y),\n ]\n2-element Vector{MathOptInterface.ScalarQuadraticTerm{Float64}}:\n MathOptInterface.ScalarQuadraticTerm{Float64}(4.0, MOI.VariableIndex(1), MOI.VariableIndex(1))\n MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(2))\n\njulia> f = MOI.ScalarQuadraticFunction(quadratic_terms, affine_terms, constant)\n5.0 + 4.0 MOI.VariableIndex(1) + 2.0 MOI.VariableIndex(1)² + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ScalarNonlinearFunction","page":"Standard form","title":"MathOptInterface.ScalarNonlinearFunction","text":"ScalarNonlinearFunction(head::Symbol, args::Vector{Any})\n\nThe scalar-valued nonlinear function head(args...), represented as a symbolic expression tree, with the call operator head and ordered arguments in args.\n\nhead\n\nThe head::Symbol must be an operator supported by the model.\n\nThe default list of supported univariate operators is given by:\n\nNonlinear.DEFAULT_UNIVARIATE_OPERATORS\n\nand the default list of supported multivariate operators is given by:\n\nNonlinear.DEFAULT_MULTIVARIATE_OPERATORS\n\nAdditional operators can be registered by setting a UserDefinedFunction attribute.\n\nSee the full list of operators supported by a ModelLike by querying ListOfSupportedNonlinearOperators.\n\nargs\n\nThe vector args contains the arguments to the nonlinear function. If the operator is univariate, it must contain one element. Otherwise, it may contain multiple elements.\n\nEach element must be one of the following:\n\nA constant value of type T<:Real\nA VariableIndex\nA ScalarAffineFunction\nA ScalarQuadraticFunction\nA ScalarNonlinearFunction\n\nUnsupported operators\n\nIf the optimizer does not support head, an UnsupportedNonlinearOperator error will be thrown.\n\nThere is no guarantee about when this error will be thrown; it may be thrown when the function is first added to the model, or it may be thrown when optimize! is called.\n\nExample\n\nTo represent the function f(x) = sin(x)^2, do:\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> MOI.ScalarNonlinearFunction(\n :^,\n Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2],\n )\n^(sin(MOI.VariableIndex(1)), (2))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Vector-functions","page":"Standard form","title":"Vector functions","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractVectorFunction\nVectorOfVariables\nVectorAffineTerm\nVectorAffineFunction\nVectorQuadraticTerm\nVectorQuadraticFunction\nVectorNonlinearFunction","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractVectorFunction","page":"Standard form","title":"MathOptInterface.AbstractVectorFunction","text":"abstract type AbstractVectorFunction <: AbstractFunction\n\nAbstract supertype for vector-valued AbstractFunctions.\n\nRequired methods\n\nAll subtypes of AbstractVectorFunction must implement:\n\noutput_dimension\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorOfVariables","page":"Standard form","title":"MathOptInterface.VectorOfVariables","text":"VectorOfVariables(variables::Vector{VariableIndex}) <: AbstractVectorFunction\n\nThe vector-valued function f(x) = variables, where variables is a subset of VariableIndexes in the model.\n\nThe list of variables may contain duplicates.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex.(1:2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n\njulia> f = MOI.VectorOfVariables([x[1], x[2], x[1]])\n┌ ┐\n│MOI.VariableIndex(1)│\n│MOI.VariableIndex(2)│\n│MOI.VariableIndex(1)│\n└ ┘\n\njulia> MOI.output_dimension(f)\n3\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorAffineTerm","page":"Standard form","title":"MathOptInterface.VectorAffineTerm","text":"VectorAffineTerm{T}(\n output_index::Int64,\n scalar_term::ScalarAffineTerm{T},\n) where {T}\n\nA VectorAffineTerm is a scalar_term that appears in the output_index row of the vector-valued VectorAffineFunction or VectorQuadraticFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x))\nMathOptInterface.VectorAffineTerm{Float64}(2, MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1)))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorAffineFunction","page":"Standard form","title":"MathOptInterface.VectorAffineFunction","text":"VectorAffineFunction{T}(\n terms::Vector{VectorAffineTerm{T}},\n constants::Vector{T},\n) where {T}\n\nThe vector-valued affine function A x + b, where:\n\nA x is the sparse matrix given by the vector of VectorAffineTerms\nb is the vector constants\n\nDuplicates\n\nDuplicate indices in the A are accepted, and the corresponding coefficients are summed together.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> terms = [\n MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),\n MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),\n ];\n\njulia> f = MOI.VectorAffineFunction(terms, [4.0, 5.0])\n┌ ┐\n│4.0 + 2.0 MOI.VariableIndex(1)│\n│5.0 + 3.0 MOI.VariableIndex(1)│\n└ ┘\n\njulia> MOI.output_dimension(f)\n2\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorQuadraticTerm","page":"Standard form","title":"MathOptInterface.VectorQuadraticTerm","text":"VectorQuadraticTerm{T}(\n output_index::Int64,\n scalar_term::ScalarQuadraticTerm{T},\n) where {T}\n\nA VectorQuadraticTerm is a ScalarQuadraticTerm scalar_term that appears in the output_index row of the vector-valued VectorQuadraticFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, x))\nMathOptInterface.VectorQuadraticTerm{Float64}(2, MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(1)))\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorQuadraticFunction","page":"Standard form","title":"MathOptInterface.VectorQuadraticFunction","text":"VectorQuadraticFunction{T}(\n quadratic_terms::Vector{VectorQuadraticTerm{T}},\n affine_terms::Vector{VectorAffineTerm{T}},\n constants::Vector{T},\n) where {T}\n\nThe vector-valued quadratic function with ith component (\"output index\") defined as frac12x^top Q_i x + a_i^top x + b_i, where:\n\nfrac12x^top Q_i x is the symmetric matrix given by the VectorQuadraticTerm elements in quadratic_terms with output_index == i\na_i^top x is the sparse vector given by the VectorAffineTerm elements in affine_terms with output_index == i\nb_i is a scalar given by constants[i]\n\nDuplicates\n\nDuplicate indices in quadratic_terms and affine_terms with the same output_index are handled in the same manner as duplicates in ScalarQuadraticFunction.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1);\n\njulia> y = MOI.VariableIndex(2);\n\njulia> constants = [4.0, 5.0];\n\njulia> affine_terms = [\n MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),\n MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),\n ];\n\njulia> quad_terms = [\n MOI.VectorQuadraticTerm(Int64(1), MOI.ScalarQuadraticTerm(2.0, x, x)),\n MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, y)),\n ];\n\njulia> f = MOI.VectorQuadraticFunction(quad_terms, affine_terms, constants)\n┌ ┐\n│4.0 + 2.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)² │\n│5.0 + 3.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)│\n└ ┘\n\njulia> MOI.output_dimension(f)\n2\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.VectorNonlinearFunction","page":"Standard form","title":"MathOptInterface.VectorNonlinearFunction","text":"VectorNonlinearFunction(args::Vector{ScalarNonlinearFunction})\n\nThe vector-valued nonlinear function composed of a vector of ScalarNonlinearFunction.\n\nargs\n\nThe vector args contains the scalar elements of the nonlinear function. Each element must be a ScalarNonlinearFunction, but if you pass a Vector{Any}, the elements can be automatically converted from one of the following:\n\nA constant value of type T<:Real\nA VariableIndex\nA ScalarAffineFunction\nA ScalarQuadraticFunction\nA ScalarNonlinearFunction\n\nExample\n\nTo represent the function f(x) = sin(x)^2 x, do:\n\njulia> import MathOptInterface as MOI\n\njulia> x = MOI.VariableIndex(1)\nMOI.VariableIndex(1)\n\njulia> g = MOI.ScalarNonlinearFunction(\n :^,\n Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2.0],\n )\n^(sin(MOI.VariableIndex(1)), 2.0)\n\njulia> MOI.VectorNonlinearFunction([g, x])\n┌ ┐\n│^(sin(MOI.VariableIndex(1)), 2.0)│\n│+(MOI.VariableIndex(1)) │\n└ ┘\n\nNote the automatic conversion from x to +(x).\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Sets","page":"Standard form","title":"Sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractSet\nAbstractScalarSet\nAbstractVectorSet","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractSet","page":"Standard form","title":"MathOptInterface.AbstractSet","text":"AbstractSet\n\nAbstract supertype for set objects used to encode constraints.\n\nRequired methods\n\nFor sets of type S with isbitstype(S) == false, you must implement:\n\nBase.copy(set::S)\nBase.:(==)(x::S, y::S)\n\nSubtypes of AbstractSet such as AbstractScalarSet and AbstractVectorSet may prescribe additional required methods.\n\nOptional methods\n\nYou may optionally implement:\n\ndual_set\ndual_set_type\n\nNote for developers\n\nWhen creating a new set, the set struct must not contain any VariableIndex or ConstraintIndex objects.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.AbstractScalarSet","page":"Standard form","title":"MathOptInterface.AbstractScalarSet","text":"AbstractScalarSet\n\nAbstract supertype for subsets of mathbbR.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.AbstractVectorSet","page":"Standard form","title":"MathOptInterface.AbstractVectorSet","text":"AbstractVectorSet\n\nAbstract supertype for subsets of mathbbR^n for some n.\n\nRequired methods\n\nAll AbstractVectorSets of type S must implement:\n\ndimension, unless the dimension is stored in the set.dimension field\nUtilities.set_dot, unless the dot product between two vectors in the set is equivalent to LinearAlgebra.dot.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Utilities","page":"Standard form","title":"Utilities","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"dimension\ndual_set\ndual_set_type\nconstant(s::EqualTo)\nsupports_dimension_update\nupdate_dimension","category":"page"},{"location":"reference/standard_form/#MathOptInterface.dimension","page":"Standard form","title":"MathOptInterface.dimension","text":"dimension(set::AbstractSet)\n\nReturn the output_dimension that an AbstractFunction should have to be used with the set set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.dimension(MOI.Reals(4))\n4\n\njulia> MOI.dimension(MOI.LessThan(3.0))\n1\n\njulia> MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2))\n3\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.dual_set","page":"Standard form","title":"MathOptInterface.dual_set","text":"dual_set(set::AbstractSet)\n\nReturn the dual set of set, that is the dual cone of the set. This follows the definition of duality discussed in Duality.\n\nSee Dual cone for more information.\n\nIf the dual cone is not defined it returns an error.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.dual_set(MOI.Reals(4))\nMathOptInterface.Zeros(4)\n\njulia> MOI.dual_set(MOI.SecondOrderCone(5))\nMathOptInterface.SecondOrderCone(5)\n\njulia> MOI.dual_set(MOI.ExponentialCone())\nMathOptInterface.DualExponentialCone()\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.dual_set_type","page":"Standard form","title":"MathOptInterface.dual_set_type","text":"dual_set_type(S::Type{<:AbstractSet})\n\nReturn the type of dual set of sets of type S, as returned by dual_set. If the dual cone is not defined it returns an error.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.dual_set_type(MOI.Reals)\nMathOptInterface.Zeros\n\njulia> MOI.dual_set_type(MOI.SecondOrderCone)\nMathOptInterface.SecondOrderCone\n\njulia> MOI.dual_set_type(MOI.ExponentialCone)\nMathOptInterface.DualExponentialCone\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.constant-Tuple{MathOptInterface.EqualTo}","page":"Standard form","title":"MathOptInterface.constant","text":"constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})\n\nReturns the constant term of the set set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> MOI.constant(MOI.GreaterThan(1.0))\n1.0\n\njulia> MOI.constant(MOI.LessThan(2.5))\n2.5\n\njulia> MOI.constant(MOI.EqualTo(3))\n3\n\njulia> MOI.constant(MOI.Parameter(4.5))\n4.5\n\n\n\n\n\n","category":"method"},{"location":"reference/standard_form/#MathOptInterface.supports_dimension_update","page":"Standard form","title":"MathOptInterface.supports_dimension_update","text":"supports_dimension_update(S::Type{<:MOI.AbstractVectorSet})\n\nReturn a Bool indicating whether the elimination of any dimension of n-dimensional sets of type S give an n-1-dimensional set S. By default, this function returns false so it should only be implemented for sets that supports dimension update.\n\nFor instance, supports_dimension_update(MOI.Nonnegatives) is true because the elimination of any dimension of the n-dimensional nonnegative orthant gives the n-1-dimensional nonnegative orthant. However supports_dimension_update(MOI.ExponentialCone) is false.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.update_dimension","page":"Standard form","title":"MathOptInterface.update_dimension","text":"update_dimension(s::AbstractVectorSet, new_dim::Int)\n\nReturns a set with the dimension modified to new_dim.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#Scalar-sets","page":"Standard form","title":"Scalar sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"List of recognized scalar sets.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"GreaterThan\nLessThan\nEqualTo\nInterval\nInteger\nZeroOne\nSemicontinuous\nSemiinteger\nParameter","category":"page"},{"location":"reference/standard_form/#MathOptInterface.GreaterThan","page":"Standard form","title":"MathOptInterface.GreaterThan","text":"GreaterThan{T<:Real}(lower::T)\n\nThe set lower infty) subseteq mathbbR.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.GreaterThan(0.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.LessThan","page":"Standard form","title":"MathOptInterface.LessThan","text":"LessThan{T<:Real}(upper::T)\n\nThe set (-infty upper subseteq mathbbR.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.LessThan(2.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.EqualTo","page":"Standard form","title":"MathOptInterface.EqualTo","text":"EqualTo{T<:Number}(value::T)\n\nThe set containing the single point value subseteq mathbbR.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.EqualTo(2.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Interval","page":"Standard form","title":"MathOptInterface.Interval","text":"Interval{T<:Real}(lower::T, upper::T)\n\nThe interval lower upper subseteq mathbbR cup -infty +infty.\n\nIf lower or upper is -Inf or Inf, respectively, the set is interpreted as a one-sided interval.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Interval(1.0, 2.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Integer","page":"Standard form","title":"MathOptInterface.Integer","text":"Integer()\n\nThe set of integers, mathbbZ.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Integer())\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ZeroOne","page":"Standard form","title":"MathOptInterface.ZeroOne","text":"ZeroOne()\n\nThe set 0 1.\n\nVariables belonging to the ZeroOne set are also known as \"binary\" variables.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.ZeroOne())\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Semicontinuous","page":"Standard form","title":"MathOptInterface.Semicontinuous","text":"Semicontinuous{T<:Real}(lower::T, upper::T)\n\nThe set 0 cup lower upper.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Semicontinuous(2.0, 3.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semicontinuous{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Semiinteger","page":"Standard form","title":"MathOptInterface.Semiinteger","text":"Semiinteger{T<:Real}(lower::T, upper::T)\n\nThe set 0 cup lower lower+1 ldots upper-1 upper.\n\nNote that if lower and upper are not equivalent to an integer, then the solver may throw an error, or it may round up lower and round down upper to the nearest integers.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> MOI.add_constraint(model, x, MOI.Semiinteger(2.0, 3.0))\nMathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semiinteger{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Parameter","page":"Standard form","title":"MathOptInterface.Parameter","text":"Parameter{T<:Number}(value::T)\n\nThe set containing the single point value subseteq mathbbR.\n\nThe Parameter set is conceptually similar to the EqualTo set, except that a variable constrained to the Parameter set cannot have other constraints added to it, and the Parameter set can never be deleted. Thus, solvers are free to treat the variable as a constant, and they need not add it as a decision variable to the model.\n\nBecause of this behavior, you must add parameters using add_constrained_variable, and solvers should declare supports_add_constrained_variable and not supports_constraint for the Parameter set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> p, ci = MOI.add_constrained_variable(model, MOI.Parameter(2.5))\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Parameter{Float64}}(1))\n\njulia> MOI.set(model, MOI.ConstraintSet(), ci, MOI.Parameter(3.0))\n\njulia> MOI.get(model, MOI.ConstraintSet(), ci)\nMathOptInterface.Parameter{Float64}(3.0)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Vector-sets","page":"Standard form","title":"Vector sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"List of recognized vector sets.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"Reals\nZeros\nNonnegatives\nNonpositives\nNormInfinityCone\nNormOneCone\nNormCone\nSecondOrderCone\nRotatedSecondOrderCone\nGeometricMeanCone\nExponentialCone\nDualExponentialCone\nPowerCone\nDualPowerCone\nRelativeEntropyCone\nNormSpectralCone\nNormNuclearCone\nSOS1\nSOS2\nIndicator\nComplements\nHyperRectangle\nScaled","category":"page"},{"location":"reference/standard_form/#MathOptInterface.Reals","page":"Standard form","title":"MathOptInterface.Reals","text":"Reals(dimension::Int)\n\nThe set mathbbR^dimension (containing all points) of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Reals(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Reals}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Zeros","page":"Standard form","title":"MathOptInterface.Zeros","text":"Zeros(dimension::Int)\n\nThe set 0 ^dimension (containing only the origin) of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Zeros(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Nonnegatives","page":"Standard form","title":"MathOptInterface.Nonnegatives","text":"Nonnegatives(dimension::Int)\n\nThe nonnegative orthant x in mathbbR^dimension x ge 0 of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Nonpositives","page":"Standard form","title":"MathOptInterface.Nonpositives","text":"Nonpositives(dimension::Int)\n\nThe nonpositive orthant x in mathbbR^dimension x le 0 of non-negative dimension dimension.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonpositives(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonpositives}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormInfinityCone","page":"Standard form","title":"MathOptInterface.NormInfinityCone","text":"NormInfinityCone(dimension::Int)\n\nThe ell_infty-norm cone (tx) in mathbbR^dimension t ge lVert x rVert_infty = max_i lvert x_i rvert of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormInfinityCone(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormInfinityCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormOneCone","page":"Standard form","title":"MathOptInterface.NormOneCone","text":"NormOneCone(dimension::Int)\n\nThe ell_1-norm cone (tx) in mathbbR^dimension t ge lVert x rVert_1 = sum_i lvert x_i rvert of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormOneCone(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormOneCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormCone","page":"Standard form","title":"MathOptInterface.NormCone","text":"NormCone(p::Float64, dimension::Int)\n\nThe ell_p-norm cone (tx) in mathbbR^dimension t ge left(sumlimits_i x_i^pright)^frac1p of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormCone(3, 4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.SecondOrderCone","page":"Standard form","title":"MathOptInterface.SecondOrderCone","text":"SecondOrderCone(dimension::Int)\n\nThe second-order cone (or Lorenz cone or ell_2-norm cone) (tx) in mathbbR^dimension t ge lVert x rVert_2 of dimension dimension.\n\nThe dimension must be at least 1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.SecondOrderCone(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SecondOrderCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RotatedSecondOrderCone","page":"Standard form","title":"MathOptInterface.RotatedSecondOrderCone","text":"RotatedSecondOrderCone(dimension::Int)\n\nThe rotated second-order cone (tux) in mathbbR^dimension 2tu ge lVert x rVert_2^2 tu ge 0 of dimension dimension.\n\nThe dimension must be at least 2.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> u = MOI.add_variable(model)\nMOI.VariableIndex(2)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; u; x]),\n MOI.RotatedSecondOrderCone(5),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RotatedSecondOrderCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.GeometricMeanCone","page":"Standard form","title":"MathOptInterface.GeometricMeanCone","text":"GeometricMeanCone(dimension::Int)\n\nThe geometric mean cone (tx) in mathbbR^n+1 x ge 0 t le sqrtnx_1 x_2 cdots x_n , where dimension = n + 1 >= 2.\n\nDuality note\n\nThe dual of the geometric mean cone is (u v) in mathbbR^n+1 u le 0 v ge 0 -u le n sqrtnprod_i v_i , where dimension = n + 1 >= 2.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; x]),\n MOI.GeometricMeanCone(4),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.GeometricMeanCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.ExponentialCone","page":"Standard form","title":"MathOptInterface.ExponentialCone","text":"ExponentialCone()\n\nThe 3-dimensional exponential cone (xyz) in mathbbR^3 y exp (xy) le z y 0 .\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.ExponentialCone())\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.ExponentialCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.DualExponentialCone","page":"Standard form","title":"MathOptInterface.DualExponentialCone","text":"DualExponentialCone()\n\nThe 3-dimensional dual exponential cone (uvw) in mathbbR^3 -u exp (vu) le exp(1) w u 0 .\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualExponentialCone())\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualExponentialCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.PowerCone","page":"Standard form","title":"MathOptInterface.PowerCone","text":"PowerCone{T<:Real}(exponent::T)\n\nThe 3-dimensional power cone (xyz) in mathbbR^3 x^exponent y^1-exponent ge z x ge 0 y ge 0 with parameter exponent.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.PowerCone(0.5))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.PowerCone{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.DualPowerCone","page":"Standard form","title":"MathOptInterface.DualPowerCone","text":"DualPowerCone{T<:Real}(exponent::T)\n\nThe 3-dimensional power cone (uvw) in mathbbR^3 (fracuexponent)^exponent (fracv1-exponent)^1-exponent ge w u ge 0 v ge 0 with parameter exponent.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualPowerCone(0.5))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualPowerCone{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RelativeEntropyCone","page":"Standard form","title":"MathOptInterface.RelativeEntropyCone","text":"RelativeEntropyCone(dimension::Int)\n\nThe relative entropy cone (u v w) in mathbbR^1+2n u ge sum_i=1^n w_i log(fracw_iv_i) v_i ge 0 w_i ge 0 , where dimension = 2n + 1 >= 1.\n\nDuality note\n\nThe dual of the relative entropy cone is (u v w) in mathbbR^1+2n forall i w_i ge u (log (fracuv_i) - 1) v_i ge 0 u 0 of dimension dimension=2n+1.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> u = MOI.add_variable(model);\n\njulia> v = MOI.add_variables(model, 3);\n\njulia> w = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([u; v; w]),\n MOI.RelativeEntropyCone(7),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RelativeEntropyCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormSpectralCone","page":"Standard form","title":"MathOptInterface.NormSpectralCone","text":"NormSpectralCone(row_dim::Int, column_dim::Int)\n\nThe epigraph of the matrix spectral norm (maximum singular value function) (t X) in mathbbR^1 + row_dim times column_dim t ge sigma_1(X) , where sigma_i is the ith singular value of the matrix X of non-negative row dimension row_dim and column dimension column_dim.\n\nThe matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 6), 2, 3)\n2×3 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4) MOI.VariableIndex(6)\n MOI.VariableIndex(3) MOI.VariableIndex(5) MOI.VariableIndex(7)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.NormSpectralCone(2, 3),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormSpectralCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.NormNuclearCone","page":"Standard form","title":"MathOptInterface.NormNuclearCone","text":"NormNuclearCone(row_dim::Int, column_dim::Int)\n\nThe epigraph of the matrix nuclear norm (sum of singular values function) (t X) in mathbbR^1 + row_dim times column_dim t ge sum_i sigma_i(X) , where sigma_i is the ith singular value of the matrix X of non-negative row dimension row_dim and column dimension column_dim.\n\nThe matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 6), 2, 3)\n2×3 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4) MOI.VariableIndex(6)\n MOI.VariableIndex(3) MOI.VariableIndex(5) MOI.VariableIndex(7)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.NormNuclearCone(2, 3),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormNuclearCone}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.SOS1","page":"Standard form","title":"MathOptInterface.SOS1","text":"SOS1{T<:Real}(weights::Vector{T})\n\nThe set corresponding to the Special Ordered Set (SOS) constraint of Type I.\n\nOf the variables in the set, at most one can be nonzero.\n\nThe weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Solvers may use these weights to improve the efficiency of the solution process, but the ordering does not change the set of feasible solutions.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.SOS1([1.0, 3.0, 2.5]),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS1{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.SOS2","page":"Standard form","title":"MathOptInterface.SOS2","text":"SOS2{T<:Real}(weights::Vector{T})\n\nThe set corresponding to the Special Ordered Set (SOS) constraint of Type II.\n\nThe weights induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights. Therefore, the weights must be unique.\n\nOf the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.SOS2([1.0, 3.0, 2.5]),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS2{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Indicator","page":"Standard form","title":"MathOptInterface.Indicator","text":"Indicator{A<:ActivationCondition,S<:AbstractScalarSet}(set::S)\n\nThe set corresponding to an indicator constraint.\n\nWhen A is ACTIVATE_ON_ZERO, this means: (y x) in 0 1 times mathbbR^n y = 0 implies x in set\n\nWhen A is ACTIVATE_ON_ONE, this means: (y x) in 0 1 times mathbbR^n y = 1 implies x in set\n\nNotes\n\nMost solvers expect that the first row of the function is interpretable as a variable index x_i (for example, 1.0 * x + 0.0). An error will be thrown if this is not the case.\n\nExample\n\nThe constraint (y x) in 0 1 times mathbbR^2 y = 1 implies x_1 + x_2 leq 9 is defined as\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 2)\n2-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n\njulia> y, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())\n(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3))\n\njulia> f = MOI.VectorAffineFunction(\n [\n MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, y)),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[1])),\n MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[2])),\n ],\n [0.0, 0.0],\n )\n┌ ┐\n│0.0 + 1.0 MOI.VariableIndex(3) │\n│0.0 + 1.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(2)│\n└ ┘\n\njulia> s = MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))\nMathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}(MathOptInterface.LessThan{Float64}(9.0))\n\njulia> MOI.add_constraint(model, f, s)\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Complements","page":"Standard form","title":"MathOptInterface.Complements","text":"Complements(dimension::Base.Integer)\n\nThe set corresponding to a mixed complementarity constraint.\n\nComplementarity constraints should be specified with an AbstractVectorFunction-in-Complements(dimension) constraint.\n\nThe dimension of the vector-valued function F must be dimension. This defines a complementarity constraint between the scalar function F[i] and the variable in F[i + dimension/2]. Thus, F[i + dimension/2] must be interpretable as a single variable x_i (for example, 1.0 * x + 0.0), and dimension must be even.\n\nThe mixed complementarity problem consists of finding x_i in the interval [lb, ub] (that is, in the set Interval(lb, ub)), such that the following holds:\n\nF_i(x) == 0 if lb_i < x_i < ub_i\nF_i(x) >= 0 if lb_i == x_i\nF_i(x) <= 0 if x_i == ub_i\n\nClassically, the bounding set for x_i is Interval(0, Inf), which recovers: 0 <= F_i(x) ⟂ x_i >= 0, where the ⟂ operator implies F_i(x) * x_i = 0.\n\nExample\n\nThe problem:\n\nx -in- Interval(-1, 1)\n[-4 * x - 3, x] -in- Complements(2)\n\ndefines the mixed complementarity problem where the following holds:\n\n-4 * x - 3 == 0 if -1 < x < 1\n-4 * x - 3 >= 0 if x == -1\n-4 * x - 3 <= 0 if x == 1\n\nThere are three solutions:\n\nx = -3/4 with F(x) = 0\nx = -1 with F(x) = 1\nx = 1 with F(x) = -7\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x, _ = MOI.add_constrained_variable(model, MOI.Interval(-1.0, 1.0));\n\njulia> MOI.add_constraint(\n model,\n MOI.Utilities.vectorize([-4.0 * x - 3.0, x]),\n MOI.Complements(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Complements}(1)\n\nThe function F can also be defined in terms of single variables. For example, the problem:\n\n[x_3, x_4] -in- Nonnegatives(2)\n[x_1, x_2, x_3, x_4] -in- Complements(4)\n\ndefines the complementarity problem where 0 <= x_1 ⟂ x_3 >= 0 and 0 <= x_2 ⟂ x_4 >= 0.\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 4);\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x[3:4]), MOI.Nonnegatives(2))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.Complements(4),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Complements}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.HyperRectangle","page":"Standard form","title":"MathOptInterface.HyperRectangle","text":"HyperRectangle(lower::Vector{T}, upper::Vector{T}) where {T}\n\nThe set x in barmathbbR^d x_i in lower_i upper_i forall i=1ldotsd.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3)\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables(x),\n MOI.HyperRectangle(zeros(3), ones(3)),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.HyperRectangle{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Scaled","page":"Standard form","title":"MathOptInterface.Scaled","text":"struct Scaled{S<:AbstractVectorSet} <: AbstractVectorSet\n set::S\nend\n\nGiven a vector a in mathbbR^d and a set representing the set mathcalS in mathbbR^d such that Utilities.set_dot for x in mathcalS and y in mathcalS^* is\n\nsum_i=1^d a_i x_i y_i\n\nthe set Scaled(set) is defined as\n\n (sqrta_1 x_1 sqrta_2 x_2 ldots sqrta_d x_d) x in S \n\nExample\n\nThis can be used to scale a vector of numbers\n\njulia> import MathOptInterface as MOI\n\njulia> set = MOI.PositiveSemidefiniteConeTriangle(2)\nMathOptInterface.PositiveSemidefiniteConeTriangle(2)\n\njulia> a = MOI.Utilities.SetDotScalingVector{Float64}(set)\n3-element MathOptInterface.Utilities.SetDotScalingVector{Float64, MathOptInterface.PositiveSemidefiniteConeTriangle}:\n 1.0\n 1.4142135623730951\n 1.0\n\njulia> using LinearAlgebra\n\njulia> MOI.Utilities.operate(*, Float64, Diagonal(a), ones(3))\n3-element Vector{Float64}:\n 1.0\n 1.4142135623730951\n 1.0\n\nIt can be also used to scale a vector of function\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3);\n\njulia> func = MOI.VectorOfVariables(x)\n┌ ┐\n│MOI.VariableIndex(1)│\n│MOI.VariableIndex(2)│\n│MOI.VariableIndex(3)│\n└ ┘\n\njulia> set = MOI.PositiveSemidefiniteConeTriangle(2)\nMathOptInterface.PositiveSemidefiniteConeTriangle(2)\n\njulia> MOI.Utilities.operate(*, Float64, Diagonal(a), func)\n┌ ┐\n│0.0 + 1.0 MOI.VariableIndex(1) │\n│0.0 + 1.4142135623730951 MOI.VariableIndex(2)│\n│0.0 + 1.0 MOI.VariableIndex(3) │\n└ ┘\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Constraint-programming-sets","page":"Standard form","title":"Constraint programming sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AllDifferent\nBinPacking\nCircuit\nCountAtLeast\nCountBelongs\nCountDistinct\nCountGreaterThan\nCumulative\nPath\nReified\nTable","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AllDifferent","page":"Standard form","title":"MathOptInterface.AllDifferent","text":"AllDifferent(dimension::Int)\n\nThe set x in mathbbZ^d such that no two elements in x take the same value and dimension = d.\n\nAlso known as\n\nThis constraint is called all_different in MiniZinc, and is sometimes also called distinct.\n\nExample\n\nTo enforce x[1] != x[2] AND x[1] != x[3] AND x[2] != x[3]:\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.AllDifferent(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.AllDifferent}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.BinPacking","page":"Standard form","title":"MathOptInterface.BinPacking","text":"BinPacking(c::T, w::Vector{T}) where {T}\n\nThe set x in mathbbZ^d where d = length(w), such that each item i in 1:d of weight w[i] is put into bin x[i], and the total weight of each bin does not exceed c.\n\nThere are additional assumptions that the capacity, c, and the weights, w, must all be non-negative.\n\nThe bin numbers depend on the bounds of x, so they may be something other than the integers 1:d.\n\nAlso known as\n\nThis constraint is called bin_packing in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> bins = MOI.add_variables(model, 5)\n5-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n\njulia> weights = Float64[1, 1, 2, 2, 3]\n5-element Vector{Float64}:\n 1.0\n 1.0\n 2.0\n 2.0\n 3.0\n\njulia> MOI.add_constraint.(model, bins, MOI.Integer())\n5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(4)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(5)\n\njulia> MOI.add_constraint.(model, bins, MOI.Interval(4.0, 6.0))\n5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(2)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(3)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(4)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(5)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(bins), MOI.BinPacking(3.0, weights))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.BinPacking{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Circuit","page":"Standard form","title":"MathOptInterface.Circuit","text":"Circuit(dimension::Int)\n\nThe set x in 1d^d that constraints x to be a circuit, such that x_i = j means that j is the successor of i, and dimension = d.\n\nGraphs with multiple independent circuits, such as [2, 1, 3] and [2, 1, 4, 3], are not valid.\n\nAlso known as\n\nThis constraint is called circuit in MiniZinc, and it is equivalent to forming a (potentially sub-optimal) tour in the travelling salesperson problem.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Circuit(3))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Circuit}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountAtLeast","page":"Standard form","title":"MathOptInterface.CountAtLeast","text":"CountAtLeast(n::Int, d::Vector{Int}, set::Set{Int})\n\nThe set x in mathbbZ^d_1 + d_2 + ldots d_N, where x is partitioned into N subsets (x_1 ldots x_d_1, x_d_1 + 1 ldots x_d_1 + d_2 and so on), and at least n elements of each subset take one of the values in set.\n\nAlso known as\n\nThis constraint is called at_least in MiniZinc.\n\nExample\n\nTo ensure that 3 appears at least once in each of the subsets {a, b} and {b, c}:\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> a, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))\n\njulia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3))\n\njulia> x, d, set = [a, b, b, c], [2, 2], [3]\n(MathOptInterface.VariableIndex[MOI.VariableIndex(1), MOI.VariableIndex(2), MOI.VariableIndex(2), MOI.VariableIndex(3)], [2, 2], [3])\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.CountAtLeast(1, d, Set(set)))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountAtLeast}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountBelongs","page":"Standard form","title":"MathOptInterface.CountBelongs","text":"CountBelongs(dimenson::Int, set::Set{Int})\n\nThe set (n x) in mathbbZ^1+d, such that n elements of the vector x take on of the values in set and dimension = 1 + d.\n\nAlso known as\n\nThis constraint is called among by MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n\njulia> set = Set([3, 4, 5])\nSet{Int64} with 3 elements:\n 5\n 4\n 3\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([n; x]), MOI.CountBelongs(4, set))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountBelongs}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountDistinct","page":"Standard form","title":"MathOptInterface.CountDistinct","text":"CountDistinct(dimension::Int)\n\nThe set (n x) in mathbbZ^1+d, such that the number of distinct values in x is n and dimension = 1 + d.\n\nAlso known as\n\nThis constraint is called nvalues in MiniZinc.\n\nExample\n\nTo model:\n\nif n == 1`, thenx[1] == x[2] == x[3]`\nif n == 2, then\nx[1] == x[2] != x[3] or\nx[1] != x[2] == x[3] or\nx[1] == x[3] != x[2]\nif n == 3, then x[1] != x[2], x[2] != x[3] and x[3] != x[1]\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(vcat(n, x)), MOI.CountDistinct(4))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountDistinct}(1)\n\nRelationship to AllDifferent\n\nWhen the first element is d, CountDistinct is equivalent to an AllDifferent constraint.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.CountGreaterThan","page":"Standard form","title":"MathOptInterface.CountGreaterThan","text":"CountGreaterThan(dimension::Int)\n\nThe set (c y x) in mathbbZ^1+1+d, such that c is strictly greater than the number of occurences of y in x and dimension = 1 + 1 + d.\n\nAlso known as\n\nThis constraint is called count_gt in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> y, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))\n\njulia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([c; y; x]), MOI.CountGreaterThan(5))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountGreaterThan}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Cumulative","page":"Standard form","title":"MathOptInterface.Cumulative","text":"Cumulative(dimension::Int)\n\nThe set (s d r b) in mathbbZ^3n+1, representing the cumulative global constraint, where n == length(s) == length(r) == length(b) and dimension = 3n + 1.\n\nCumulative requires that a set of tasks given by start times s, durations d, and resource requirements r, never requires more than the global resource bound b at any one time.\n\nAlso known as\n\nThis constraint is called cumulative in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> d = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n MOI.VariableIndex(6)\n\njulia> r = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(7)\n MOI.VariableIndex(8)\n MOI.VariableIndex(9)\n\njulia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(10), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(10))\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([s; d; r; b]), MOI.Cumulative(10))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Cumulative}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Path","page":"Standard form","title":"MathOptInterface.Path","text":"Path(from::Vector{Int}, to::Vector{Int})\n\nGiven a graph comprised of a set of nodes 1..N and a set of arcs 1..E represented by an edge from node from[i] to node to[i], Path constrains the set (s t ns es) in (1N)times(1E)times01^Ntimes01^E, to form subgraph that is a path from node s to node t, where node n is in the path if ns[n] is 1, and edge e is in the path if es[e] is 1.\n\nThe path must be acyclic, and it must traverse all nodes n for which ns[n] is 1, and all edges e for which es[e] is 1.\n\nAlso known as\n\nThis constraint is called path in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> N, E = 4, 5\n(4, 5)\n\njulia> from = [1, 1, 2, 2, 3]\n5-element Vector{Int64}:\n 1\n 1\n 2\n 2\n 3\n\njulia> to = [2, 3, 3, 4, 4]\n5-element Vector{Int64}:\n 2\n 3\n 3\n 4\n 4\n\njulia> s, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))\n\njulia> t, _ = MOI.add_constrained_variable(model, MOI.Integer())\n(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))\n\njulia> ns = MOI.add_variables(model, N)\n4-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(3)\n MOI.VariableIndex(4)\n MOI.VariableIndex(5)\n MOI.VariableIndex(6)\n\njulia> MOI.add_constraint.(model, ns, MOI.ZeroOne())\n4-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(4)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(5)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(6)\n\njulia> es = MOI.add_variables(model, E)\n5-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(7)\n MOI.VariableIndex(8)\n MOI.VariableIndex(9)\n MOI.VariableIndex(10)\n MOI.VariableIndex(11)\n\njulia> MOI.add_constraint.(model, es, MOI.ZeroOne())\n5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(7)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(8)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(9)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(10)\n MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(11)\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables([s; t; ns; es]), MOI.Path(from, to))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Path}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Reified","page":"Standard form","title":"MathOptInterface.Reified","text":"Reified(set::AbstractSet)\n\nThe constraint z f(x) in Reified(S) ensures that f(x) in S if and only if z == 1, where z in 0 1.\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())\nMOIU.UniversalFallback{MOIU.Model{Float64}}\nfallback for MOIU.Model{Float64}\n\njulia> z, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())\n(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1))\n\njulia> x = MOI.add_variable(model)\nMOI.VariableIndex(2)\n\njulia> MOI.add_constraint(\n model,\n MOI.Utilities.vectorize([z, 2.0 * x]),\n MOI.Reified(MOI.GreaterThan(1.0)),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Reified{MathOptInterface.GreaterThan{Float64}}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.Table","page":"Standard form","title":"MathOptInterface.Table","text":"Table(table::Matrix{T}) where {T}\n\nThe set x in mathbbR^d where d = size(table, 2), such that x belongs to one row of table. That is, there exists some j in 1:size(table, 1), such that x[i] = table[j, i] for all i=1:size(table, 2).\n\nAlso known as\n\nThis constraint is called table in MiniZinc.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> x = MOI.add_variables(model, 3)\n3-element Vector{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(1)\n MOI.VariableIndex(2)\n MOI.VariableIndex(3)\n\njulia> table = Float64[1 1 0; 0 1 1; 1 0 1; 1 1 1]\n4×3 Matrix{Float64}:\n 1.0 1.0 0.0\n 0.0 1.0 1.0\n 1.0 0.0 1.0\n 1.0 1.0 1.0\n\njulia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Table(table))\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Table{Float64}}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#Matrix-sets","page":"Standard form","title":"Matrix sets","text":"","category":"section"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"Matrix sets are vectorized to be subtypes of AbstractVectorSet.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"For sets of symmetric matrices, storing both the (i, j) and (j, i) elements is redundant. Use the AbstractSymmetricMatrixSetTriangle set to represent only the vectorization of the upper triangular part of the matrix.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"When the matrix of expressions constrained to be in the set is not symmetric, and hence additional constraints are needed to force the equality of the (i, j) and (j, i) elements, use the AbstractSymmetricMatrixSetSquare set.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"The Bridges.Constraint.SquareBridge can transform a set from the square form to the triangular_form by adding appropriate constraints if the (i, j) and (j, i) expressions are different.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"AbstractSymmetricMatrixSetTriangle\nAbstractSymmetricMatrixSetSquare\nside_dimension\ntriangular_form","category":"page"},{"location":"reference/standard_form/#MathOptInterface.AbstractSymmetricMatrixSetTriangle","page":"Standard form","title":"MathOptInterface.AbstractSymmetricMatrixSetTriangle","text":"abstract type AbstractSymmetricMatrixSetTriangle <: AbstractVectorSet end\n\nAbstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row). A vectorized cone of dimension n corresponds to a square matrix with side dimension sqrt14 + 2 n - 12. (Because a d times d matrix has d(d + 1) 2 elements in the upper or lower triangle.)\n\nExample\n\nThe matrix\n\nbeginbmatrix\n 1 2 4\n 2 3 5\n 4 5 6\nendbmatrix\n\nhas side_dimension 3 and vectorization (1 2 3 4 5 6).\n\nNote\n\nTwo packed storage formats exist for symmetric matrices, the respective orders of the entries are:\n\nupper triangular column by column (or lower triangular row by row);\nlower triangular column by column (or upper triangular row by row).\n\nThe advantage of the first format is the mapping between the (i, j) matrix indices and the k index of the vectorized form. It is simpler and does not depend on the side dimension of the matrix. Indeed,\n\nthe entry of matrix indices (i, j) has vectorized index k = div((j - 1) * j, 2) + i if i leq j and k = div((i - 1) * i, 2) + j if j leq i;\nand the entry with vectorized index k has matrix indices i = div(1 + isqrt(8k - 7), 2) and j = k - div((i - 1) * i, 2) or j = div(1 + isqrt(8k - 7), 2) and i = k - div((j - 1) * j, 2).\n\nDuality note\n\nThe scalar product for the symmetric matrix in its vectorized form is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries; see [p. 634, 1]. This has important consequence for duality.\n\nConsider for example the following problem (PositiveSemidefiniteConeTriangle is a subtype of AbstractSymmetricMatrixSetTriangle)\n\nbeginalign*\n max_x in mathbbR x\n \n textst \n (1 -x 1) in textPositiveSemidefiniteConeTriangle(2)\nendalign*\n\nThe dual is the following problem\n\nbeginalign*\n min_x in mathbbR^3 y_1 + y_3\n \n textst 2y_2 = 1\n y in textPositiveSemidefiniteConeTriangle(2)\nendalign*\n\nWhy do we use 2y_2 in the dual constraint instead of y_2 ? The reason is that 2y_2 is the scalar product between y and the symmetric matrix whose vectorized form is (0 1 0). Indeed, with our modified scalar products we have\n\nlangle\n(0 1 0)\n(y_1 y_2 y_3)\nrangle\n=\nmathrmtrace\nbeginpmatrix\n 0 1\n 1 0\nendpmatrix\nbeginpmatrix\n y_1 y_2\n y_2 y_3\nendpmatrix\n= 2y_2\n\nReferences\n\n[1] Boyd, S. and Vandenberghe, L.. Convex optimization. Cambridge university press, 2004.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.AbstractSymmetricMatrixSetSquare","page":"Standard form","title":"MathOptInterface.AbstractSymmetricMatrixSetSquare","text":"abstract type AbstractSymmetricMatrixSetSquare <: AbstractVectorSet end\n\nAbstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to have its triangular_form belong to the corresponding set. That is, if the functions in entries (i j) and (j i) are different, then a constraint will be added to make sure that the entries are equal.\n\nExample\n\nPositiveSemidefiniteConeSquare is a subtype of AbstractSymmetricMatrixSetSquare and constraining the matrix\n\nbeginbmatrix\n 1 -y\n -z 0\nendbmatrix\n\nto be symmetric positive semidefinite can be achieved by constraining the vector (1 -z -y 0) (or (1 -y -z 0)) to belong to the PositiveSemidefiniteConeSquare(2). It both constrains y = z and (1 -y 0) (or (1 -z 0)) to be in PositiveSemidefiniteConeTriangle(2), since triangular_form(PositiveSemidefiniteConeSquare) is PositiveSemidefiniteConeTriangle.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.side_dimension","page":"Standard form","title":"MathOptInterface.side_dimension","text":"side_dimension(\n set::Union{\n AbstractSymmetricMatrixSetTriangle,\n AbstractSymmetricMatrixSetSquare,\n HermitianPositiveSemidefiniteConeTriangle,\n },\n)\n\nSide dimension of the matrices in set.\n\nConvention\n\nBy convention, the side dimension should be stored in the side_dimension field. If this is not the case for a subtype of AbstractSymmetricMatrixSetTriangle, or AbstractSymmetricMatrixSetSquare you must implement this method.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/#MathOptInterface.triangular_form","page":"Standard form","title":"MathOptInterface.triangular_form","text":"triangular_form(S::Type{<:AbstractSymmetricMatrixSetSquare})\ntriangular_form(set::AbstractSymmetricMatrixSetSquare)\n\nReturn the AbstractSymmetricMatrixSetTriangle corresponding to the vectorization of the upper triangular part of matrices in the AbstractSymmetricMatrixSetSquare set.\n\n\n\n\n\n","category":"function"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"List of recognized matrix sets.","category":"page"},{"location":"reference/standard_form/","page":"Standard form","title":"Standard form","text":"PositiveSemidefiniteConeTriangle\nPositiveSemidefiniteConeSquare\nHermitianPositiveSemidefiniteConeTriangle\nLogDetConeTriangle\nLogDetConeSquare\nRootDetConeTriangle\nRootDetConeSquare","category":"page"},{"location":"reference/standard_form/#MathOptInterface.PositiveSemidefiniteConeTriangle","page":"Standard form","title":"MathOptInterface.PositiveSemidefiniteConeTriangle","text":"PositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractSymmetricMatrixSetTriangle\n\nThe (vectorized) cone of symmetric positive semidefinite matrices, with non-negative side_dimension rows and columns.\n\nSee AbstractSymmetricMatrixSetTriangle for more details on the vectorized form.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.PositiveSemidefiniteConeSquare","page":"Standard form","title":"MathOptInterface.PositiveSemidefiniteConeSquare","text":"PositiveSemidefiniteConeSquare(side_dimension::Int) <: AbstractSymmetricMatrixSetSquare\n\nThe cone of symmetric positive semidefinite matrices, with non-negative side length side_dimension.\n\nSee AbstractSymmetricMatrixSetSquare for more details on the vectorized form.\n\nThe entries of the matrix are given column by column (or equivalently, row by row).\n\nThe matrix is both constrained to be symmetric and to be positive semidefinite. That is, if the functions in entries (i j) and (j i) are different, then a constraint will be added to make sure that the entries are equal.\n\nExample\n\nConstraining the matrix\n\nbeginbmatrix\n 1 -y\n -z 0\nendbmatrix\n\nto be symmetric positive semidefinite can be achieved by constraining the vector (1 -z -y 0) (or (1 -y -z 0)) to belong to the PositiveSemidefiniteConeSquare(2).\n\nIt both constrains y = z and (1 -y 0) (or (1 -z 0)) to be in PositiveSemidefiniteConeTriangle(2).\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.HermitianPositiveSemidefiniteConeTriangle","page":"Standard form","title":"MathOptInterface.HermitianPositiveSemidefiniteConeTriangle","text":"HermitianPositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractVectorSet\n\nThe (vectorized) cone of Hermitian positive semidefinite matrices, with non-negative side_dimension rows and columns.\n\nBecaue the matrix is Hermitian, the diagonal elements are real, and the complex-valued lower triangular entries are obtained as the conjugate of corresponding upper triangular entries.\n\nVectorization format\n\nThe vectorized form starts with real part of the entries of the upper triangular part of the matrix, given column by column as explained in AbstractSymmetricMatrixSetSquare.\n\nIt is then followed by the imaginary part of the off-diagonal entries of the upper triangular part, also given column by column.\n\nFor example, the matrix\n\nbeginbmatrix\n 1 2 + 7im 4 + 8im\n 2 - 7im 3 5 + 9im\n 4 - 8im 5 - 9im 6\nendbmatrix\n\nhas side_dimension 3 and is represented as the vector 1 2 3 4 5 6 7 8 9.\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.LogDetConeTriangle","page":"Standard form","title":"MathOptInterface.LogDetConeTriangle","text":"LogDetConeTriangle(side_dimension::Int)\n\nThe log-determinant cone (t u X) in mathbbR^2 + d(d+1)2 t le u log(det(Xu)) u 0 , where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; X]),\n MOI.LogDetConeTriangle(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeTriangle}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.LogDetConeSquare","page":"Standard form","title":"MathOptInterface.LogDetConeSquare","text":"LogDetConeSquare(side_dimension::Int)\n\nThe log-determinant cone (t u X) in mathbbR^2 + d^2 t le u log(det(Xu)) X text symmetric u 0 , where the matrix X is represented in the same format as in the PositiveSemidefiniteConeSquare.\n\nSimilarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 4), 2, 2)\n2×2 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4)\n MOI.VariableIndex(3) MOI.VariableIndex(5)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.LogDetConeSquare(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeSquare}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RootDetConeTriangle","page":"Standard form","title":"MathOptInterface.RootDetConeTriangle","text":"RootDetConeTriangle(side_dimension::Int)\n\nThe root-determinant cone (t X) in mathbbR^1 + d(d+1)2 t le det(X)^1d , where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = MOI.add_variables(model, 3);\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; X]),\n MOI.RootDetConeTriangle(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeTriangle}(1)\n\n\n\n\n\n","category":"type"},{"location":"reference/standard_form/#MathOptInterface.RootDetConeSquare","page":"Standard form","title":"MathOptInterface.RootDetConeSquare","text":"RootDetConeSquare(side_dimension::Int)\n\nThe root-determinant cone (t X) in mathbbR^1 + d^2 t le det(X)^1d X text symmetric , where the matrix X is represented in the same format as PositiveSemidefiniteConeSquare.\n\nSimilarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric.\n\nThe non-negative argument side_dimension is the side dimension of the matrix X, that is, its number of rows or columns.\n\nExample\n\njulia> import MathOptInterface as MOI\n\njulia> model = MOI.Utilities.Model{Float64}()\nMOIU.Model{Float64}\n\njulia> t = MOI.add_variable(model)\nMOI.VariableIndex(1)\n\njulia> X = reshape(MOI.add_variables(model, 4), 2, 2)\n2×2 Matrix{MathOptInterface.VariableIndex}:\n MOI.VariableIndex(2) MOI.VariableIndex(4)\n MOI.VariableIndex(3) MOI.VariableIndex(5)\n\njulia> MOI.add_constraint(\n model,\n MOI.VectorOfVariables([t; vec(X)]),\n MOI.RootDetConeSquare(2),\n )\nMathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeSquare}(1)\n\n\n\n\n\n","category":"type"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/bridging_constraint/#Implementing-a-constraint-bridge","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"This guide outlines the basic steps to create a new bridge from a constraint expressed in the formalism Function-in-Set.","category":"page"},{"location":"tutorials/bridging_constraint/#Preliminaries","page":"Implementing a constraint bridge","title":"Preliminaries","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"First, decide on the set you want to bridge. Then, study its properties: the most important one is whether the set is scalar or vector, which impacts the dimensionality of the functions that can be used with the set.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"A scalar function only has one dimension. MOI defines three types of scalar functions: a variable (VariableIndex), an affine function (ScalarAffineFunction), or a quadratic function (ScalarQuadraticFunction).\nA vector function has several dimensions (at least one). MOI defines three types of vector functions: several variables (VectorOfVariables), an affine function (VectorAffineFunction), or a quadratic function (VectorQuadraticFunction). The main difference with scalar functions is that the order of dimensions can be very important: for instance, in an indicator constraint (Indicator), the first dimension indicates whether the constraint about the second dimension is active.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"To explain how to implement a bridge, we present the example of Bridges.Constraint.FlipSignBridge. This bridge maps <= (LessThan) constraints to >= (GreaterThan) constraints. This corresponds to reversing the sign of the inequality. We focus on scalar affine functions (we disregard the cases of a single variable or of quadratic functions). This example is a simplified version of the code included in MOI.","category":"page"},{"location":"tutorials/bridging_constraint/#Four-mandatory-parts-in-a-constraint-bridge","page":"Implementing a constraint bridge","title":"Four mandatory parts in a constraint bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The first part of a constraint bridge is a new concrete subtype of Bridges.Constraint.AbstractBridge. This type must have fields to store all the new variables and constraints that the bridge will add. Typically, these types are parametrized by the type of the coefficients in the model.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Then, three sets of functions must be defined:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Bridges.Constraint.bridge_constraint: this function implements the bridge and creates the required variables and constraints.\nsupports_constraint: these functions must return true when the combination of function and set is supported by the bridge. By default, the base implementation always returns false and the bridge does not have to provide this implementation.\nBridges.added_constrained_variable_types and Bridges.added_constraint_types: these functions return the types of variables and constraints that this bridge adds. They are used to compute the set of other bridges that are required to use the one you are defining, if need be.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"More functions can be implemented, for instance to retrieve properties from the bridge or deleting a bridged constraint.","category":"page"},{"location":"tutorials/bridging_constraint/#1.-Structure-for-the-bridge","page":"Implementing a constraint bridge","title":"1. Structure for the bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"A typical struct behind a bridge depends on the type of the coefficients that are used for the model (typically Float64, but coefficients might also be integers or complex numbers).","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"This structure must hold a reference to all the variables and the constraints that are created as part of the bridge.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The type of this structure is used throughout MOI as an identifier for the bridge. It is passed as argument to most functions related to bridges.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The best practice is to have the name of this type end with Bridge.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our example, the bridge maps any ScalarAffineFunction{T}-in-LessThan{T} constraint to a single ScalarAffineFunction{T}-in-GreaterThan{T} constraint. The affine function has coefficients of type T. The bridge is parametrized with T, so that the constraint that the bridge creates also has coefficients of type T.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"struct SignBridge{T<:Number} <: Bridges.Constraint.AbstractBridge\n constraint::ConstraintIndex{ScalarAffineFunction{T}, GreaterThan{T}}\nend","category":"page"},{"location":"tutorials/bridging_constraint/#2.-Bridge-creation","page":"Implementing a constraint bridge","title":"2. Bridge creation","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The function Bridges.Constraint.bridge_constraint is called whenever the bridge is instantiated for a specific model, with the given function and set. The arguments to bridge_constraint are similar to add_constraint, with the exception of the first argument: it is the Type of the struct defined in the first step (for our example, Type{SignBridge{T}}).","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"bridge_constraint returns an instance of the struct defined in the first step. the first step.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our example, the bridge constraint could be defined as:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function Bridges.Constraint.bridge_constraint(\n ::Type{SignBridge{T}}, # Bridge to use.\n model::ModelLike, # Model to which the constraint is being added.\n f::ScalarAffineFunction{T}, # Function to rewrite.\n s::LessThan{T}, # Set to rewrite.\n) where {T}\n # Create the variables and constraints required for the bridge.\n con = add_constraint(model, -f, GreaterThan(-s.upper))\n\n # Return an instance of the bridge type with a reference to all the\n # variables and constraints that were created in this function.\n return SignBridge(con)\nend","category":"page"},{"location":"tutorials/bridging_constraint/#3.-Supported-constraint-types","page":"Implementing a constraint bridge","title":"3. Supported constraint types","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The function supports_constraint determines whether the bridge type supports a given combination of function and set.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"This function must closely match bridge_constraint, because it will not be called if supports_constraint returns false.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function supports_constraint(\n ::Type{SignBridge{T}}, # Bridge to use.\n ::Type{ScalarAffineFunction{T}}, # Function to rewrite.\n ::Type{LessThan{T}}, # Set to rewrite.\n) where {T}\n # Do some computation to ensure that the constraint is supported.\n # Typically, you can directly return true.\n return true\nend","category":"page"},{"location":"tutorials/bridging_constraint/#4.-Metadata-about-the-bridge","page":"Implementing a constraint bridge","title":"4. Metadata about the bridge","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"To determine whether a bridge can be used, MOI uses a shortest-path algorithm that uses the variable types and the constraints that the bridge can create. This information is communicated from the bridge to MOI using the functions Bridges.added_constrained_variable_types and Bridges.added_constraint_types. Both return lists of tuples: either a list of 1-tuples containing the variable types (typically, ZeroOne or Integer) or a list of 2-tuples contained the functions and sets (like ScalarAffineFunction{T}-GreaterThan).","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"For our example, the bridge does not create any constrained variables, and only ScalarAffineFunction{T}-in-GreaterThan{T} constraints:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function Bridges.added_constrained_variable_types(::Type{SignBridge{T}}) where {T}\n # The bridge does not create variables, return an empty list of tuples:\n return Tuple{Type}[]\nend\n\nfunction Bridges.added_constraint_types(::Type{SignBridge{T}}) where {T}\n return Tuple{Type,Type}[\n # One element per F-in-S the bridge creates.\n (ScalarAffineFunction{T}, GreaterThan{T}),\n ]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"A bridge that creates binary variables would rather have this definition of added_constrained_variable_types:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function Bridges.added_constrained_variable_types(::Type{SomeBridge{T}}) where {T}\n # The bridge only creates binary variables:\n return Tuple{Type}[(ZeroOne,)]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"warning: Warning\nIf you declare the creation of constrained variables in added_constrained_variable_types, the corresponding constraint type VariableIndex must not be indicated in added_constraint_types. This would restrict the use of the bridge to solvers that can add such a constraint after the variable is created.More concretely, if you declare in added_constrained_variable_types that your bridge creates binary variables (ZeroOne), and if you never add such a constraint afterward (you do not call add_constraint(model, var, ZeroOne())), then you must not list (VariableIndex, ZeroOne) in added_constraint_types.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Typically, the function Bridges.Constraint.concrete_bridge_type does not have to be defined for most bridges.","category":"page"},{"location":"tutorials/bridging_constraint/#Bridge-registration","page":"Implementing a constraint bridge","title":"Bridge registration","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"For a bridge to be used by MOI, it must be known by MOI.","category":"page"},{"location":"tutorials/bridging_constraint/#SingleBridgeOptimizer","page":"Implementing a constraint bridge","title":"SingleBridgeOptimizer","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"The first way to do so is to create a single-bridge optimizer. This type of optimizer wraps another optimizer and adds the possibility to use only one bridge. It is especially useful when unit testing bridges.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"It is common practice to use the same name as the type defined for the bridge (SignBridge, in our example) without the suffix Bridge.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"const Sign{T,OT<: ModelLike} =\n SingleBridgeOptimizer{SignBridge{T}, OT}","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In the context of unit tests, this bridge is used in conjunction with a Utilities.MockOptimizer:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"mock = Utilities.MockOptimizer(\n Utilities.UniversalFallback(Utilities.Model{Float64}()),\n)\nbridged_mock = Sign{Float64}(mock)","category":"page"},{"location":"tutorials/bridging_constraint/#New-bridge-for-a-LazyBridgeOptimizer","page":"Implementing a constraint bridge","title":"New bridge for a LazyBridgeOptimizer","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Typical user-facing models for MOI are based on Bridges.LazyBridgeOptimizer. For instance, this type of model is returned by Bridges.full_bridge_optimizer. These models can be added more bridges by using Bridges.add_bridge:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"inner_optimizer = Utilities.Model{Float64}()\noptimizer = Bridges.full_bridge_optimizer(inner_optimizer, Float64)\nBridges.add_bridge(optimizer, SignBridge{Float64})","category":"page"},{"location":"tutorials/bridging_constraint/#Bridge-improvements","page":"Implementing a constraint bridge","title":"Bridge improvements","text":"","category":"section"},{"location":"tutorials/bridging_constraint/#Attribute-retrieval","page":"Implementing a constraint bridge","title":"Attribute retrieval","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"Like models, bridges have attributes that can be retrieved using get and set. The most important ones are the number of variables and constraints, but also the lists of variables and constraints.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our example, we only have one constraint and only have to implement the NumberOfConstraints and ListOfConstraintIndices attributes:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function get(\n ::SignBridge{T},\n ::NumberOfConstraints{\n ScalarAffineFunction{T},\n GreaterThan{T},\n },\n) where {T}\n return 1\nend\n\nfunction get(\n bridge::SignBridge{T},\n ::ListOfConstraintIndices{\n ScalarAffineFunction{T},\n GreaterThan{T},\n },\n) where {T}\n return [bridge.constraint]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"You must implement one such pair of functions for each type of constraint the bridge adds to the model.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"warning: Warning\nAvoid returning a list from the bridge object without copying it. Users must be able to change the contents of the returned list without altering the bridge object.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"For variables, the situation is simpler. If your bridge creates new variables, you must implement the NumberOfVariables and ListOfVariableIndices attributes. However, these attributes do not have parameters, unlike their constraint counterparts. Only two functions suffice:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function get(\n ::SignBridge{T},\n ::NumberOfVariables,\n) where {T}\n return 0\nend\n\nfunction get(\n ::SignBridge{T},\n ::ListOfVariableIndices,\n) where {T}\n return VariableIndex[]\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In order for the user to be able to access the function and set of the original constraint, the bridge needs to implement getters for the ConstraintFunction and ConstraintSet attributes:","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function get(\n model::MOI.ModelLike,\n attr::MOI.ConstraintFunction,\n bridge::SignBridge,\n)\n return -MOI.get(model, attr, bridge.constraint)\nend\n\nfunction get(\n model::MOI.ModelLike,\n attr::MOI.ConstraintSet,\n bridge::SignBridge,\n)\n set = MOI.get(model, attr, bridge.constraint)\n return MOI.LessThan(-set.lower)\nend","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"warning: Warning\nAlternatively, one could store the original function and set in SignBridge during Bridges.Constraint.bridge_constraint to make these getters simpler and more efficient. On the other hand, this will increase the memory footprint of the bridges as the garbage collector won't be able to delete that object. The convention is to not store the function in the bridge and not care too much about the efficiency of these getters. If the user needs efficient getters for ConstraintFunction then they should use a Utilities.CachingOptimizer.","category":"page"},{"location":"tutorials/bridging_constraint/#Model-modifications","page":"Implementing a constraint bridge","title":"Model modifications","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"To avoid copying the model when the user request to change a constraint, MOI provides modify. Bridges can also implement this API to allow certain changes, such as coefficient changes.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"In our case, a modification of a coefficient in the original constraint (for example, replacing the value of the coefficient of a variable in the affine function) must be transmitted to the constraint created by the bridge, but with a sign change.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function modify(\n model::ModelLike,\n bridge::SignBridge,\n change::ScalarCoefficientChange,\n)\n modify(\n model,\n bridge.constraint,\n ScalarCoefficientChange(change.variable, -change.new_coefficient),\n )\n return\nend","category":"page"},{"location":"tutorials/bridging_constraint/#Bridge-deletion","page":"Implementing a constraint bridge","title":"Bridge deletion","text":"","category":"section"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"When a bridge is deleted, the constraints it added must be deleted too.","category":"page"},{"location":"tutorials/bridging_constraint/","page":"Implementing a constraint bridge","title":"Implementing a constraint bridge","text":"function delete(model::ModelLike, bridge::SignBridge)\n delete(model, bridge.constraint)\n return\nend","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/latency/#Latency","page":"Latency","title":"Latency","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"MathOptInterface suffers the \"time-to-first-solve\" problem of start-up latency.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This hurts both the user- and developer-experience of MathOptInterface. In the first case, because simple models have a multi-second delay before solving, and in the latter, because our tests take so long to run.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This page contains some advice on profiling and fixing latency-related problems in the MathOptInterface.jl repository.","category":"page"},{"location":"tutorials/latency/#Background","page":"Latency","title":"Background","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Before reading this part of the documentation, you should familiarize yourself with the reasons for latency in Julia and how to fix them.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Read the blogposts on julialang.org on precompilation and SnoopCompile\nRead the SnoopCompile documentation.\nWatch Tim Holy's talk at JuliaCon 2021\nWatch the package development workshop at JuliaCon 2021","category":"page"},{"location":"tutorials/latency/#Causes","page":"Latency","title":"Causes","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are three main causes of latency in MathOptInterface:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"A large number of types\nLack of method ownership\nType-instability in the bridge layer","category":"page"},{"location":"tutorials/latency/#A-large-number-of-types","page":"Latency","title":"A large number of types","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Julia is very good at specializing method calls based on the input type. Each specialization has a compilation cost, but the benefit of faster run-time performance.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"The best-case scenario is for a method to be called a large number of times with a single set of argument types. The worst-case scenario is for a method to be called a single time for a large set of argument types.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Because of MathOptInterface's function-in-set formulation, we fall into the worst-case situation.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This is a fundamental limitation of Julia, so there isn't much we can do about it. However, if we can precompile MathOptInterface, much of the cost can be shifted from start-up latency to the time it takes to precompile a package on installation.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"However, there are two things which make MathOptInterface hard to precompile.","category":"page"},{"location":"tutorials/latency/#Lack-of-method-ownership","page":"Latency","title":"Lack of method ownership","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Lack of method ownership happens when a call is made using a mix of structs and methods from different modules. Because of this, no single module \"owns\" the method that is being dispatched, and so it cannot be precompiled.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"tip: Tip\nThis is a slightly simplified explanation. Read the precompilation tutorial for a more in-depth discussion on back-edges.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Unfortunately, the design of MOI means that this is a frequent occurrence: we have a bunch of types in MOI.Utilities that wrap types defined in external packages (for example, the Optimizers), which implement methods of functions defined in MOI (for example, add_variable, add_constraint).","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Here's a simple example of method-ownership in practice:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"module MyMOI\nstruct Wrapper{T}\n inner::T\nend\noptimize!(x::Wrapper) = optimize!(x.inner)\nend # MyMOI\n\nmodule MyOptimizer\nusing ..MyMOI\nstruct Optimizer end\nMyMOI.optimize!(x::Optimizer) = 1\nend # MyOptimizer\n\nusing SnoopCompile\nmodel = MyMOI.Wrapper(MyOptimizer.Optimizer())\n\njulia> tinf = @snoopi_deep MyMOI.optimize!(model)\nInferenceTimingNode: 0.008256/0.008543 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 1 direct children","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"The result is that there was one method that required type inference. If we visualize tinf:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"using ProfileView\nProfileView.view(flamegraph(tinf))","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"we see a flamegraph with a large red-bar indicating that the method MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) cannot be precompiled.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"To fix this, we need to designate a module to \"own\" that method (that is, create a back-edge). The easiest way to do this is for MyOptimizer to call MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) during using MyOptimizer. Let's see that in practice:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"module MyMOI\nstruct Wrapper{T}\n inner::T\nend\noptimize(x::Wrapper) = optimize(x.inner)\nend # MyMOI\n\nmodule MyOptimizer\nusing ..MyMOI\nstruct Optimizer end\nMyMOI.optimize(x::Optimizer) = 1\n# The syntax of this let-while loop is very particular:\n# * `let ... end` keeps everything local to avoid polluting the MyOptimizer\n# namespace\n# * `while true ... break end` runs the code once, and forces Julia to compile\n# the inner loop, rather than interpret it.\nlet\n while true\n model = MyMOI.Wrapper(Optimizer())\n MyMOI.optimize(model)\n break\n end\nend\nend # MyOptimizer\n\nusing SnoopCompile\nmodel = MyMOI.Wrapper(MyOptimizer.Optimizer())\n\njulia> tinf = @snoopi_deep MyMOI.optimize(model)\nInferenceTimingNode: 0.006822/0.006822 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 0 direct children","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are now 0 direct children that required type inference because the method was already stored in MyOptimizer!","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Unfortunately, this trick only works if the call-chain is fully inferrable. If there are breaks (due to type instability), then the benefit of doing this is reduced. And unfortunately for us, the design of MathOptInterface has a lot of type instabilities.","category":"page"},{"location":"tutorials/latency/#Type-instability-in-the-bridge-layer","page":"Latency","title":"Type instability in the bridge layer","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Most of MathOptInterface is pretty good at ensuring type-stability. However, a key component is not type stable, and that is the bridging layer.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"In particular, the bridging layer defines Bridges.LazyBridgeOptimizer, which has fields like:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"struct LazyBridgeOptimizer\n constraint_bridge_types::Vector{Any}\n constraint_node::Dict{Tuple{Type,Type},ConstraintNode}\n constraint_types::Vector{Tuple{Type,Type}}\nend","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"This is because the LazyBridgeOptimizer needs to be able to deal with any function-in-set type passed to it, and we also allow users to pass additional bridges that they defined in external packages.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"So to recap, MathOptInterface suffers package latency because:","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"there are a large number of types and functions\nand these are split between multiple modules, including external packages\nand there are type-instabilities like those in the bridging layer.","category":"page"},{"location":"tutorials/latency/#Resolutions","page":"Latency","title":"Resolutions","text":"","category":"section"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are no magic solutions to reduce latency. Issue #1313 tracks progress on reducing latency in MathOptInterface.","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"A useful script is the following (replace GLPK as needed):","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"import GLPK\nimport MathOptInterface as MOI\n\nfunction example_diet(optimizer, bridge)\n category_data = [\n 1800.0 2200.0;\n 91.0 Inf;\n 0.0 65.0;\n 0.0 1779.0\n ]\n cost = [2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59]\n food_data = [\n 410 24 26 730;\n 420 32 10 1190;\n 560 20 32 1800;\n 380 4 19 270;\n 320 12 10 930;\n 320 15 12 820;\n 320 31 12 1230;\n 100 8 2.5 125;\n 330 8 10 180\n ]\n bridge_model = if bridge\n MOI.instantiate(optimizer; with_bridge_type=Float64)\n else\n MOI.instantiate(optimizer)\n end\n model = MOI.Utilities.CachingOptimizer(\n MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),\n MOI.Utilities.AUTOMATIC,\n )\n MOI.Utilities.reset_optimizer(model, bridge_model)\n MOI.set(model, MOI.Silent(), true)\n nutrition = MOI.add_variables(model, size(category_data, 1))\n for (i, v) in enumerate(nutrition)\n MOI.add_constraint(model, v, MOI.GreaterThan(category_data[i, 1]))\n MOI.add_constraint(model, v, MOI.LessThan(category_data[i, 2]))\n end\n buy = MOI.add_variables(model, size(food_data, 1))\n MOI.add_constraint.(model, buy, MOI.GreaterThan(0.0))\n MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)\n f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(cost, buy), 0.0)\n MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)\n for (j, n) in enumerate(nutrition)\n f = MOI.ScalarAffineFunction(\n MOI.ScalarAffineTerm.(food_data[:, j], buy),\n 0.0,\n )\n push!(f.terms, MOI.ScalarAffineTerm(-1.0, n))\n MOI.add_constraint(model, f, MOI.EqualTo(0.0))\n end\n MOI.optimize!(model)\n term_status = MOI.get(model, MOI.TerminationStatus())\n @assert term_status == MOI.OPTIMAL\n MOI.add_constraint(\n model,\n MOI.ScalarAffineFunction(\n MOI.ScalarAffineTerm.(1.0, [buy[end-1], buy[end]]),\n 0.0,\n ),\n MOI.LessThan(6.0),\n )\n MOI.optimize!(model)\n @assert MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE\n return\nend\n\nif length(ARGS) > 0\n bridge = get(ARGS, 2, \"\") != \"--no-bridge\"\n println(\"Running: $(ARGS[1]) $(get(ARGS, 2, \"\"))\")\n @time example_diet(GLPK.Optimizer, bridge)\n @time example_diet(GLPK.Optimizer, bridge)\n exit(0)\nend","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"You can create a flame-graph via","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"using SnoopCompile\ntinf = @snoopi_deep example_diet(GLPK.Optimizer, true)\nusing ProfileView\nProfileView.view(flamegraph(tinf))","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"Here's how things looked in mid-August 2021: (Image: flamegraph)","category":"page"},{"location":"tutorials/latency/","page":"Latency","title":"Latency","text":"There are a few opportunities for improvement (non-red flames, particularly on the right). But the main problem is a large red (non-precompilable due to method ownership) flame.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"manual/solutions/#manual_solutions","page":"Solutions","title":"Solutions","text":"","category":"section"},{"location":"manual/solutions/#Solving-and-retrieving-the-results","page":"Solutions","title":"Solving and retrieving the results","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Once an optimizer is loaded with the objective function and all of the constraints, we can ask the solver to solve the model by calling optimize!.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"MOI.optimize!(optimizer)","category":"page"},{"location":"manual/solutions/#Why-did-the-solver-stop?","page":"Solutions","title":"Why did the solver stop?","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"The optimization procedure may stop for a number of reasons. The TerminationStatus attribute of the optimizer returns a TerminationStatusCode object which explains why the solver stopped.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"The termination statuses distinguish between proofs of optimality, infeasibility, local convergence, limits, and termination because of something unexpected like invalid problem data or failure to converge.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"A typical usage of the TerminationStatus attribute is as follows:","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"status = MOI.get(optimizer, TerminationStatus())\nif status == MOI.OPTIMAL\n # Ok, we solved the problem!\nelse\n # Handle other cases.\nend","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"After checking the TerminationStatus, check ResultCount. This attribute returns the number of results that the solver has available to return. A result is defined as a primal-dual pair, but either the primal or the dual may be missing from the result. While the OPTIMAL termination status normally implies that at least one result is available, other statuses do not. For example, in the case of infeasibility, a solver may return no result or a proof of infeasibility. The ResultCount attribute distinguishes between these two cases.","category":"page"},{"location":"manual/solutions/#Primal-solutions","page":"Solutions","title":"Primal solutions","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Use the PrimalStatus optimizer attribute to return a ResultStatusCode describing the status of the primal solution.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Common returns are described below in the Common status situations section.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the primal solution using the VariablePrimal and ConstraintPrimal attributes.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the objective function value using the ObjectiveValue attribute.","category":"page"},{"location":"manual/solutions/#Dual-solutions","page":"Solutions","title":"Dual solutions","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"warning: Warning\nSee Duality for a discussion of the MOI conventions for primal-dual pairs and certificates.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Use the DualStatus optimizer attribute to return a ResultStatusCode describing the status of the dual solution.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the dual solution using the ConstraintDual attribute.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Query the dual objective function value using the DualObjectiveValue attribute.","category":"page"},{"location":"manual/solutions/#Common-status-situations","page":"Solutions","title":"Common status situations","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"The sections below describe how to interpret typical or interesting status cases for three common classes of solvers. The example cases are illustrative, not comprehensive. Solver wrappers may provide additional information on how the solver's statuses map to MOI statuses.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"info: Info\n* in the tables indicate that multiple different values are possible.","category":"page"},{"location":"manual/solutions/#Primal-dual-convex-solver","page":"Solutions","title":"Primal-dual convex solver","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Linear programming and conic optimization solvers fall into this category.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"What happened? TerminationStatus ResultCount PrimalStatus DualStatus\nProved optimality OPTIMAL 1 FEASIBLE_POINT FEASIBLE_POINT\nProved infeasible INFEASIBLE 1 NO_SOLUTION INFEASIBILITY_CERTIFICATE\nOptimal within relaxed tolerances ALMOST_OPTIMAL 1 FEASIBLE_POINT FEASIBLE_POINT\nOptimal within relaxed tolerances ALMOST_OPTIMAL 1 ALMOST_FEASIBLE_POINT ALMOST_FEASIBLE_POINT\nDetected an unbounded ray of the primal DUAL_INFEASIBLE 1 INFEASIBILITY_CERTIFICATE NO_SOLUTION\nStall SLOW_PROGRESS 1 * *","category":"page"},{"location":"manual/solutions/#Global-branch-and-bound-solvers","page":"Solutions","title":"Global branch-and-bound solvers","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Mixed-integer programming solvers fall into this category.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"What happened? TerminationStatus ResultCount PrimalStatus DualStatus\nProved optimality OPTIMAL 1 FEASIBLE_POINT NO_SOLUTION\nPresolve detected infeasibility or unboundedness INFEASIBLE_OR_UNBOUNDED 0 NO_SOLUTION NO_SOLUTION\nProved infeasibility INFEASIBLE 0 NO_SOLUTION NO_SOLUTION\nTimed out (no solution) TIME_LIMIT 0 NO_SOLUTION NO_SOLUTION\nTimed out (with a solution) TIME_LIMIT 1 FEASIBLE_POINT NO_SOLUTION\nCPXMIP_OPTIMAL_INFEAS ALMOST_OPTIMAL 1 INFEASIBLE_POINT NO_SOLUTION","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"info: Info\nCPXMIP_OPTIMAL_INFEAS is a CPLEX status that indicates that a preprocessed problem was solved to optimality, but the solver was unable to recover a feasible solution to the original problem. Handling this status was one of the motivating drivers behind the design of MOI.","category":"page"},{"location":"manual/solutions/#Local-search-solvers","page":"Solutions","title":"Local search solvers","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Nonlinear programming solvers fall into this category. It also includes non-global tree search solvers like Juniper.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"What happened? TerminationStatus ResultCount PrimalStatus DualStatus\nConverged to a stationary point LOCALLY_SOLVED 1 FEASIBLE_POINT FEASIBLE_POINT\nCompleted a non-global tree search (with a solution) LOCALLY_SOLVED 1 FEASIBLE_POINT FEASIBLE_POINT\nConverged to an infeasible point LOCALLY_INFEASIBLE 1 INFEASIBLE_POINT *\nCompleted a non-global tree search (no solution found) LOCALLY_INFEASIBLE 0 NO_SOLUTION NO_SOLUTION\nIteration limit ITERATION_LIMIT 1 * *\nDiverging iterates NORM_LIMIT or OBJECTIVE_LIMIT 1 * *","category":"page"},{"location":"manual/solutions/#Querying-solution-attributes","page":"Solutions","title":"Querying solution attributes","text":"","category":"section"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"Some solvers will not implement every solution attribute. Therefore, a call like MOI.get(model, MOI.SolveTimeSec()) may throw an UnsupportedAttribute error.","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"If you need to write code that is agnostic to the solver (for example, you are writing a library that an end-user passes their choice of solver to), you can work-around this problem using a try-catch:","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"function get_solve_time(model)\n try\n return MOI.get(model, MOI.SolveTimeSec())\n catch err\n if err isa MOI.UnsupportedAttribute\n return NaN # Solver doesn't support. Return a placeholder value.\n end\n rethrow(err) # Something else went wrong. Rethrow the error\n end\nend","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"If, after careful profiling, you find that the try-catch is taking a significant portion of your runtime, you can improve performance by caching the result of the try-catch:","category":"page"},{"location":"manual/solutions/","page":"Solutions","title":"Solutions","text":"mutable struct CachedSolveTime{M}\n model::M\n supports_solve_time::Bool\n CachedSolveTime(model::M) where {M} = new(model, true)\nend\n\nfunction get_solve_time(model::CachedSolveTime)\n if !model.supports_solve_time\n return NaN\n end\n try\n return MOI.get(model, MOI.SolveTimeSec())\n catch err\n if err isa MOI.UnsupportedAttribute\n model.supports_solve_time = false\n return NaN\n end\n rethrow(err) # Something else went wrong. Rethrow the error\n end\nend","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"tutorials/manipulating_expressions/#Manipulating-expressions","page":"Manipulating expressions","title":"Manipulating expressions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"This guide highlights a syntactically appealing way to build expressions at the MOI level, but also to look at their contents. It may be especially useful when writing models or bridge code.","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-functions","page":"Manipulating expressions","title":"Creating functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"This section details the ways to create functions with MathOptInterface.","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-scalar-affine-functions","page":"Manipulating expressions","title":"Creating scalar affine functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"The simplest scalar function is simply a variable:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> x = MOI.add_variable(model) # Create the variable x\nMOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"This type of function is extremely simple; to express more complex functions, other types must be used. For instance, a ScalarAffineFunction is a sum of linear terms (a factor times a variable) and a constant. Such an object can be built using the standard constructor:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1, x)], 2) # x + 2\n(2) + (1) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"However, you can also use operators to build the same scalar function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> f = x + 2\n(2) + (1) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-scalar-quadratic-functions","page":"Manipulating expressions","title":"Creating scalar quadratic functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Scalar quadratic functions are stored in ScalarQuadraticFunction objects, in a way that is highly similar to scalar affine functions. You can obtain a quadratic function as a product of affine functions:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> 1 * x * x\n(0) + 1.0 MOI.VariableIndex(1)²\n\njulia> f * f # (x + 2)²\n(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²\n\njulia> f^2 # (x + 2)² too\n(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²","category":"page"},{"location":"tutorials/manipulating_expressions/#Creating-vector-functions","page":"Manipulating expressions","title":"Creating vector functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"A vector function is a function with several values, irrespective of the number of input variables. Similarly to scalar functions, there are three main types of vector functions: VectorOfVariables, VectorAffineFunction, and VectorQuadraticFunction.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"The easiest way to create a vector function is to stack several scalar functions using Utilities.vectorize. It takes a vector as input, and the generated vector function (of the most appropriate type) has each dimension corresponding to a dimension of the vector.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> g = MOI.Utilities.vectorize([f, 2 * f])\n┌ ┐\n│(2) + (1) MOI.VariableIndex(1)│\n│(4) + (2) MOI.VariableIndex(1)│\n└ ┘","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"warning: Warning\nUtilities.vectorize only takes a vector of similar scalar functions: you cannot mix VariableIndex and ScalarAffineFunction, for instance. In practice, it means that Utilities.vectorize([x, f]) does not work; you should rather use Utilities.vectorize([1 * x, f]) instead to only have ScalarAffineFunction objects.","category":"page"},{"location":"tutorials/manipulating_expressions/#Canonicalizing-functions","page":"Manipulating expressions","title":"Canonicalizing functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"In more advanced use cases, you might need to ensure that a function is \"canonical.\" Functions are stored as an array of terms, but there is no check that these terms are redundant: a ScalarAffineFunction object might have two terms with the same variable, like x + x + 1. These terms could be merged without changing the semantics of the function: 2x + 1.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Working with these objects might be cumbersome. Canonicalization helps maintain redundancy to zero.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Utilities.is_canonical checks whether a function is already in its canonical form:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.Utilities.is_canonical(f + f) # (x + 2) + (x + 2) is stored as x + x + 4\nfalse","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Utilities.canonical returns the equivalent canonical version of the function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.Utilities.canonical(f + f) # Returns 2x + 4\n(4) + (2) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/#Exploring-functions","page":"Manipulating expressions","title":"Exploring functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"At some point, you might need to dig into a function, for instance to map it into solver constructs.","category":"page"},{"location":"tutorials/manipulating_expressions/#Vector-functions","page":"Manipulating expressions","title":"Vector functions","text":"","category":"section"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"Utilities.scalarize returns a vector of scalar functions from a vector function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.Utilities.scalarize(g) # Returns a vector [f, 2 * f].\n2-element Vector{MathOptInterface.ScalarAffineFunction{Int64}}:\n (2) + (1) MOI.VariableIndex(1)\n (4) + (2) MOI.VariableIndex(1)","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"note: Note\nUtilities.eachscalar returns an iterator on the dimensions, which serves the same purpose as Utilities.scalarize.","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"output_dimension returns the number of dimensions of the output of a function:","category":"page"},{"location":"tutorials/manipulating_expressions/","page":"Manipulating expressions","title":"Manipulating expressions","text":"julia> MOI.output_dimension(g)\n2","category":"page"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"submodules/Bridges/reference/#Bridges","page":"API Reference","title":"Bridges","text":"","category":"section"},{"location":"submodules/Bridges/reference/#AbstractBridge-API","page":"API Reference","title":"AbstractBridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.AbstractBridge\nBridges.added_constrained_variable_types\nBridges.added_constraint_types\nget(::Bridges.AbstractBridge, ::NumberOfVariables)\nget(::Bridges.AbstractBridge, ::ListOfVariableIndices)\nget(::Bridges.AbstractBridge, ::NumberOfConstraints)\nget(::Bridges.AbstractBridge, ::ListOfConstraintIndices)\nBridges.needs_final_touch\nBridges.final_touch\nBridges.bridging_cost\nBridges.runtests","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.AbstractBridge","text":"abstract type AbstractBridge end\n\nAn abstract type representing a bridged constraint or variable in a MOI.Bridges.AbstractBridgeOptimizer.\n\nAll bridges must implement:\n\nadded_constrained_variable_types\nadded_constraint_types\nMOI.get(::AbstractBridge, ::MOI.NumberOfVariables)\nMOI.get(::AbstractBridge, ::MOI.ListOfVariableIndices)\nMOI.get(::AbstractBridge, ::MOI.NumberOfConstraints)\nMOI.get(::AbstractBridge, ::MOI.ListOfConstraintIndices)\n\nSubtypes of AbstractBridge may have additional requirements. Consult their docstrings for details.\n\nIn addition, all subtypes may optionally implement the following constraint attributes with the bridge in place of the constraint index:\n\nMOI.ConstraintDual\nMOI.ConstraintPrimal\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.added_constrained_variable_types","page":"API Reference","title":"MathOptInterface.Bridges.added_constrained_variable_types","text":"added_constrained_variable_types(\n BT::Type{<:AbstractBridge},\n)::Vector{Tuple{Type}}\n\nReturn a list of the types of constrained variables that bridges of concrete type BT add.\n\nImplementation notes\n\nThis method depends only on the type of the bridge, not the runtime value. If the bridge may add a constrained variable, the type must be included in the return vector.\nIf the bridge adds a free variable via MOI.add_variable or MOI.add_variables, the return vector must include (MOI.Reals,).\n\nExample\n\njulia> MOI.Bridges.added_constrained_variable_types(\n MOI.Bridges.Variable.NonposToNonnegBridge{Float64},\n )\n1-element Vector{Tuple{Type}}:\n (MathOptInterface.Nonnegatives,)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.added_constraint_types","page":"API Reference","title":"MathOptInterface.Bridges.added_constraint_types","text":"added_constraint_types(\n BT::Type{<:AbstractBridge},\n)::Vector{Tuple{Type,Type}}\n\nReturn a list of the types of constraints that bridges of concrete type BT add.\n\nImplementation notes\n\nThis method depends only on the type of the bridge, not the runtime value. If the bridge may add a constraint, the type must be included in the return vector.\n\nExample\n\njulia> MOI.Bridges.added_constraint_types(\n MOI.Bridges.Constraint.ZeroOneBridge{Float64},\n )\n2-element Vector{Tuple{Type, Type}}:\n (MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.Interval{Float64})\n (MathOptInterface.VariableIndex, MathOptInterface.Integer)\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.NumberOfVariables}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64\n\nReturn the number of variables created by the bridge b in the model.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.ListOfVariableIndices}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)\n\nReturn the list of variables created by the bridge b.\n\nSee also MOI.ListOfVariableIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this if the bridge adds new variables.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.NumberOfConstraints}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}\n\nReturn the number of constraints of the type F-in-S created by the bridge b.\n\nSee also MOI.NumberOfConstraints.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.get-Tuple{MathOptInterface.Bridges.AbstractBridge, MathOptInterface.ListOfConstraintIndices}","page":"API Reference","title":"MathOptInterface.get","text":"MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}\n\nReturn a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.\n\nSee also MOI.ListOfConstraintIndices.\n\nImplementation notes\n\nThere is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.needs_final_touch","page":"API Reference","title":"MathOptInterface.Bridges.needs_final_touch","text":"needs_final_touch(bridge::AbstractBridge)::Bool\n\nReturn whether final_touch is implemented by bridge.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.final_touch","page":"API Reference","title":"MathOptInterface.Bridges.final_touch","text":"final_touch(bridge::AbstractBridge, model::MOI.ModelLike)::Nothing\n\nA function that is called immediately prior to MOI.optimize! to allow bridges to modify their reformulations with respect to other variables and constraints in model.\n\nFor example, if the correctness of bridge depends on the bounds of a variable or the fact that variables are integer, then the bridge can implement final_touch to check assumptions immediately before a call to MOI.optimize!.\n\nIf you implement this method, you must also implement needs_final_touch.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridging_cost","page":"API Reference","title":"MathOptInterface.Bridges.bridging_cost","text":"bridging_cost(b::AbstractBridgeOptimizer, S::Type{<:MOI.AbstractSet}})\n\nReturn the cost of bridging variables constrained in S on creation, is_bridged(b, S) is assumed to be true.\n\nbridging_cost(\n b::AbstractBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)\n\nReturn the cost of bridging F-in-S constraints.\n\nis_bridged(b, S) is assumed to be true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.runtests","page":"API Reference","title":"MathOptInterface.Bridges.runtests","text":"runtests(\n Bridge::Type{<:AbstractBridge},\n input::String,\n output::String;\n variable_start = 1.2,\n constraint_start = 1.2,\n eltype = Float64,\n)\n\nRun a series of tests that check the correctness of Bridge.\n\ninput and output are models in the style of MOI.Utilities.loadfromstring!.\n\nExample\n\njulia> MOI.Bridges.runtests(\n MOI.Bridges.Constraint.ZeroOneBridge,\n \"\"\"\n variables: x\n x in ZeroOne()\n \"\"\",\n \"\"\"\n variables: x\n x in Integer()\n 1.0 * x in Interval(0.0, 1.0)\n \"\"\",\n )\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#Constraint-bridge-API","page":"API Reference","title":"Constraint bridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Constraint.AbstractBridge\nsupports_constraint(::Type{<:Bridges.Constraint.AbstractBridge}, ::Type{<:AbstractFunction}, ::Type{<:AbstractSet})\nBridges.Constraint.concrete_bridge_type\nBridges.Constraint.bridge_constraint\nBridges.Constraint.AbstractFunctionConversionBridge\nBridges.Constraint.SingleBridgeOptimizer\nBridges.Constraint.add_all_bridges\nBridges.Constraint.FlipSignBridge\nBridges.Constraint.AbstractToIntervalBridge\nBridges.Constraint.MultiSetMapBridge\nBridges.Constraint.SetMapBridge\nBridges.Constraint.conversion_cost","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.AbstractBridge","text":"abstract type AbstractBridge <: MOI.Bridges.AbstractType\n\nSubtype of MOI.Bridges.AbstractBridge for constraint bridges.\n\nIn addition to the required implementation described in MOI.Bridges.AbstractBridge, subtypes of AbstractBridge must additionally implement:\n\nMOI.supports_constraint(::Type{<:AbstractBridge}, ::Type{<:MOI.AbstractFunction}, ::Type{<:MOI.AbstractSet})\nconcrete_bridge_type\nbridge_constraint\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.supports_constraint-Tuple{Type{<:MathOptInterface.Bridges.Constraint.AbstractBridge}, Type{<:MathOptInterface.AbstractFunction}, Type{<:MathOptInterface.AbstractSet}}","page":"API Reference","title":"MathOptInterface.supports_constraint","text":"MOI.supports_constraint(\n BT::Type{<:AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.\n\nImplementation notes\n\nThis method depends only on the type of the inputs, not the runtime values.\nThere is a default fallback, so you need only implement this method for constraint types that the bridge implements.\n\n\n\n\n\n","category":"method"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.concrete_bridge_type","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.concrete_bridge_type","text":"concrete_bridge_type(\n BT::Type{<:AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet}\n)::Type\n\nReturn the concrete type of the bridge supporting F-in-S constraints.\n\nThis function can only be called if MOI.supports_constraint(BT, F, S) is true.\n\nExample\n\nThe SplitIntervalBridge bridges a MOI.VariableIndex-in-MOI.Interval constraint into a MOI.VariableIndex-in-MOI.GreaterThan and a MOI.VariableIndex-in-MOI.LessThan constraint.\n\njulia> MOI.Bridges.Constraint.concrete_bridge_type(\n MOI.Bridges.Constraint.SplitIntervalBridge{Float64},\n MOI.VariableIndex,\n MOI.Interval{Float64},\n )\nMathOptInterface.Bridges.Constraint.SplitIntervalBridge{Float64, MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}, MathOptInterface.GreaterThan{Float64}, MathOptInterface.LessThan{Float64}}\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.bridge_constraint","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.bridge_constraint","text":"bridge_constraint(\n BT::Type{<:AbstractBridge},\n model::MOI.ModelLike,\n func::AbstractFunction,\n set::MOI.AbstractSet,\n)::BT\n\nBridge the constraint func-in-set using bridge BT to model and returns a bridge object of type BT.\n\nImplementation notes\n\nThe bridge type BT should be a concrete type, that is, all the type parameters of the bridge must be set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.AbstractFunctionConversionBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.AbstractFunctionConversionBridge","text":"abstract type AbstractFunctionConversionBridge{F,S} <: AbstractBridge end\n\nAbstract type to support writing bridges in which the function changes but the set does not.\n\nBy convention, the transformed function is stored in the .constraint field.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.SingleBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.SingleBridgeOptimizer","text":"SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)\n\nReturn AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.\n\nThis is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.\n\nExample\n\njulia> struct MyNewBridge{T} <: MOI.Bridges.Constraint.AbstractBridge end\n\njulia> bridge = MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}}(\n MOI.Utilities.Model{Float64}(),\n )\nMOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 constraint bridges\nwith inner model MOIU.Model{Float64}\n\nImplementation notes\n\nAll bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.\n\njulia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =\n MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{T},OT};\n\nThis enables users to create bridged models as follows:\n\njulia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())\nMOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 constraint bridges\nwith inner model MOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.add_all_bridges","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.add_all_bridges","text":"add_all_bridges(bridged_model, ::Type{T}) where {T}\n\nAdd all bridges defined in the Bridges.Constraint submodule to bridged_model. The coefficient type used is T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.FlipSignBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.FlipSignBridge","text":"FlipSignBridge{T,S1,S2,F,G}\n\nAn abstract type that simplifies the creation of other bridges.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.AbstractToIntervalBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.AbstractToIntervalBridge","text":"AbstractToIntervalBridge{T<:AbstractFloat,S,F}\n\nAn abstract type that simplifies the creation of other bridges.\n\nwarning: Warning\nT must be a AbstractFloat type because otherwise typemin and typemax would either be not implemented (for example, BigInt), or would not give infinite value (for example, Int). For this reason, this bridge is only added to MOI.Bridges.full_bridge_optimizer when T is a subtype of AbstractFloat.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.MultiSetMapBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.MultiSetMapBridge","text":"abstract type MultiSetMapBridge{T,S1,G} <: AbstractBridge end\n\nSame as SetMapBridge but the output constraint type does not only depend on the input constraint type.\n\nWhen subtyping MultiSetMapBridge, added_constraint_types and supports should additionally be implemented by the bridge.\n\nFor example, if a bridge BridgeType may create either a constraint of type F2-in-S2 or F3-in-S3, these methods should be implemented as follows:\n\nfunction MOI.Bridges.added_constraint_types(\n ::Type{<:BridgeType{T,F2,F3}},\n) where {T,F2,F3}\n return Tuple{Type,Type}[(F2, S2), (F3, S3)]\nend\n\nfunction MOI.supports(\n model::MOI.ModelLike,\n attr::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},\n ::Type{<:BridgeType{T,F2,F3}},\n) where {T,F2,F3}\n return MOI.supports(model, attr, MOI.ConstraintIndex{F2,S2}) ||\n MOI.supports(model, attr, MOI.ConstraintIndex{F3,S3})\nend\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.SetMapBridge","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.SetMapBridge","text":"abstract type SetMapBridge{T,S2,S1,F,G} <: MultiSetMapBridge{T,S1,G} end\n\nConsider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.\n\nA SetMapBridge{T,S2,S1,F,G} is a bridge that maps G-in-S1 constraints into F-in-S2 by mapping the function through A.\n\nThe linear map A is described by;\n\nMOI.Bridges.map_set\nMOI.Bridges.map_function.\n\nImplementing a method for these two functions is sufficient to bridge constraints. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:\n\nMOI.Bridges.inverse_map_set\nMOI.Bridges.inverse_map_function\nMOI.Bridges.adjoint_map_function\nMOI.Bridges.inverse_adjoint_map_function\n\nSee the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Constraint.conversion_cost","page":"API Reference","title":"MathOptInterface.Bridges.Constraint.conversion_cost","text":"conversion_cost(\n F::Type{<:MOI.AbstractFunction},\n G::Type{<:MOI.AbstractFunction},\n)::Float64\n\nReturn a Float64 returning the cost of converting any function of type G to a function of type F with convert.\n\nThis cost is used to compute MOI.Bridges.bridging_cost.\n\nThe default cost is Inf, which means that MOI.Bridges.Constraint.FunctionConversionBridge should not attempt the conversion.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#Objective-bridge-API","page":"API Reference","title":"Objective bridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Objective.AbstractBridge\nBridges.Objective.supports_objective_function\nBridges.set_objective_function_type\nBridges.Objective.concrete_bridge_type\nBridges.Objective.bridge_objective\nBridges.Objective.SingleBridgeOptimizer\nBridges.Objective.add_all_bridges","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.Objective.AbstractBridge","text":"abstract type AbstractBridge <: MOI.Bridges.AbstractBridge end\n\nSubtype of MOI.Bridges.AbstractBridge for objective bridges.\n\nIn addition to the required implementation described in MOI.Bridges.AbstractBridge, subtypes of AbstractBridge must additionally implement:\n\nsupports_objective_function\nconcrete_bridge_type\nbridge_objective\nMOI.Bridges.set_objective_function_type\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.supports_objective_function","page":"API Reference","title":"MathOptInterface.Bridges.Objective.supports_objective_function","text":"supports_objective_function(\n BT::Type{<:MOI.Bridges.Objective.AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging objective functions of type F.\n\nImplementation notes\n\nThis method depends only on the type of the inputs, not the runtime values.\nThere is a default fallback, so you need only implement this method For objective functions that the bridge implements.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.set_objective_function_type","page":"API Reference","title":"MathOptInterface.Bridges.set_objective_function_type","text":"set_objective_function_type(\n BT::Type{<:Objective.AbstractBridge},\n)::Type{<:MOI.AbstractFunction}\n\nReturn the type of objective function that bridges of concrete type BT set.\n\nImplementation notes\n\nThis method depends only on the type of the bridge, not the runtime value.\n\nExample\n\njulia> MOI.Bridges.set_objective_function_type(\n MOI.Bridges.Objective.FunctionizeBridge{Float64},\n )\nMathOptInterface.ScalarAffineFunction{Float64}\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.concrete_bridge_type","page":"API Reference","title":"MathOptInterface.Bridges.Objective.concrete_bridge_type","text":"concrete_bridge_type(\n BT::Type{<:MOI.Bridges.Objective.AbstractBridge},\n F::Type{<:MOI.AbstractFunction},\n)::Type\n\nReturn the concrete type of the bridge supporting objective functions of type F.\n\nThis function can only be called if MOI.supports_objective_function(BT, F) is true.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.bridge_objective","page":"API Reference","title":"MathOptInterface.Bridges.Objective.bridge_objective","text":"bridge_objective(\n BT::Type{<:MOI.Bridges.Objective.AbstractBridge},\n model::MOI.ModelLike,\n func::MOI.AbstractFunction,\n)::BT\n\nBridge the objective function func using bridge BT to model and returns a bridge object of type BT.\n\nImplementation notes\n\nThe bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.SingleBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.Objective.SingleBridgeOptimizer","text":"SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)\n\nReturn AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.\n\nThis is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.\n\nExample\n\njulia> struct MyNewBridge{T} <: MOI.Bridges.Objective.AbstractBridge end\n\njulia> bridge = MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}}(\n MOI.Utilities.Model{Float64}(),\n )\nMOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}\n\nImplementation notes\n\nAll bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.\n\njulia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =\n MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{T},OT};\n\nThis enables users to create bridged models as follows:\n\njulia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())\nMOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Objective.add_all_bridges","page":"API Reference","title":"MathOptInterface.Bridges.Objective.add_all_bridges","text":"add_all_bridges(model, ::Type{T}) where {T}\n\nAdd all bridges defined in the Bridges.Objective submodule to model.\n\nThe coefficient type used is T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#ref_variable_bridges","page":"API Reference","title":"Variable bridge API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Variable.AbstractBridge\nBridges.Variable.supports_constrained_variable\nBridges.Variable.concrete_bridge_type\nBridges.Variable.bridge_constrained_variable\nBridges.Variable.SingleBridgeOptimizer\nBridges.Variable.add_all_bridges\nBridges.Variable.FlipSignBridge\nBridges.Variable.SetMapBridge\nBridges.Variable.unbridged_map","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.AbstractBridge","page":"API Reference","title":"MathOptInterface.Bridges.Variable.AbstractBridge","text":"abstract type AbstractBridge <: MOI.Bridges.AbstractBridge end\n\nSubtype of MOI.Bridges.AbstractBridge for variable bridges.\n\nIn addition to the required implementation described in MOI.Bridges.AbstractBridge, subtypes of AbstractBridge must additionally implement:\n\nsupports_constrained_variable\nconcrete_bridge_type\nbridge_constrained_variable\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.supports_constrained_variable","page":"API Reference","title":"MathOptInterface.Bridges.Variable.supports_constrained_variable","text":"supports_constrained_variable(\n BT::Type{<:AbstractBridge},\n S::Type{<:MOI.AbstractSet},\n)::Bool\n\nReturn a Bool indicating whether the bridges of type BT support bridging constrained variables in S. That is, it returns true if the bridge of type BT converts constrained variables of type S into a form supported by the solver.\n\nImplementation notes\n\nThis method depends only on the type of the bridge and set, not the runtime values.\nThere is a default fallback, so you need only implement this method for sets that the bridge implements.\n\nExample\n\njulia> MOI.Bridges.Variable.supports_constrained_variable(\n MOI.Bridges.Variable.NonposToNonnegBridge{Float64},\n MOI.Nonpositives,\n )\ntrue\n\njulia> MOI.Bridges.Variable.supports_constrained_variable(\n MOI.Bridges.Variable.NonposToNonnegBridge{Float64},\n MOI.Nonnegatives,\n )\nfalse\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.concrete_bridge_type","page":"API Reference","title":"MathOptInterface.Bridges.Variable.concrete_bridge_type","text":"concrete_bridge_type(\n BT::Type{<:AbstractBridge},\n S::Type{<:MOI.AbstractSet},\n)::Type\n\nReturn the concrete type of the bridge supporting variables in S constraints.\n\nThis function can only be called if MOI.supports_constrained_variable(BT, S) is true.\n\nExamples\n\nAs a variable in MOI.GreaterThan is bridged into variables in MOI.Nonnegatives by the VectorizeBridge:\n\njulia> MOI.Bridges.Variable.concrete_bridge_type(\n MOI.Bridges.Variable.VectorizeBridge{Float64},\n MOI.GreaterThan{Float64},\n )\nMathOptInterface.Bridges.Variable.VectorizeBridge{Float64, MathOptInterface.Nonnegatives}\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.bridge_constrained_variable","page":"API Reference","title":"MathOptInterface.Bridges.Variable.bridge_constrained_variable","text":"bridge_constrained_variable(\n BT::Type{<:AbstractBridge},\n model::MOI.ModelLike,\n set::MOI.AbstractSet,\n)::BT\n\nBridge the constrained variable in set using bridge BT to model and returns a bridge object of type BT.\n\nImplementation notes\n\nThe bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.SingleBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.Variable.SingleBridgeOptimizer","text":"SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)\n\nReturn MOI.Bridges.AbstractBridgeOptimizer that always bridges any variables constrained on creation supported by the bridge BT.\n\nThis is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the variables constrained on creation if they are supported by the bridge BT and unsupported by model.\n\nwarning: Warning\nTwo SingleBridgeOptimizers cannot be used together as both of them assume that the underlying model only returns variable indices with nonnegative values. Use MOI.Bridges.LazyBridgeOptimizer instead.\n\nExample\n\njulia> struct MyNewBridge{T} <: MOI.Bridges.Variable.AbstractBridge end\n\njulia> bridge = MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}}(\n MOI.Utilities.Model{Float64}(),\n )\nMOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 variable bridges\nwith inner model MOIU.Model{Float64}\n\nImplementation notes\n\nAll bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.\n\njulia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =\n MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{T},OT};\n\nThis enables users to create bridged models as follows:\n\njulia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())\nMOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}\nwith 0 variable bridges\nwith inner model MOIU.Model{Float64}\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.add_all_bridges","page":"API Reference","title":"MathOptInterface.Bridges.Variable.add_all_bridges","text":"add_all_bridges(model, ::Type{T}) where {T}\n\nAdd all bridges defined in the Bridges.Variable submodule to model.\n\nThe coefficient type used is T.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.FlipSignBridge","page":"API Reference","title":"MathOptInterface.Bridges.Variable.FlipSignBridge","text":"abstract type FlipSignBridge{T,S1,S2} <: SetMapBridge{T,S2,S1} end\n\nAn abstract type that simplifies the creation of other bridges.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.SetMapBridge","page":"API Reference","title":"MathOptInterface.Bridges.Variable.SetMapBridge","text":"abstract type SetMapBridge{T,S1,S2} <: AbstractBridge end\n\nConsider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.\n\nA SetMapBridge{T,S1,S2} is a bridge that substitutes constrained variables in S2 into the image through A of constrained variables in S1.\n\nThe linear map A is described by:\n\nMOI.Bridges.map_set\nMOI.Bridges.map_function\n\nImplementing a method for these two functions is sufficient to bridge constrained variables. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:\n\nMOI.Bridges.inverse_map_set\nMOI.Bridges.inverse_map_function\nMOI.Bridges.adjoint_map_function\nMOI.Bridges.inverse_adjoint_map_function.\n\nSee the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Variable.unbridged_map","page":"API Reference","title":"MathOptInterface.Bridges.Variable.unbridged_map","text":"unbridged_map(\n bridge::MOI.Bridges.Variable.AbstractBridge,\n vi::MOI.VariableIndex,\n)\n\nFor a bridged variable in a scalar set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi.\n\nunbridged_map(\n bridge::MOI.Bridges.Variable.AbstractBridge,\n vis::Vector{MOI.VariableIndex},\n)\n\nFor a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vis. If this method is not implemented, it falls back to calling the following method for every variable of vis.\n\nunbridged_map(\n bridge::MOI.Bridges.Variable.AbstractBridge,\n vi::MOI.VariableIndex,\n i::MOI.Bridges.IndexInVector,\n)\n\nFor a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi corresponding to the ith variable of the vector.\n\nIf there is no way to recover the expression in terms of the bridged variable(s) vi(s), return nothing. See ZerosBridge for an example of bridge returning nothing.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#AbstractBridgeOptimizer-API","page":"API Reference","title":"AbstractBridgeOptimizer API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.AbstractBridgeOptimizer\nBridges.bridged_variable_function\nBridges.unbridged_variable_function\nBridges.bridged_function\nBridges.supports_constraint_bridges\nBridges.recursive_model\nBridges.FirstBridge","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.AbstractBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.AbstractBridgeOptimizer","text":"abstract type AbstractBridgeOptimizer <: MOI.AbstractOptimizer end\n\nAn abstract type that implements generic functions for bridges.\n\nImplementation notes\n\nBy convention, the inner optimizer should be stored in a model field. If not, the optimizer must implement MOI.optimize!.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridged_variable_function","page":"API Reference","title":"MathOptInterface.Bridges.bridged_variable_function","text":"bridged_variable_function(\n b::AbstractBridgeOptimizer,\n vi::MOI.VariableIndex,\n)\n\nReturn a MOI.AbstractScalarFunction of variables of b.model that equals vi. That is, if the variable vi is bridged, it returns its expression in terms of the variables of b.model. Otherwise, it returns vi.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.unbridged_variable_function","page":"API Reference","title":"MathOptInterface.Bridges.unbridged_variable_function","text":"unbridged_variable_function(\n b::AbstractBridgeOptimizer,\n vi::MOI.VariableIndex,\n)\n\nReturn a MOI.AbstractScalarFunction of variables of b that equals vi. That is, if the variable vi is an internal variable of b.model created by a bridge but not visible to the user, it returns its expression in terms of the variables of bridged variables. Otherwise, it returns vi.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridged_function","page":"API Reference","title":"MathOptInterface.Bridges.bridged_function","text":"bridged_function(b::AbstractBridgeOptimizer, value)::typeof(value)\n\nSubstitute any bridged MOI.VariableIndex in value by an equivalent expression in terms of variables of b.model.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.supports_constraint_bridges","page":"API Reference","title":"MathOptInterface.Bridges.supports_constraint_bridges","text":"supports_constraint_bridges(b::AbstractBridgeOptimizer)::Bool\n\nReturn a Bool indicating if b supports MOI.Bridges.Constraint.AbstractBridge.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.recursive_model","page":"API Reference","title":"MathOptInterface.Bridges.recursive_model","text":"recursive_model(b::AbstractBridgeOptimizer)\n\nIf a variable, constraint, or objective is bridged, return the context of the inner variables. For most optimizers, this should be b.model.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.FirstBridge","page":"API Reference","title":"MathOptInterface.Bridges.FirstBridge","text":"struct FirstBridge <: MOI.AbstractConstraintAttribute end\n\nReturns the first bridge used to bridge the constraint.\n\nwarning: Warning\nThe indices of the bridge correspond to internal indices and may not correspond to indices of the model this attribute is got from.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#LazyBridgeOptimizer-API","page":"API Reference","title":"LazyBridgeOptimizer API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.LazyBridgeOptimizer\nBridges.full_bridge_optimizer\nBridges.ListOfNonstandardBridges\nBridges.add_bridge\nBridges.remove_bridge\nBridges.has_bridge\nBridges.print_active_bridges\nBridges.print_graph\nBridges.debug_supports_constraint\nBridges.debug_supports","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.LazyBridgeOptimizer","page":"API Reference","title":"MathOptInterface.Bridges.LazyBridgeOptimizer","text":"LazyBridgeOptimizer(model::MOI.ModelLike)\n\nThe LazyBridgeOptimizer is a bridge optimizer that supports multiple bridges, and only bridges things which are not supported by the internal model.\n\nInternally, the LazyBridgeOptimizer solves a shortest hyper-path problem to determine which bridges to use.\n\nIn general, you should use full_bridge_optimizer instead of this constructor because full_bridge_optimizer automatically adds a large number of supported bridges.\n\nSee also: add_bridge, remove_bridge, has_bridge and full_bridge_optimizer.\n\nExample\n\njulia> model = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.Model{Float64}())\nMOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}\nwith 0 variable bridges\nwith 0 constraint bridges\nwith 0 objective bridges\nwith inner model MOIU.Model{Float64}\n\njulia> MOI.Bridges.add_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})\n\njulia> MOI.Bridges.has_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})\ntrue\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.full_bridge_optimizer","page":"API Reference","title":"MathOptInterface.Bridges.full_bridge_optimizer","text":"full_bridge_optimizer(model::MOI.ModelLike, ::Type{T}) where {T}\n\nReturns a LazyBridgeOptimizer bridging model for every bridge defined in this package (see below for the few exceptions) and for the coefficient type T, as well as the bridges in the list returned by the ListOfNonstandardBridges attribute.\n\nExample\n\njulia> model = MOI.Utilities.Model{Float64}();\n\njulia> bridged_model = MOI.Bridges.full_bridge_optimizer(model, Float64);\n\nExceptions\n\nThe following bridges are not added by full_bridge_optimizer, except if they are in the list returned by the ListOfNonstandardBridges attribute:\n\nConstraint.SOCtoNonConvexQuadBridge\nConstraint.RSOCtoNonConvexQuadBridge](@ref)\nConstraint.SOCtoPSDBridge\nIf T is not a subtype of AbstractFloat, subtypes of Constraint.AbstractToIntervalBridge\nConstraint.GreaterToIntervalBridge\nConstraint.LessToIntervalBridge)\n\nSee the docstring of the each bridge for the reason they are not added.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ListOfNonstandardBridges","page":"API Reference","title":"MathOptInterface.Bridges.ListOfNonstandardBridges","text":"ListOfNonstandardBridges{T}() <: MOI.AbstractOptimizerAttribute\n\nAny optimizer can be wrapped in a LazyBridgeOptimizer using full_bridge_optimizer. However, by default LazyBridgeOptimizer uses a limited set of bridges that are:\n\nimplemented in MOI.Bridges\ngenerally applicable for all optimizers.\n\nFor some optimizers however, it is useful to add additional bridges, such as those that are implemented in external packages (for example, within the solver package itself) or only apply in certain circumstances (for example, Constraint.SOCtoNonConvexQuadBridge).\n\nSuch optimizers should implement the ListOfNonstandardBridges attribute to return a vector of bridge types that are added by full_bridge_optimizer in addition to the list of default bridges.\n\nNote that optimizers implementing ListOfNonstandardBridges may require package-specific functions or sets to be used if the non-standard bridges are not added. Therefore, you are recommended to use model = MOI.instantiate(Package.Optimizer; with_bridge_type = T) instead of model = MOI.instantiate(Package.Optimizer). See MOI.instantiate.\n\nExamples\n\nAn optimizer using a non-default bridge in MOI.Bridges\n\nSolvers supporting MOI.ScalarQuadraticFunction can support MOI.SecondOrderCone and MOI.RotatedSecondOrderCone by defining:\n\nfunction MOI.get(::MyQuadraticOptimizer, ::ListOfNonstandardBridges{Float64})\n return Type[\n MOI.Bridges.Constraint.SOCtoNonConvexQuadBridge{Float64},\n MOI.Bridges.Constraint.RSOCtoNonConvexQuadBridge{Float64},\n ]\nend\n\nAn optimizer defining an internal bridge\n\nSuppose an optimizer can exploit specific structure of a constraint, for example, it can exploit the structure of the matrix A in the linear system of equations A * x = b.\n\nThe optimizer can define the function:\n\nstruct MatrixAffineFunction{T} <: MOI.AbstractVectorFunction\n A::SomeStructuredMatrixType{T}\n b::Vector{T}\nend\n\nand then a bridge\n\nstruct MatrixAffineFunctionBridge{T} <: MOI.Constraint.AbstractBridge\n # ...\nend\n# ...\n\nfrom VectorAffineFunction{T} to the MatrixAffineFunction. Finally, it defines:\n\nfunction MOI.get(::Optimizer{T}, ::ListOfNonstandardBridges{T}) where {T}\n return Type[MatrixAffineFunctionBridge{T}]\nend\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.add_bridge","page":"API Reference","title":"MathOptInterface.Bridges.add_bridge","text":"add_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})\n\nEnable the use of the bridges of type BT by b.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.remove_bridge","page":"API Reference","title":"MathOptInterface.Bridges.remove_bridge","text":"remove_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})\n\nDisable the use of the bridges of type BT by b.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.has_bridge","page":"API Reference","title":"MathOptInterface.Bridges.has_bridge","text":"has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})\n\nReturn a Bool indicating whether the bridges of type BT are used by b.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.print_active_bridges","page":"API Reference","title":"MathOptInterface.Bridges.print_active_bridges","text":"print_active_bridges([io::IO=stdout,] b::MOI.Bridges.LazyBridgeOptimizer)\n\nPrint the set of bridges that are active in the model b.\n\n\n\n\n\nprint_active_bridges(\n [io::IO=stdout,]\n b::MOI.Bridges.LazyBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction}\n)\n\nPrint the set of bridges required for an objective function of type F.\n\n\n\n\n\nprint_active_bridges(\n [io::IO=stdout,]\n b::MOI.Bridges.LazyBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet},\n)\n\nPrint the set of bridges required for a constraint of type F-in-S.\n\n\n\n\n\nprint_active_bridges(\n [io::IO=stdout,]\n b::MOI.Bridges.LazyBridgeOptimizer,\n S::Type{<:MOI.AbstractSet}\n)\n\nPrint the set of bridges required for a variable constrained to set S.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.print_graph","page":"API Reference","title":"MathOptInterface.Bridges.print_graph","text":"print_graph([io::IO = stdout,] b::LazyBridgeOptimizer)\n\nPrint the hyper-graph containing all variable, constraint, and objective types that could be obtained by bridging the variables, constraints, and objectives that are present in the model by all the bridges added to b.\n\nEach node in the hyper-graph corresponds to a variable, constraint, or objective type.\n\nVariable nodes are indicated by [ ]\nConstraint nodes are indicated by ( )\nObjective nodes are indicated by | |\n\nThe number inside each pair of brackets is an index of the node in the hyper-graph.\n\nNote that this hyper-graph is the full list of possible transformations. When the bridged model is created, we select the shortest hyper-path from this graph, so many nodes may be un-used.\n\nTo see which nodes are used, call print_active_bridges.\n\nFor more information, see Legat, B., Dowson, O., Garcia, J., and Lubin, M. (2020). \"MathOptInterface: a data structure for mathematical optimization problems.\" URL\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.debug_supports_constraint","page":"API Reference","title":"MathOptInterface.Bridges.debug_supports_constraint","text":"debug_supports_constraint(\n b::LazyBridgeOptimizer,\n F::Type{<:MOI.AbstractFunction},\n S::Type{<:MOI.AbstractSet};\n io::IO = Base.stdout,\n)\n\nPrints to io explanations for the value of MOI.supports_constraint with the same arguments.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.debug_supports","page":"API Reference","title":"MathOptInterface.Bridges.debug_supports","text":"debug_supports(\n b::LazyBridgeOptimizer,\n ::MOI.ObjectiveFunction{F};\n io::IO = Base.stdout,\n) where F\n\nPrints to io explanations for the value of MOI.supports with the same arguments.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#constraint_set_map","page":"API Reference","title":"SetMap API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.map_set\nBridges.inverse_map_set\nBridges.map_function\nBridges.inverse_map_function\nBridges.adjoint_map_function\nBridges.inverse_adjoint_map_function","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.map_set","page":"API Reference","title":"MathOptInterface.Bridges.map_set","text":"map_set(::Type{BT}, set) where {BT}\n\nReturn the image of set through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for bridging the constraint and setting the MOI.ConstraintSet.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.inverse_map_set","page":"API Reference","title":"MathOptInterface.Bridges.inverse_map_set","text":"inverse_map_set(::Type{BT}, set) where {BT}\n\nReturn the preimage of set through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintSet.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.map_function","page":"API Reference","title":"MathOptInterface.Bridges.map_function","text":"map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintPrimal of variable bridges. For constraint bridges, this is used for bridging the constraint, setting the MOI.ConstraintFunction and MOI.ConstraintPrimalStart and modifying the function with MOI.modify.\n\nmap_function(::Type{BT}, func, i::IndexInVector) where {BT}\n\nReturn the scalar function at the ith index of the vector function that would be returned by map_function(BT, func) except that it may compute the ith element. This is used by bridged_function and for getting the MOI.VariablePrimal and MOI.VariablePrimalStart of variable bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.inverse_map_function","page":"API Reference","title":"MathOptInterface.Bridges.inverse_map_function","text":"inverse_map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the inverse of the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used by Variable.unbridged_map and for setting the MOI.VariablePrimalStart of variable bridges and for getting the MOI.ConstraintFunction, the MOI.ConstraintPrimal and the MOI.ConstraintPrimalStart of constraint bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.adjoint_map_function","page":"API Reference","title":"MathOptInterface.Bridges.adjoint_map_function","text":"adjoint_map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the adjoint of the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintDual and MOI.ConstraintDualStart of constraint bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.inverse_adjoint_map_function","page":"API Reference","title":"MathOptInterface.Bridges.inverse_adjoint_map_function","text":"inverse_adjoint_map_function(::Type{BT}, func) where {BT}\n\nReturn the image of func through the inverse of the adjoint of the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintDual of variable bridges and setting the MOI.ConstraintDualStart of constraint bridges.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#Bridging-graph-API","page":"API Reference","title":"Bridging graph API","text":"","category":"section"},{"location":"submodules/Bridges/reference/","page":"API Reference","title":"API Reference","text":"Bridges.Graph\nBridges.VariableNode\nBridges.ConstraintNode\nBridges.ObjectiveNode\nBridges.Edge\nBridges.ObjectiveEdge\nBridges.add_node\nBridges.add_edge\nBridges.set_variable_constraint_node\nBridges.bridge_index\nBridges.is_variable_edge_best","category":"page"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Graph","page":"API Reference","title":"MathOptInterface.Bridges.Graph","text":"Graph()\n\nA type-stable datastructure for computing the shortest hyperpath problem.\n\nNodes\n\nThere are three types of nodes in the graph:\n\nVariableNode\nConstraintNode\nObjectiveNode\n\nAdd nodes to the graph using add_node.\n\nEdges\n\nThere are two types of edges in the graph:\n\nEdge\nObjectiveEdge\n\nAdd edges to the graph using add_edge.\n\nFor the ability to add a variable constrained on creation as a free variable followed by a constraint, use set_variable_constraint_node.\n\nOptimal hyper-edges\n\nUse bridge_index to compute the minimum-cost bridge leaving a node.\n\nNote that bridge_index lazy runs a Bellman-Ford algorithm to compute the set of minimum cost edges. Thus, the first call to bridge_index after adding new nodes or edges will take longer than subsequent calls.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.VariableNode","page":"API Reference","title":"MathOptInterface.Bridges.VariableNode","text":"VariableNode(index::Int)\n\nA node in Graph representing a variable constrained on creation.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ConstraintNode","page":"API Reference","title":"MathOptInterface.Bridges.ConstraintNode","text":"ConstraintNode(index::Int)\n\nA node in Graph representing a constraint.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ObjectiveNode","page":"API Reference","title":"MathOptInterface.Bridges.ObjectiveNode","text":"ObjectiveNode(index::Int)\n\nA node in Graph representing an objective function.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.Edge","page":"API Reference","title":"MathOptInterface.Bridges.Edge","text":"Edge(\n bridge_index::Int,\n added_variables::Vector{VariableNode},\n added_constraints::Vector{ConstraintNode},\n cost::Float64 = 1.0,\n)\n\nReturn a new datastructure representing an edge in Graph that starts at a VariableNode or a ConstraintNode.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.ObjectiveEdge","page":"API Reference","title":"MathOptInterface.Bridges.ObjectiveEdge","text":"ObjectiveEdge(\n bridge_index::Int,\n added_variables::Vector{VariableNode},\n added_constraints::Vector{ConstraintNode},\n)\n\nReturn a new datastructure representing an edge in Graph that starts at an ObjectiveNode.\n\n\n\n\n\n","category":"type"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.add_node","page":"API Reference","title":"MathOptInterface.Bridges.add_node","text":"add_node(graph::Graph, ::Type{VariableNode})::VariableNode\nadd_node(graph::Graph, ::Type{ConstraintNode})::ConstraintNode\nadd_node(graph::Graph, ::Type{ObjectiveNode})::ObjectiveNode\n\nAdd a new node to graph.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.add_edge","page":"API Reference","title":"MathOptInterface.Bridges.add_edge","text":"add_edge(graph::Graph, node::VariableNode, edge::Edge)::Nothing\nadd_edge(graph::Graph, node::ConstraintNode, edge::Edge)::Nothing\nadd_edge(graph::Graph, node::ObjectiveNode, edge::ObjectiveEdge)::Nothing\n\nAdd edge to graph, where edge starts at node and connects to the nodes defined in edge.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.set_variable_constraint_node","page":"API Reference","title":"MathOptInterface.Bridges.set_variable_constraint_node","text":"set_variable_constraint_node(\n graph::Graph,\n variable_node::VariableNode,\n constraint_node::ConstraintNode,\n cost::Int,\n)\n\nAs an alternative to variable_node, add a virtual edge to graph that represents adding a free variable, followed by a constraint of type constraint_node, with bridging cost cost.\n\nWhy is this needed?\n\nVariables can either be added as a variable constrained on creation, or as a free variable which then has a constraint added to it.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.bridge_index","page":"API Reference","title":"MathOptInterface.Bridges.bridge_index","text":"bridge_index(graph::Graph, node::VariableNode)::Int\nbridge_index(graph::Graph, node::ConstraintNode)::Int\nbridge_index(graph::Graph, node::ObjectiveNode)::Int\n\nReturn the optimal index of the bridge to chose from node.\n\n\n\n\n\n","category":"function"},{"location":"submodules/Bridges/reference/#MathOptInterface.Bridges.is_variable_edge_best","page":"API Reference","title":"MathOptInterface.Bridges.is_variable_edge_best","text":"is_variable_edge_best(graph::Graph, node::VariableNode)::Bool\n\nReturn a Bool indicating whether node should be added as a variable constrained on creation, or as a free variable followed by a constraint.\n\n\n\n\n\n","category":"function"},{"location":"#Introduction","page":"Introduction","title":"Introduction","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"Welcome to the documentation for MathOptInterface.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"note: Note\nThis documentation is also available in PDF format: MathOptInterface.pdf.","category":"page"},{"location":"#What-is-MathOptInterface?","page":"Introduction","title":"What is MathOptInterface?","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"MathOptInterface.jl (MOI) is an abstraction layer designed to provide a unified interface to mathematical optimization solvers so that users do not need to understand multiple solver-specific APIs.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"tip: Tip\nThis documentation is aimed at developers writing software interfaces to solvers and modeling languages using the MathOptInterface API. If you are a user interested in solving optimization problems, we encourage you instead to use MOI through a higher-level modeling interface like JuMP or Convex.jl.","category":"page"},{"location":"#How-the-documentation-is-structured","page":"Introduction","title":"How the documentation is structured","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"Having a high-level overview of how this documentation is structured will help you know where to look for certain things.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"The Tutorials section contains articles on how to use and implement the MathOptInteraface API. Look here if you want to write a model in MOI, or write an interface to a new solver.\nThe Manual contains short code-snippets that explain how to use the MOI API. Look here for more details on particular areas of MOI.\nThe Background section contains articles on the theory behind MathOptInterface. Look here if you want to understand why, rather than how.\nThe API Reference contains a complete list of functions and types that comprise the MOI API. Look here is you want to know how to use (or implement) a particular function.\nThe Submodules section contains stand-alone documentation for each of the submodules within MOI. These submodules are not required to interface a solver with MOI, but they make the job much easier.","category":"page"},{"location":"#Citing-MathOptInterface","page":"Introduction","title":"Citing MathOptInterface","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"If you find MathOptInterface useful in your work, we kindly request that you cite the following paper:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"@article{legat2021mathoptinterface,\n title={{MathOptInterface}: a data structure for mathematical optimization problems},\n author={Legat, Beno{\\^\\i}t and Dowson, Oscar and Garcia, Joaquim Dias and Lubin, Miles},\n journal={INFORMS Journal on Computing},\n year={2021},\n doi={10.1287/ijoc.2021.1067},\n publisher={INFORMS}\n}","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"A preprint of this paper is freely available.","category":"page"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"CurrentModule = MathOptInterface\nDocTestSetup = quote\n import MathOptInterface as MOI\nend\nDocTestFilters = [r\"MathOptInterface|MOI\"]","category":"page"},{"location":"background/naming_conventions/#Naming-conventions","page":"Naming conventions","title":"Naming conventions","text":"","category":"section"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"MOI follows several conventions for naming functions and structures. These should also be followed by packages extending MOI.","category":"page"},{"location":"background/naming_conventions/#Sets","page":"Naming conventions","title":"Sets","text":"","category":"section"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"Sets encode the structure of constraints. Their names should follow the following conventions:","category":"page"},{"location":"background/naming_conventions/","page":"Naming conventions","title":"Naming conventions","text":"Abstract types in the set hierarchy should begin with Abstract and end in Set, for example, AbstractScalarSet, AbstractVectorSet.\nVector-valued conic sets should end with Cone, for example, NormInfinityCone, SecondOrderCone.\nVector-valued Cartesian products should be plural and not end in Cone, for example, Nonnegatives, not NonnegativeCone.\nMatrix-valued conic sets should provide two representations: ConeSquare and ConeTriangle, for example, RootDetConeTriangle and RootDetConeSquare. See Matrix cones for more details.\nScalar sets should be singular, not plural, for example, Integer, not Integers.\nAs much as possible, the names should follow established conventions in the domain where this set is used: for instance, convex sets should have names close to those of CVX, and constraint-programming sets should follow MiniZinc's constraints.","category":"page"}] +} diff --git a/previews/PR2418/siteinfo.js b/previews/PR2418/siteinfo.js new file mode 100644 index 0000000000..30690aaed7 --- /dev/null +++ b/previews/PR2418/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "previews/PR2418"; diff --git a/previews/PR2418/submodules/Benchmarks/overview/index.html b/previews/PR2418/submodules/Benchmarks/overview/index.html new file mode 100644 index 0000000000..939754199f --- /dev/null +++ b/previews/PR2418/submodules/Benchmarks/overview/index.html @@ -0,0 +1,20 @@ + +Overview · MathOptInterface

The Benchmarks submodule

To aid the development of efficient solver wrappers, MathOptInterface provides benchmarking capability. Benchmarking a wrapper follows a two-step process.

First, prior to making changes, create a baseline for the benchmark results on a given benchmark suite as follows:

using SolverPackage  # Replace with your choice of solver.
+import MathOptInterface as MOI
+
+suite = MOI.Benchmarks.suite() do
+    SolverPackage.Optimizer()
+end
+
+MOI.Benchmarks.create_baseline(
+    suite, "current"; directory = "/tmp", verbose = true
+)

Use the exclude argument to Benchmarks.suite to exclude benchmarks that the solver doesn't support.

Second, after making changes to the package, re-run the benchmark suite and compare to the prior saved results:

using SolverPackage
+import MathOptInterface as MOI
+
+suite = MOI.Benchmarks.suite() do
+    SolverPackage.Optimizer()
+end
+
+MOI.Benchmarks.compare_against_baseline(
+    suite, "current"; directory = "/tmp", verbose = true
+)

This comparison will create a report detailing improvements and regressions.

diff --git a/previews/PR2418/submodules/Benchmarks/reference/index.html b/previews/PR2418/submodules/Benchmarks/reference/index.html new file mode 100644 index 0000000000..d5dc10a535 --- /dev/null +++ b/previews/PR2418/submodules/Benchmarks/reference/index.html @@ -0,0 +1,17 @@ + +API Reference · MathOptInterface

Benchmarks

Functions to help benchmark the performance of solver wrappers. See The Benchmarks submodule for more details.

MathOptInterface.Benchmarks.suiteFunction
suite(
+    new_model::Function;
+    exclude::Vector{Regex} = Regex[]
+)

Create a suite of benchmarks. new_model should be a function that takes no arguments, and returns a new instance of the optimizer you wish to benchmark.

Use exclude to exclude a subset of benchmarks.

Examples

suite() do
+    GLPK.Optimizer()
+end
+suite(exclude = [r"delete"]) do
+    Gurobi.Optimizer(OutputFlag=0)
+end
source
MathOptInterface.Benchmarks.create_baselineFunction
create_baseline(suite, name::String; directory::String = ""; kwargs...)

Run all benchmarks in suite and save to files called name in directory.

Extra kwargs are based to BenchmarkTools.run.

Examples

my_suite = suite(() -> GLPK.Optimizer())
+create_baseline(my_suite, "glpk_master"; directory = "/tmp", verbose = true)
source
MathOptInterface.Benchmarks.compare_against_baselineFunction
compare_against_baseline(
+    suite, name::String; directory::String = "",
+    report_filename::String = "report.txt"
+)

Run all benchmarks in suite and compare against files called name in directory that were created by a call to create_baseline.

A report summarizing the comparison is written to report_filename in directory.

Extra kwargs are based to BenchmarkTools.run.

Examples

my_suite = suite(() -> GLPK.Optimizer())
+compare_against_baseline(
+    my_suite, "glpk_master"; directory = "/tmp", verbose = true
+)
source
diff --git a/previews/PR2418/submodules/Bridges/implementation/index.html b/previews/PR2418/submodules/Bridges/implementation/index.html new file mode 100644 index 0000000000..e81664c3d8 --- /dev/null +++ b/previews/PR2418/submodules/Bridges/implementation/index.html @@ -0,0 +1,32 @@ + +Implementation · MathOptInterface

Implementing a bridge

The easiest way to implement a bridge is to follow an existing example. There are three locations of bridges in the source code:

  • Constraint bridges are stored in src/Bridges/Constraint/bridges
  • Objective bridges are stored in src/Bridges/Objective/bridges
  • Variable bridges are stored in src/Bridges/Variable/bridges

The Implementing a constraint bridge tutorial has a more detailed guide on what is required to implement a bridge.

When opening a pull request that adds a new bridge, use the checklist Adding a new bridge.

If you need help or advice, please contact the Developer Chatroom.

SetMap bridges

For constraint and variable bridges, a common reformulation is that $f(x) \in F$ is reformulated to $g(x) \in G$. In this case, no additional variables and constraints are added, and the bridge needs only a way to map between the functions f and g and the sets F and G.

To implementation a bridge of this form, subtype the abstract type Bridges.Constraint.SetMapBridge or Bridges.Variable.SetMapBridge and implement the API described in the docstring of each type.

final_touch

Some bridges require information from other parts of the model. One set of examples are the various combinatorial ToMILP bridges, such as Bridges.Constraint.SOS1ToMILPBridge, which require knowledge of the variable bounds.

Bridges requiring information from other parts of the model should implement Bridges.final_touch and Bridges.needs_final_touch.

During the bridge's construction, store the function and set and make no changes to the underlying model. Then, in Bridges.final_touch, query the additional information and add the reformulated problem to the model.

When implementing, you must consider that:

  • Bridges.final_touch may be called multiple times, so that your reformulation should be applied only if necessary. Sometimes the additional data will be the same, and sometimes it may be different.
  • We do not currently support final_touch bridges that introduce constraints which also require a final_touch bridge. Therefore, you should implement final_touch only if necessary, and we recommend that you contact the Developer Chatroom for advice before doing so.

Testing

Use the Bridges.runtests function to test a bridge. It takes three arguments: the type of the bridge, the input model as a string, and the output model as a string.

Here is an example:

julia> MOI.Bridges.runtests(
+           MOI.Bridges.Constraint.GreaterToLessBridge,
+           """
+           variables: x
+           x >= 1.0
+           """,
+           """
+           variables: x
+           -1.0 * x <= -1.0
+           """,
+       )

There are a number of other useful keyword arguments.

  • eltype can be used to specify the element type of the model (and bridge). It defaults to Float64.
  • variable_start and constraint_start are used as the values to set the VariablePrimalStart and ConstraintPrimalStart attributes to. They default to 1.2. If you use a different eltype, you must set appropriate starting values of the same type. The default 1.2 was chosen to minimize the risk that the starting point is undefined, which could happen for common situations like 0.0 and 1.0. The tests associated with the starting values do not necessarily check for correctness, only that they can be set and get to produce the same result.
  • print_inner_model can be used to print the reformulated output model from the bridge. This is especially helpful during debugging to see what the bridge is doing, and to spot mistakes. It defaults to false.

Here is an example:

julia> MOI.Bridges.runtests(
+           MOI.Bridges.Constraint.GreaterToLessBridge,
+           """
+           variables: x
+           x >= 1
+           """,
+           """
+           variables: x
+           ::Int: -1 * x <= -1
+           """;
+           eltype = Int,
+           print_inner_model = true,
+           variable_start = 2,
+           constraint_start = 2,
+       )
+Feasibility
+
+Subject to:
+
+ScalarAffineFunction{Int64}-in-LessThan{Int64}
+ (0) - (1) x <= (-1)
diff --git a/previews/PR2418/submodules/Bridges/list_of_bridges/index.html b/previews/PR2418/submodules/Bridges/list_of_bridges/index.html new file mode 100644 index 0000000000..c516f1df97 --- /dev/null +++ b/previews/PR2418/submodules/Bridges/list_of_bridges/index.html @@ -0,0 +1,110 @@ + +List of bridges · MathOptInterface

List of bridges

This section describes the Bridges.AbstractBridges that are implemented in MathOptInterface.

Constraint bridges

These bridges are subtypes of Bridges.Constraint.AbstractBridge.

MathOptInterface.Bridges.Constraint.VectorizeBridgeType
VectorizeBridge{T,F,S,G} <: Bridges.Constraint.AbstractBridge

VectorizeBridge implements the following reformulations:

  • $g(x) \ge a$ into $[g(x) - a] \in \mathbb{R}_+$
  • $g(x) \le a$ into $[g(x) - a] \in \mathbb{R}_-$
  • $g(x) == a$ into $[g(x) - a] \in \{0\}$

where T is the coefficient type of g(x) - a.

Source node

VectorizeBridge supports:

Target nodes

VectorizeBridge creates:

source
MathOptInterface.Bridges.Constraint.ScalarizeBridgeType
ScalarizeBridge{T,F,S}

ScalarizeBridge implements the following reformulations:

  • $f(x) - a \in \mathbb{R}_+$ into $f_i(x) \ge a_i$ for all $i$
  • $f(x) - a \in \mathbb{R}_-$ into $f_i(x) \le a_i$ for all $i$
  • $f(x) - a \in \{0\}$ into $f_i(x) == a_i$ for all $i$

Source node

ScalarizeBridge supports:

Target nodes

ScalarizeBridge creates:

source
MathOptInterface.Bridges.Constraint.FunctionConversionBridgeType
FunctionConversionBridge{T,F,G,S} <: AbstractFunctionConversionBridge{G,S}

FunctionConversionBridge implements the following reformulations:

  • $g(x) \in S$ into $f(x) \in S$

for these pairs of functions:

Source node

FunctionConversionBridge supports:

  • G in S

Target nodes

FunctionConversionBridge creates:

  • F in S
source
MathOptInterface.Bridges.Constraint.SplitComplexEqualToBridgeType
SplitComplexEqualToBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

SplitComplexEqualToBridge implements the following reformulation:

  • $f(x) + g(x) * im = a + b * im$ into $f(x) = a$ and $g(x) = b$

Source node

SplitComplexEqualToBridge supports:

where G is a function with Complex coefficients.

Target nodes

SplitComplexEqualToBridge creates:

where F is the type of the real/imaginary part of G.

source
MathOptInterface.Bridges.Constraint.SplitComplexZerosBridgeType
SplitComplexZerosBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

SplitComplexZerosBridge implements the following reformulation:

  • $f(x) \in \{0\}^n$ into $\text{Re}(f(x)) \in \{0\}^n$ and $\text{Im}(f(x)) \in \{0\}^n$

Source node

SplitComplexZerosBridge supports:

where G is a function with Complex coefficients.

Target nodes

SplitComplexZerosBridge creates:

where F is the type of the real/imaginary part of G.

source
MathOptInterface.Bridges.Constraint.SplitIntervalBridgeType
SplitIntervalBridge{T,F,S,LS,US} <: Bridges.Constraint.AbstractBridge

SplitIntervalBridge implements the following reformulations:

  • $l \le f(x) \le u$ into $f(x) \ge l$ and $f(x) \le u$
  • $f(x) = b$ into $f(x) \ge b$ and $f(x) \le b$
  • $f(x) \in \{0\}$ into $f(x) \in \mathbb{R}_+$ and $f(x) \in \mathbb{R}_-$

Source node

SplitIntervalBridge supports:

Target nodes

SplitIntervalBridge creates:

or

Note

If T<:AbstractFloat and S is MOI.Interval{T} then no lower (resp. upper) bound constraint is created if the lower (resp. upper) bound is typemin(T) (resp. typemax(T)). Similarly, when MOI.ConstraintSet is set, a lower or upper bound constraint may be deleted or created accordingly.

source
MathOptInterface.Bridges.Constraint.SOCtoNonConvexQuadBridgeType
SOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge

SOCtoNonConvexQuadBridge implements the following reformulations:

  • $||x||_2 \le t$ into $\sum x^2 - t^2 \le 0$ and $1t + 0 \ge 0$

The MOI.ScalarAffineFunction $1t + 0$ is used in case the variable has other bound constraints.

Warning

This transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.

Source node

SOCtoNonConvexQuadBridge supports:

Target nodes

SOCtoNonConvexQuadBridge creates:

source
MathOptInterface.Bridges.Constraint.RSOCtoNonConvexQuadBridgeType
RSOCtoNonConvexQuadBridge{T} <: Bridges.Constraint.AbstractBridge

RSOCtoNonConvexQuadBridge implements the following reformulations:

  • $||x||_2^2 \le 2tu$ into $\sum x^2 - 2tu \le 0$, $1t + 0 \ge 0$, and $1u + 0 \ge 0$.

The MOI.ScalarAffineFunctions $1t + 0$ and $1u + 0$ are used in case the variables have other bound constraints.

Warning

This transformation starts from a convex constraint and creates a non-convex constraint. Unless the solver has explicit support for detecting rotated second-order cones in quadratic form, this may (wrongly) be interpreted by the solver as being non-convex. Therefore, this bridge is not added automatically by MOI.Bridges.full_bridge_optimizer. Care is recommended when adding this bridge to a optimizer.

Source node

RSOCtoNonConvexQuadBridge supports:

Target nodes

RSOCtoNonConvexQuadBridge creates:

source
MathOptInterface.Bridges.Constraint.QuadtoSOCBridgeType
QuadtoSOCBridge{T} <: Bridges.Constraint.AbstractBridge

QuadtoSOCBridge converts quadratic inequalities

\[\frac{1}{2}x^T Q x + a^T x \le ub\]

into MOI.RotatedSecondOrderCone constraints, but it only applies when $Q$ is positive definite.

This is because, if Q is positive definite, there exists U such that $Q = U^T U$, and so the inequality can then be rewritten as;

\[\|U x\|_2^2 \le 2 (-a^T x + ub)\]

Therefore, QuadtoSOCBridge implements the following reformulations:

  • $\frac{1}{2}x^T Q x + a^T x \le ub$ into $(1, -a^T x + ub, Ux) \in RotatedSecondOrderCone$ where $Q = U^T U$
  • $\frac{1}{2}x^T Q x + a^T x \ge lb$ into $(1, a^T x - lb, Ux) \in RotatedSecondOrderCone$ where $-Q = U^T U$

Source node

QuadtoSOCBridge supports:

Target nodes

RelativeEntropyBridge creates:

Errors

This bridge errors if Q is not positive definite.

source
MathOptInterface.Bridges.Constraint.SOCtoPSDBridgeType
SOCtoPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

SOCtoPSDBridge implements the following reformulation:

  • $||x||_2 \le t$ into $\left[\begin{array}{c c}t & x^\top \\ x & t \mathbf{I}\end{array}\right]\succeq 0$
Warning

This bridge is not added by default by MOI.Bridges.full_bridge_optimizer because bridging second order cone constraints to semidefinite constraints can be achieved by the SOCtoRSOCBridge followed by the RSOCtoPSDBridge, while creating a smaller semidefinite constraint.

Source node

SOCtoPSDBridge supports:

Target nodes

SOCtoPSDBridge creates:

source
MathOptInterface.Bridges.Constraint.NormToPowerBridgeType
NormToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge

NormToPowerBridge implements the following reformulation:

  • $(t, x) \in NormCone(p, 1+d)$ into $(r_i, t, x_i) \in PowerCone(1 / p)$ for all $i$, and $\sum\limits_i r_i == t$.

For details, see Alizadeh, F., and Goldfarb, D. (2001). "Second-order cone programming." Mathematical Programming, Series B, 95:3-51.

Source node

NormToPowerBridge supports:

Target nodes

NormToPowerBridge creates:

source
MathOptInterface.Bridges.Constraint.GeoMeantoRelEntrBridgeType
GeoMeantoRelEntrBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

GeoMeantoRelEntrBridge implements the following reformulation:

  • $(u, w) \in GeometricMeanCone$ into $(0, w, (u + y)\mathbf{1})\in RelativeEntropyCone$ and $y \ge 0$

Source node

GeoMeantoRelEntrBridge supports:

Target nodes

GeoMeantoRelEntrBridge creates:

Derivation

The derivation of the bridge is as follows:

\[\begin{aligned} +(u, w) \in GeometricMeanCone \iff & u \le \left(\prod_{i=1}^n w_i\right)^{1/n} \\ +\iff & 0 \le u + y \le \left(\prod_{i=1}^n w_i\right)^{1/n}, y \ge 0 \\ +\iff & 1 \le \frac{\left(\prod_{i=1}^n w_i\right)^{1/n}}{u + y}, y \ge 0 \\ +\iff & 1 \le \left(\prod_{i=1}^n \frac{w_i}{u + y}\right)^{1/n}, y \ge 0 \\ +\iff & 0 \le \sum_{i=1}^n \log\left(\frac{w_i}{u + y}\right), y \ge 0 \\ +\iff & 0 \ge \sum_{i=1}^n \log\left(\frac{u + y}{w_i}\right), y \ge 0 \\ +\iff & 0 \ge \sum_{i=1}^n (u + y) \log\left(\frac{u + y}{w_i}\right), y \ge 0 \\ +\iff & (0, w, (u + y)\mathbf{1}) \in RelativeEntropyCone, y \ge 0 \\ +\end{aligned}\]

This derivation assumes that $u + y > 0$, which is enforced by the relative entropy cone.

source
MathOptInterface.Bridges.Constraint.GeoMeanToPowerBridgeType
GeoMeanToPowerBridge{T,F} <: Bridges.Constraint.AbstractBridge

GeoMeanToPowerBridge implements the following reformulation:

  • $(y, x...) \in GeometricMeanCone(1+d)$ into $(x_1, t, y) \in PowerCone(1/d)$ and $(t, x_2, ..., x_d) in GeometricMeanCone(d)$, which is then recursively expanded into more PowerCone constraints.

Source node

GeoMeanToPowerBridge supports:

Target nodes

GeoMeanToPowerBridge creates:

source
MathOptInterface.Bridges.Constraint.GeoMeanBridgeType
GeoMeanBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

GeoMeanBridge implements a reformulation from MOI.GeometricMeanCone into MOI.RotatedSecondOrderCone.

The reformulation is best described in an example.

Consider the cone of dimension 4:

\[t \le \sqrt[3]{x_1 x_2 x_3}\]

This can be rewritten as $\exists y \ge 0$ such that:

\[\begin{align*} + t & \le y,\\ + y^4 & \le x_1 x_2 x_3 y. +\end{align*}\]

Note that we need to create $y$ and not use $t^4$ directly because $t$ is not allowed to be negative.

This is equivalent to:

\[\begin{align*} + t & \le \frac{y_1}{\sqrt{4}},\\ + y_1^2 & \le 2y_2 y_3,\\ + y_2^2 & \le 2x_1 x_2, \\ + y_3^2 & \le 2x_3(y_1/\sqrt{4}) \\ + y & \ge 0. +\end{align*}\]

More generally, you can show how the geometric mean code is recursively expanded into a set of new variables $y$ in MOI.Nonnegatives, a set of MOI.RotatedSecondOrderCone constraints, and a MOI.LessThan constraint between $t$ and $y_1$.

Source node

GeoMeanBridge supports:

Target nodes

GeoMeanBridge creates:

source
MathOptInterface.Bridges.Constraint.RelativeEntropyBridgeType
RelativeEntropyBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

RelativeEntropyBridge implements the following reformulation that converts a MOI.RelativeEntropyCone into an MOI.ExponentialCone:

  • $u \ge \sum_{i=1}^n w_i \log \left(\frac{w_i}{v_i}\right)$ into $y_i \ge 0$, $u \ge \sum_{i=1}^n y_i$, and $(-y_i, w_i, v_i) \in ExponentialCone$.

Source node

RelativeEntropyBridge supports:

Target nodes

RelativeEntropyBridge creates:

source
MathOptInterface.Bridges.Constraint.SquareBridgeType
SquareBridge{T,F,G,TT,ST} <: Bridges.Constraint.AbstractBridge

SquareBridge implements the following reformulations:

  • $(t, u, X) \in LogDetConeSquare$ into $(t, u, Y) in LogDetConeTriangle$
  • $(t, X) \in RootDetConeSquare$ into $(t, Y) in RootDetConeTriangle$
  • $X \in AbstractSymmetricMatrixSetSquare$ into $Y in AbstractSymmetricMatrixSetTriangle$

where $Y$ is the upper triangluar component of $X$.

In addition, constraints are added as necessary to constrain the matrix $X$ to be symmetric. For example, the constraint for the matrix:

\[\begin{pmatrix} + 1 & 1 + x & 2 - 3x\\ + 1 + x & 2 + x & 3 - x\\ + 2 - 3x & 2 + x & 2x +\end{pmatrix}\]

can be broken down to the constraint of the symmetric matrix

\[\begin{pmatrix} + 1 & 1 + x & 2 - 3x\\ + \cdot & 2 + x & 3 - x\\ + \cdot & \cdot & 2x +\end{pmatrix}\]

and the equality constraint between the off-diagonal entries (2, 3) and (3, 2) $3 - x == 2 + x$. Note that no symmetrization constraint needs to be added between the off-diagonal entries (1, 2) and (2, 1) or between (1, 3) and (3, 1) because the expressions are the same.

Source node

SquareBridge supports:

  • F in ST

Target nodes

SquareBridge creates:

  • G in TT
source
MathOptInterface.Bridges.Constraint.HermitianToSymmetricPSDBridgeType
HermitianToSymmetricPSDBridge{T,F,G} <: Bridges.Constraint.AbstractBridge

HermitianToSymmetricPSDBridge implements the following reformulation:

  • Hermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix.

See also MOI.Bridges.Variable.HermitianToSymmetricPSDBridge.

Source node

HermitianToSymmetricPSDBridge supports:

Target node

HermitianToSymmetricPSDBridge creates:

Reformulation

The reformulation is best described by example.

The Hermitian matrix:

\[\begin{bmatrix} + x_{11} & x_{12} + y_{12}im & x_{13} + y_{13}im\\ + x_{12} - y_{12}im & x_{22} & x_{23} + y_{23}im\\ + x_{13} - y_{13}im & x_{23} - y_{23}im & x_{33} +\end{bmatrix}\]

is positive semidefinite if and only if the symmetric matrix:

\[\begin{bmatrix} + x_{11} & x_{12} & x_{13} & 0 & y_{12} & y_{13} \\ + & x_{22} & x_{23} & -y_{12} & 0 & y_{23} \\ + & & x_{33} & -y_{13} & -y_{23} & 0 \\ + & & & x_{11} & x_{12} & x_{13} \\ + & & & & x_{22} & x_{23} \\ + & & & & & x_{33} +\end{bmatrix}\]

is positive semidefinite.

The bridge achieves this reformulation by constraining the above matrix to belong to the MOI.PositiveSemidefiniteConeTriangle(6).

source
MathOptInterface.Bridges.Constraint.RootDetBridgeType
RootDetBridge{T,F,G,H} <: Bridges.Constraint.AbstractBridge

The MOI.RootDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.GeometricMeanCone constraints, see [1, p. 149].

Indeed, $t \le \det(X)^{1/n}$ if and only if there exists a lower triangular matrix $Δ$ such that:

\[\begin{align*} + \begin{pmatrix} + X & Δ\\ + Δ^\top & \mathrm{Diag}(Δ) + \end{pmatrix} & \succeq 0\\ + (t, \mathrm{Diag}(Δ)) & \in GeometricMeanCone +\end{align*}\]

Source node

RootDetBridge supports:

Target nodes

RootDetBridge creates:

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.LogDetBridgeType
LogDetBridge{T,F,G,H,I} <: Bridges.Constraint.AbstractBridge

The MOI.LogDetConeTriangle is representable by MOI.PositiveSemidefiniteConeTriangle and MOI.ExponentialCone constraints.

Indeed, $\log\det(X) = \sum\limits_{i=1}^n \log(\delta_i)$ where $\delta_i$ are the eigenvalues of $X$.

Adapting the method from [1, p. 149], we see that $t \le u \log(\det(X/u))$ for $u > 0$ if and only if there exists a lower triangular matrix $Δ$ such that

\[\begin{align*} + \begin{pmatrix} + X & Δ\\ + Δ^\top & \mathrm{Diag}(Δ) + \end{pmatrix} & \succeq 0\\ + t - \sum_{i=1}^n u \log\left(\frac{Δ_{ii}}{u}\right) & \le 0 +\end{align*}\]

Which we reformulate further into

\[\begin{align*} + \begin{pmatrix} + X & Δ\\ + Δ^\top & \mathrm{Diag}(Δ) + \end{pmatrix} & \succeq 0\\ + (l_i, u , Δ_{ii}) & \in ExponentialCone\quad \forall i \\ + t - \sum_{i=1}^n l_i & \le 0 +\end{align*}\]

Source node

LogDetBridge supports:

Target nodes

LogDetBridge creates:

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridgeType
IndicatorActiveOnFalseBridge{T,F,S} <: Bridges.Constraint.AbstractBridge

IndicatorActiveOnFalseBridge implements the following reformulation:

  • $\neg z \implies {f(x) \in S}$ into $y \implies {f(x) \in S}$, $z + y = 1$, and $y \in \{0, 1\}$

Source node

IndicatorActiveOnFalseBridge supports:

Target nodes

IndicatorActiveOnFalseBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorGreaterToLessThanBridgeType
IndicatorGreaterToLessThanBridge{T,A} <: Bridges.Constraint.AbstractBridge

IndicatorGreaterToLessThanBridge implements the following reformulation:

  • $z \implies {f(x) \ge l}$ into $z \implies {-f(x) \le -l}$

Source node

IndicatorGreaterToLessThanBridge supports:

Target nodes

IndicatorGreaterToLessThanBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorLessToGreaterThanBridgeType
IndicatorLessToGreaterThanBridge{T,A} <: Bridges.Constraint.AbstractBridge

IndicatorLessToGreaterThanBridge implements the following reformulations:

  • $z \implies {f(x) \le u}$ into $z \implies {-f(x) \ge -u}$

Source node

IndicatorLessToGreaterThanBridge supports:

Target nodes

IndicatorLessToGreaterThanBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorSOS1BridgeType
IndicatorSOS1Bridge{T,S} <: Bridges.Constraint.AbstractBridge

IndicatorSOS1Bridge implements the following reformulation:

  • $z \implies {f(x) \in S}$ into $f(x) + y \in S$, $SOS1(y, z)$
Warning

This bridge assumes that the solver supports MOI.SOS1{T} constraints in which one of the variables ($y$) is continuous.

Source node

IndicatorSOS1Bridge supports:

Target nodes

IndicatorSOS1Bridge creates:

source
MathOptInterface.Bridges.Constraint.SemiToBinaryBridgeType
SemiToBinaryBridge{T,S} <: Bridges.Constraint.AbstractBridge

SemiToBinaryBridge implements the following reformulations:

  • $x \in \{0\} \cup [l, u]$ into

    \[\begin{aligned} +x \leq z u \\ +x \geq z l \\ +z \in \{0, 1\} +\end{aligned}\]

  • $x \in \{0\} \cup \{l, \ldots, u\}$ into

    \[\begin{aligned} +x \leq z u \\ +x \geq z l \\ +z \in \{0, 1\} \\ +x \in \mathbb{Z} +\end{aligned}\]

Source node

SemiToBinaryBridge supports:

Target nodes

SemiToBinaryBridge creates:

source
MathOptInterface.Bridges.Constraint.ZeroOneBridgeType
ZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge

ZeroOneBridge implements the following reformulation:

  • $x \in \{0, 1\}$ into $x \in \mathbb{Z}$, $1x \in [0, 1]$.
Note

ZeroOneBridge adds a linear constraint instead of adding variable bounds to avoid conflicting with bounds set by the user.

Source node

ZeroOneBridge supports:

Target nodes

ZeroOneBridge creates:

source
MathOptInterface.Bridges.Constraint.IntegerToZeroOneBridgeType
IntegerToZeroOneBridge{T} <: Bridges.Constraint.AbstractBridge

IntegerToZeroOneBridge implements the following reformulation:

  • $x \in \mathbf{Z}$ into $y_i \in \{0, 1\}$, $x == lb + \sum 2^{i-1} y_i$.

Source node

IntegerToZeroOneBridge supports:

Target nodes

IntegerToZeroOneBridge creates:

Developer note

This bridge is implemented as a constraint bridge instead of a variable bridge because we don't want to substitute the linear combination of y for every instance of x. Doing so would be expensive and greatly reduce the sparsity of the constraints.

source
MathOptInterface.Bridges.Constraint.NumberConversionBridgeType
NumberConversionBridge{T,F1,S1,F2,S2} <: Bridges.Constraint.AbstractBridge

NumberConversionBridge implements the following reformulation:

  • $f1(x) \in S1$ to $f2(x) \in S2$

where f and S are the same functional form, but differ in their coefficient type.

Source node

NumberConversionBridge supports:

  • F1 in S1

Target node

NumberConversionBridge creates:

  • F2 in S2
source
MathOptInterface.Bridges.Constraint.AllDifferentToCountDistinctBridgeType
AllDifferentToCountDistinctBridge{T,F} <: Bridges.Constraint.AbstractBridge

AllDifferentToCountDistinctBridge implements the following reformulations:

  • $x \in \textsf{AllDifferent}(d)$ to $(n, x) \in \textsf{CountDistinct}(1+d)$ and $n = d$
  • $f(x) \in \textsf{AllDifferent}(d)$ to $(d, f(x)) \in \textsf{CountDistinct}(1+d)$

Source node

AllDifferentToCountDistinctBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

AllDifferentToCountDistinctBridge creates:

source
MathOptInterface.Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridgeType
ReifiedAllDifferentToCountDistinctBridge{T,F} <:
+Bridges.Constraint.AbstractBridge

ReifiedAllDifferentToCountDistinctBridge implements the following reformulations:

  • $r \iff x \in \textsf{AllDifferent}(d)$ to $r \iff (n, x) \in \textsf{CountDistinct}(1+d)$ and $n = d$
  • $r \iff f(x) \in \textsf{AllDifferent}(d)$ to $r \iff (d, f(x)) \in \textsf{CountDistinct}(1+d)$

Source node

ReifiedAllDifferentToCountDistinctBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

ReifiedAllDifferentToCountDistinctBridge creates:

source
MathOptInterface.Bridges.Constraint.BinPackingToMILPBridgeType
BinPackingToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

BinPackingToMILPBridge implements the following reformulation:

  • $x \in BinPacking(c, w)$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Then, we add the capacity constraint for all possible bins $j$:

\[\sum\limits_{i} w_i z_{ij} \le c \forall j \in \bigcup_{i=1,\ldots,d} S_i\]

Source node

BinPackingToMILPBridge supports:

Target nodes

BinPackingToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CircuitToMILPBridgeType
CircuitToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CircuitToMILPBridge implements the following reformulation:

  • $x \in \textsf{Circuit}(d)$ to the Miller-Tucker-Zemlin formulation of the Traveling Salesperson Problem.

Source node

CircuitToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CircuitToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CountAtLeastToCountBelongsBridgeType
CountAtLeastToCountBelongsBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountAtLeastToCountBelongsBridge implements the following reformulation:

  • $x \in \textsf{CountAtLeast}(n, d, \mathcal{S})$ to $(n_i, x_{d_i}) \in \textsf{CountBelongs}(1+d, \mathcal{S})$ and $n_i \ge n$ for all $i$.

Source node

CountAtLeastToCountBelongsBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CountAtLeastToCountBelongsBridge creates:

source
MathOptInterface.Bridges.Constraint.CountBelongsToMILPBridgeType
CountBelongsToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountBelongsToMILPBridge implements the following reformulation:

  • $(n, x) \in \textsf{CountBelongs}(1+d, \mathcal{S})$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Finally, $n$ is constrained to be the number of $z_{ij}$ elements that are in $\mathcal{S}$:

\[n - \sum\limits_{i\in 1\ldots d, j \in \mathcal{S}} z_{ij} = 0\]

Source node

CountBelongsToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CountBelongsToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CountDistinctToMILPBridgeType
CountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountDistinctToMILPBridge implements the following reformulation:

  • $(n, x) \in \textsf{CountDistinct}(1+d)$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Then, we introduce new binary variables $y_j$, which are $1$ if a variable takes the value $j$ in the optimal solution and $0$ otherwise.

\[\begin{aligned} +y_{j} \in \{0, 1\} & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i \\ +y_j \le \sum\limits_{i \in 1\ldots d: j \in S_i} z_{ij} \le M y_j & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i\\ +\end{aligned}\]

Finally, $n$ is constrained to be the number of $y_j$ elements that are non-zero:

\[n - \sum\limits_{j \in \bigcup_{i=1,\ldots,d} S_i} y_{j} = 0\]

Source node

CountDistinctToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

CountDistinctToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.ReifiedCountDistinctToMILPBridgeType
ReifiedCountDistinctToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

ReifiedCountDistinctToMILPBridge implements the following reformulation:

  • $r \iff (n, x) \in \textsf{CountDistinct}(1+d)$ into a mixed-integer linear program.

Reformulation

The reformulation is non-trivial, and it depends on the finite domain of each variable $x_i$, which we as define $S_i = \{l_i,\ldots,u_i\}$.

First, we introduce new binary variables $z_{ij}$, which are $1$ if variable $x_i$ takes the value $j$ in the optimal solution and $0$ otherwise:

\[\begin{aligned} +z_{ij} \in \{0, 1\} & \;\; \forall i \in 1\ldots d, j \in S_i \\ +x_i - \sum\limits_{j\in S_i} j \cdot z_{ij} = 0 & \;\; \forall i \in 1\ldots d \\ +\sum\limits_{j\in S_i} z_{ij} = 1 & \;\; \forall i \in 1\ldots d \\ +\end{aligned}\]

Then, we introduce new binary variables $y_j$, which are $1$ if a variable takes the value $j$ in the optimal solution and $0$ otherwise.

\[\begin{aligned} +y_{j} \in \{0, 1\} & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i \\ +y_j \le \sum\limits_{i \in 1\ldots d: j \in S_i} z_{ij} \le M y_j & \;\; \forall j \in \bigcup_{i=1,\ldots,d} S_i\\ +\end{aligned}\]

Finally, $n$ is constrained to be the number of $y_j$ elements that are non-zero, with some slack:

\[n - \sum\limits_{j \in \bigcup_{i=1,\ldots,d} S_i} y_{j} = \delta^+ - \delta^-\]

And then the slack is constrained to respect the reif variable $r$:

\[\begin{aligned} +d_1 \le \delta^+ \le M d_1 \\ +d_2 \le \delta^- \le M d_s \\ +d_1 + d_2 + r = 1 \\ +d_1, d_2 \in \{0, 1\} +\end{aligned}\]

Source node

ReifiedCountDistinctToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

ReifiedCountDistinctToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.CountGreaterThanToMILPBridgeType
CountGreaterThanToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

CountGreaterThanToMILPBridge implements the following reformulation:

  • $(c, y, x) \in CountGreaterThan()$ into a mixed-integer linear program.

Source node

CountGreaterThanToMILPBridge supports:

Target nodes

CountGreaterThanToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.TableToMILPBridgeType
TableToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

TableToMILPBridge implements the following reformulation:

  • $x \in Table(t)$ into

    \[\begin{aligned} +z_{j} \in \{0, 1\} & \quad \forall i, j \\ +\sum\limits_{j=1}^n z_{j} = 1 \\ +\sum\limits_{j=1}^n t_{ij} z_{j} = x_i & \quad \forall i +\end{aligned}\]

Source node

TableToMILPBridge supports:

Target nodes

TableToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.SOS1ToMILPBridgeType
SOS1ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

SOS1ToMILPBridge implements the following reformulation:

  • $x \in \textsf{SOS1}(d)$ into a mixed-integer linear program.

Source node

SOS1ToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

SOS1ToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.SOS2ToMILPBridgeType
SOS2ToMILPBridge{T,F} <: Bridges.Constraint.AbstractBridge

SOS2ToMILPBridge implements the following reformulation:

  • $x \in \textsf{SOS2}(d)$ into a mixed-integer linear program.

Source node

SOS2ToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

SOS2ToMILPBridge creates:

source
MathOptInterface.Bridges.Constraint.IndicatorToMILPBridgeType
IndicatorToMILPBridge{T,F,A,S} <: Bridges.Constraint.AbstractBridge

IndicatorToMILPBridge implements the following reformulation:

  • $x \in \textsf{Indicator}(s)$ into a mixed-integer linear program.

Source node

IndicatorToMILPBridge supports:

where F is MOI.VectorOfVariables or MOI.VectorAffineFunction{T}.

Target nodes

IndicatorToMILPBridge creates:

source

Objective bridges

These bridges are subtypes of Bridges.Objective.AbstractBridge.

MathOptInterface.Bridges.Objective.QuadratizeBridgeType
QuadratizeBridge{T,G} <: FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G}

QuadratizeBridge implements the following reformulations:

  • $\min \{a^\top x + b\}$ into $\min\{x^\top \mathbf{0} x + a^\top x + b\}$
  • $\max \{a^\top x + b\}$ into $\max\{x^\top \mathbf{0} x + a^\top x + b\}$

where T is the coefficient type of 0.

Source node

QuadratizeBridge supports:

Target nodes

QuadratizeBridge creates:

source
MathOptInterface.Bridges.Objective.VectorFunctionizeBridgeType
VectorFunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.VectorAffineFunction{T},G}

VectorFunctionizeBridge implements the following reformulations:

  • $\min \{x\}$ into $\min\{1x + 0\}$
  • $\max \{x\}$ into $\max\{1x + 0\}$

where T is the coefficient type of 1 and 0.

Source node

VectorFunctionizeBridge supports:

Target nodes

VectorFunctionizeBridge creates:

source
MathOptInterface.Bridges.Objective.FunctionConversionBridgeType
FunctionConversionBridge{T,F,G} <: AbstractBridge

FunctionConversionBridge implements the following reformulations:

  • $\min \{g(x)\}$ into $\min\{f(x)\}$
  • $\max \{g(x)\}$ into $\max\{f(x)\}$

for these pairs of functions:

Source node

FunctionConversionBridge supports:

Target nodes

FunctionConversionBridge creates:

source
MathOptInterface.Bridges.Objective.SlackBridgeType
SlackBridge{T,F,G}

SlackBridge implements the following reformulations:

  • $\min\{f(x)\}$ into $\min\{y\;|\; f(x) - y \le 0\}$
  • $\max\{f(x)\}$ into $\max\{y\;|\; f(x) - y \ge 0\}$

where F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).

Source node

SlackBridge supports:

Target nodes

SlackBridge creates:

Warning

When using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.

source
MathOptInterface.Bridges.Objective.VectorSlackBridgeType
VectorSlackBridge{T,F,G}

VectorSlackBridge implements the following reformulations:

  • $\min\{f(x)\}$ into $\min\{y\;|\; y - f(x) \in \mathbb{R}_+ \}$
  • $\max\{f(x)\}$ into $\max\{y\;|\; f(x) - y \in \mathbb{R}_+ \}$

where F is the type of f(x) - y, G is the type of f(x), and T is the coefficient type of f(x).

Source node

VectorSlackBridge supports:

Target nodes

VectorSlackBridge creates:

Warning

When using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge, then set MOI.ObjectiveSense and re-add the objective.

source

Variable bridges

These bridges are subtypes of Bridges.Variable.AbstractBridge.

MathOptInterface.Bridges.Variable.RSOCtoPSDBridgeType
RSOCtoPSDBridge{T} <: Bridges.Variable.AbstractBridge

RSOCtoPSDBridge implements the following reformulation:

  • $||x||_2^2 \le 2tu$ where $t, u \ge 0$ into $Y \succeq 0$, with the substitution rule: $Y = \left[\begin{array}{c c}t & x^\top \\ x & 2u \mathbf{I}\end{array}\right].$

Additional bounds are added to ensure the off-diagonals of the $2uI$ submatrix are 0, and linear constraints are added to ensure the diagonal of $2uI$ takes the same values.

As a special case, if $|x|| = 0$, then RSOCtoPSDBridge reformulates into $(t, u) \in \mathbb{R}_+$.

Source node

RSOCtoPSDBridge supports:

Target nodes

RSOCtoPSDBridge creates:

source
MathOptInterface.Bridges.Variable.RSOCtoSOCBridgeType
RSOCtoSOCBridge{T} <: Bridges.Variable.AbstractBridge

RSOCtoSOCBridge implements the following reformulation:

  • $||x||_2^2 \le 2tu$ into $||v||_2 \le w$, with the substitution rules $t = \frac{w}{\sqrt 2} + \frac{v_1}{\sqrt 2}$, $u = \frac{w}{\sqrt 2} - \frac{v_1}{\sqrt 2}$, and $x = (v_2,\ldots,v_N)$.

Source node

RSOCtoSOCBridge supports:

Target node

RSOCtoSOCBridge creates:

source
MathOptInterface.Bridges.Variable.SOCtoRSOCBridgeType
SOCtoRSOCBridge{T} <: Bridges.Variable.AbstractBridge

SOCtoRSOCBridge implements the following reformulation:

  • $||x||_2 \le t$ into $2uv \ge ||w||_2^2$, with the substitution rules $t = \frac{u}{\sqrt 2} + \frac{v}{\sqrt 2}$, $x = (\frac{u}{\sqrt 2} - \frac{v}{\sqrt 2}, w)$.

Assumptions

  • SOCtoRSOCBridge assumes that $|x| \ge 1$.

Source node

SOCtoRSOCBridge supports:

Target node

SOCtoRSOCBridge creates:

source
MathOptInterface.Bridges.Variable.VectorizeBridgeType
VectorizeBridge{T,S} <: Bridges.Variable.AbstractBridge

VectorizeBridge implements the following reformulations:

  • $x \ge a$ into $[y] \in \mathbb{R}_+$ with the substitution rule $x = a + y$
  • $x \le a$ into $[y] \in \mathbb{R}_-$ with the substitution rule $x = a + y$
  • $x == a$ into $[y] \in \{0\}$ with the substitution rule $x = a + y$

where T is the coefficient type of a + y.

Source node

VectorizeBridge supports:

Target nodes

VectorizeBridge creates:

source
MathOptInterface.Bridges.Variable.ZerosBridgeType
ZerosBridge{T} <: Bridges.Variable.AbstractBridge

ZerosBridge implements the following reformulation:

  • $x \in \{0\}$ into the substitution rule $x = 0$,

where T is the coefficient type of 0.

Source node

ZerosBridge supports:

Target nodes

ZerosBridge does not create target nodes. It replaces all instances of x with 0 via substitution. This means that no variables are created in the underlying model.

Caveats

The bridged variables are similar to parameters with zero values. Parameters with non-zero values can be created with constrained variables in MOI.EqualTo by combining a VectorizeBridge and this bridge.

However, functions modified by ZerosBridge cannot be unbridged. That is, for a given function, we cannot determine if the bridged variables were used.

A related implication is that this bridge does not support MOI.ConstraintDual. However, if a MOI.Utilities.CachingOptimizer is used, the dual can be determined by the bridged optimizer using MOI.Utilities.get_fallback because the caching optimizer records the unbridged function.

source
MathOptInterface.Bridges.Variable.HermitianToSymmetricPSDBridgeType
HermitianToSymmetricPSDBridge{T} <: Bridges.Variable.AbstractBridge

HermitianToSymmetricPSDBridge implements the following reformulation:

  • Hermitian positive semidefinite n x n complex matrix to a symmetric positive semidefinite 2n x 2n real matrix satisfying equality constraints described below.

Source node

HermitianToSymmetricPSDBridge supports:

Target node

HermitianToSymmetricPSDBridge creates:

Reformulation

The reformulation is best described by example.

The Hermitian matrix:

\[\begin{bmatrix} + x_{11} & x_{12} + y_{12}im & x_{13} + y_{13}im\\ + x_{12} - y_{12}im & x_{22} & x_{23} + y_{23}im\\ + x_{13} - y_{13}im & x_{23} - y_{23}im & x_{33} +\end{bmatrix}\]

is positive semidefinite if and only if the symmetric matrix:

\[\begin{bmatrix} + x_{11} & x_{12} & x_{13} & 0 & y_{12} & y_{13} \\ + & x_{22} & x_{23} & -y_{12} & 0 & y_{23} \\ + & & x_{33} & -y_{13} & -y_{23} & 0 \\ + & & & x_{11} & x_{12} & x_{13} \\ + & & & & x_{22} & x_{23} \\ + & & & & & x_{33} +\end{bmatrix}\]

is positive semidefinite.

The bridge achieves this reformulation by adding a new set of variables in MOI.PositiveSemidefiniteConeTriangle(6), and then adding three groups of equality constraints to:

  • constrain the two x blocks to be equal
  • force the diagonal of the y blocks to be 0
  • force the lower triangular of the y block to be the negative of the upper triangle.
source
diff --git a/previews/PR2418/submodules/Bridges/overview/index.html b/previews/PR2418/submodules/Bridges/overview/index.html new file mode 100644 index 0000000000..0691a09d64 --- /dev/null +++ b/previews/PR2418/submodules/Bridges/overview/index.html @@ -0,0 +1,53 @@ + +Overview · MathOptInterface

The Bridges submodule

The Bridges module simplifies the process of converting models between equivalent formulations.

Tip

Read our paper for more details on how bridges are implemented.

Why bridges?

A constraint can often be written in a number of equivalent formulations. For example, the constraint $l \le a^\top x \le u$ (ScalarAffineFunction-in-Interval) could be re-formulated as two constraints: $a^\top x \ge l$ (ScalarAffineFunction-in-GreaterThan) and $a^\top x \le u$ (ScalarAffineFunction-in-LessThan). An alternative re-formulation is to add a dummy variable y with the constraints $l \le y \le u$ (VariableIndex-in-Interval) and $a^\top x - y = 0$ (ScalarAffineFunction-in-EqualTo).

To avoid each solver having to code these transformations manually, MathOptInterface provides bridges.

A bridge is a small transformation from one constraint type to another (potentially collection of) constraint type.

Because these bridges are included in MathOptInterface, they can be re-used by any optimizer. Some bridges also implement constraint modifications and constraint primal and dual translations.

Several bridges can be used in combination to transform a single constraint into a form that the solver may understand. Choosing the bridges to use takes the form of finding a shortest path in the hyper-graph of bridges. The methodology is detailed in the MOI paper.

The three types of bridges

There are three types of bridges in MathOptInterface:

  1. Constraint bridges
  2. Variable bridges
  3. Objective bridges

Constraint bridges

Constraint bridges convert constraints formulated by the user into an equivalent form supported by the solver. Constraint bridges are subtypes of Bridges.Constraint.AbstractBridge.

The equivalent formulation may add constraints (and possibly also variables) in the underlying model.

In particular, constraint bridges can focus on rewriting the function of a constraint, and do not change the set. Function bridges are subtypes of Bridges.Constraint.AbstractFunctionConversionBridge.

Read the list of implemented constraint bridges for more details on the types of transformations that are available. Function bridges are Bridges.Constraint.ScalarFunctionizeBridge and Bridges.Constraint.VectorFunctionizeBridge.

Variable bridges

Variable bridges convert variables added by the user, either free with add_variable/add_variables, or constrained with add_constrained_variable/add_constrained_variables, into an equivalent form supported by the solver. Variable bridges are subtypes of Bridges.Variable.AbstractBridge.

The equivalent formulation may add constraints (and possibly also variables) in the underlying model.

Read the list of implemented variable bridges for more details on the types of transformations that are available.

Objective bridges

Objective bridges convert the ObjectiveFunction set by the user into an equivalent form supported by the solver. Objective bridges are subtypes of Bridges.Objective.AbstractBridge.

The equivalent formulation may add constraints (and possibly also variables) in the underlying model.

Read the list of implemented objective bridges for more details on the types of transformations that are available.

Bridges.full_bridge_optimizer

Tip

Unless you have an advanced use-case, this is probably the only function you need to care about.

To enable the full power of MathOptInterface's bridges, wrap an optimizer in a Bridges.full_bridge_optimizer.

julia> inner_optimizer = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64)
+MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}
+with 0 variable bridges
+with 0 constraint bridges
+with 0 objective bridges
+with inner model MOIU.Model{Float64}

Now, use optimizer as normal, and bridging will happen lazily behind the scenes. By lazily, we mean that bridging will happen if and only if the constraint is not supported by the inner_optimizer.

Info

Most bridges are added by default in Bridges.full_bridge_optimizer. However, for technical reasons, some bridges are not added by default. Three examples include Bridges.Constraint.SOCtoPSDBridge, Bridges.Constraint.SOCtoNonConvexQuadBridge and Bridges.Constraint.RSOCtoNonConvexQuadBridge. See the docs of those bridges for more information.

Add a single bridge

If you don't want to use Bridges.full_bridge_optimizer, you can wrap an optimizer in a single bridge.

However, this will force the constraint to be bridged, even if the inner_optimizer supports it.

julia> inner_optimizer = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer)
+MOIB.Constraint.SingleBridgeOptimizer{MOIB.Constraint.SplitIntervalBridge{Float64}, MOIU.Model{Float64}}
+with 0 constraint bridges
+with inner model MOIU.Model{Float64}
+
+julia> x = MOI.add_variable(optimizer)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
+
+julia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())
+1-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})
+
+julia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())
+2-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64})
+ (MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64})

Bridges.LazyBridgeOptimizer

If you don't want to use Bridges.full_bridge_optimizer, but you need more than a single bridge (or you want the bridging to happen lazily), you can manually construct a Bridges.LazyBridgeOptimizer.

First, wrap an inner optimizer:

julia> inner_optimizer = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> optimizer = MOI.Bridges.LazyBridgeOptimizer(inner_optimizer)
+MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}
+with 0 variable bridges
+with 0 constraint bridges
+with 0 objective bridges
+with inner model MOIU.Model{Float64}

Then use Bridges.add_bridge to add individual bridges:

julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Constraint.SplitIntervalBridge{Float64})
+
+julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Objective.FunctionizeBridge{Float64})

Now the constraints will be bridged only if needed:

julia> x = MOI.add_variable(optimizer)
+MOI.VariableIndex(1)
+
+julia> MOI.add_constraint(optimizer, x, MOI.Interval(0.0, 1.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
+
+julia> MOI.get(optimizer, MOI.ListOfConstraintTypesPresent())
+1-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})
+
+julia> MOI.get(inner_optimizer, MOI.ListOfConstraintTypesPresent())
+1-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64})
diff --git a/previews/PR2418/submodules/Bridges/reference/index.html b/previews/PR2418/submodules/Bridges/reference/index.html new file mode 100644 index 0000000000..4330ebe233 --- /dev/null +++ b/previews/PR2418/submodules/Bridges/reference/index.html @@ -0,0 +1,226 @@ + +API Reference · MathOptInterface

Bridges

AbstractBridge API

MathOptInterface.Bridges.AbstractBridgeType
abstract type AbstractBridge end

An abstract type representing a bridged constraint or variable in a MOI.Bridges.AbstractBridgeOptimizer.

All bridges must implement:

Subtypes of AbstractBridge may have additional requirements. Consult their docstrings for details.

In addition, all subtypes may optionally implement the following constraint attributes with the bridge in place of the constraint index:

source
MathOptInterface.Bridges.added_constrained_variable_typesFunction
added_constrained_variable_types(
+    BT::Type{<:AbstractBridge},
+)::Vector{Tuple{Type}}

Return a list of the types of constrained variables that bridges of concrete type BT add.

Implementation notes

  • This method depends only on the type of the bridge, not the runtime value. If the bridge may add a constrained variable, the type must be included in the return vector.
  • If the bridge adds a free variable via MOI.add_variable or MOI.add_variables, the return vector must include (MOI.Reals,).

Example

julia> MOI.Bridges.added_constrained_variable_types(
+           MOI.Bridges.Variable.NonposToNonnegBridge{Float64},
+       )
+1-element Vector{Tuple{Type}}:
+ (MathOptInterface.Nonnegatives,)
source
MathOptInterface.Bridges.added_constraint_typesFunction
added_constraint_types(
+    BT::Type{<:AbstractBridge},
+)::Vector{Tuple{Type,Type}}

Return a list of the types of constraints that bridges of concrete type BT add.

Implementation notes

  • This method depends only on the type of the bridge, not the runtime value. If the bridge may add a constraint, the type must be included in the return vector.

Example

julia> MOI.Bridges.added_constraint_types(
+           MOI.Bridges.Constraint.ZeroOneBridge{Float64},
+       )
+2-element Vector{Tuple{Type, Type}}:
+ (MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.Interval{Float64})
+ (MathOptInterface.VariableIndex, MathOptInterface.Integer)
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64

Return the number of variables created by the bridge b in the model.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)

Return the list of variables created by the bridge b.

See also MOI.ListOfVariableIndices.

Implementation notes

  • There is a default fallback, so you need only implement this if the bridge adds new variables.
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}

Return the number of constraints of the type F-in-S created by the bridge b.

See also MOI.NumberOfConstraints.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}

Return a Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-in-S created by the bride b.

See also MOI.ListOfConstraintIndices.

Implementation notes

  • There is a default fallback, so you need only implement this for the constraint types returned by added_constraint_types.
source
MathOptInterface.Bridges.final_touchFunction
final_touch(bridge::AbstractBridge, model::MOI.ModelLike)::Nothing

A function that is called immediately prior to MOI.optimize! to allow bridges to modify their reformulations with respect to other variables and constraints in model.

For example, if the correctness of bridge depends on the bounds of a variable or the fact that variables are integer, then the bridge can implement final_touch to check assumptions immediately before a call to MOI.optimize!.

If you implement this method, you must also implement needs_final_touch.

source
MathOptInterface.Bridges.bridging_costFunction
bridging_cost(b::AbstractBridgeOptimizer, S::Type{<:MOI.AbstractSet}})

Return the cost of bridging variables constrained in S on creation, is_bridged(b, S) is assumed to be true.

bridging_cost(
+    b::AbstractBridgeOptimizer,
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)

Return the cost of bridging F-in-S constraints.

is_bridged(b, S) is assumed to be true.

source
MathOptInterface.Bridges.runtestsFunction
runtests(
+    Bridge::Type{<:AbstractBridge},
+    input::String,
+    output::String;
+    variable_start = 1.2,
+    constraint_start = 1.2,
+    eltype = Float64,
+)

Run a series of tests that check the correctness of Bridge.

input and output are models in the style of MOI.Utilities.loadfromstring!.

Example

julia> MOI.Bridges.runtests(
+           MOI.Bridges.Constraint.ZeroOneBridge,
+           """
+           variables: x
+           x in ZeroOne()
+           """,
+           """
+           variables: x
+           x in Integer()
+           1.0 * x in Interval(0.0, 1.0)
+           """,
+       )
source

Constraint bridge API

MathOptInterface.supports_constraintMethod
MOI.supports_constraint(
+    BT::Type{<:AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.

Implementation notes

  • This method depends only on the type of the inputs, not the runtime values.
  • There is a default fallback, so you need only implement this method for constraint types that the bridge implements.
source
MathOptInterface.Bridges.Constraint.concrete_bridge_typeFunction
concrete_bridge_type(
+    BT::Type{<:AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet}
+)::Type

Return the concrete type of the bridge supporting F-in-S constraints.

This function can only be called if MOI.supports_constraint(BT, F, S) is true.

Example

The SplitIntervalBridge bridges a MOI.VariableIndex-in-MOI.Interval constraint into a MOI.VariableIndex-in-MOI.GreaterThan and a MOI.VariableIndex-in-MOI.LessThan constraint.

julia> MOI.Bridges.Constraint.concrete_bridge_type(
+           MOI.Bridges.Constraint.SplitIntervalBridge{Float64},
+           MOI.VariableIndex,
+           MOI.Interval{Float64},
+       )
+MathOptInterface.Bridges.Constraint.SplitIntervalBridge{Float64, MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}, MathOptInterface.GreaterThan{Float64}, MathOptInterface.LessThan{Float64}}
source
MathOptInterface.Bridges.Constraint.bridge_constraintFunction
bridge_constraint(
+    BT::Type{<:AbstractBridge},
+    model::MOI.ModelLike,
+    func::AbstractFunction,
+    set::MOI.AbstractSet,
+)::BT

Bridge the constraint func-in-set using bridge BT to model and returns a bridge object of type BT.

Implementation notes

  • The bridge type BT should be a concrete type, that is, all the type parameters of the bridge must be set.
source
MathOptInterface.Bridges.Constraint.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)

Return AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.

This is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.

Example

julia> struct MyNewBridge{T} <: MOI.Bridges.Constraint.AbstractBridge end
+
+julia> bridge = MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}}(
+           MOI.Utilities.Model{Float64}(),
+       )
+MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 constraint bridges
+with inner model MOIU.Model{Float64}

Implementation notes

All bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.

julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
+           MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{T},OT};

This enables users to create bridged models as follows:

julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
+MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 constraint bridges
+with inner model MOIU.Model{Float64}
source
MathOptInterface.Bridges.Constraint.MultiSetMapBridgeType
abstract type MultiSetMapBridge{T,S1,G} <: AbstractBridge end

Same as SetMapBridge but the output constraint type does not only depend on the input constraint type.

When subtyping MultiSetMapBridge, added_constraint_types and supports should additionally be implemented by the bridge.

For example, if a bridge BridgeType may create either a constraint of type F2-in-S2 or F3-in-S3, these methods should be implemented as follows:

function MOI.Bridges.added_constraint_types(
+    ::Type{<:BridgeType{T,F2,F3}},
+) where {T,F2,F3}
+    return Tuple{Type,Type}[(F2, S2), (F3, S3)]
+end
+
+function MOI.supports(
+    model::MOI.ModelLike,
+    attr::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},
+    ::Type{<:BridgeType{T,F2,F3}},
+) where {T,F2,F3}
+    return MOI.supports(model, attr, MOI.ConstraintIndex{F2,S2}) ||
+           MOI.supports(model, attr, MOI.ConstraintIndex{F3,S3})
+end
source
MathOptInterface.Bridges.Constraint.SetMapBridgeType
abstract type SetMapBridge{T,S2,S1,F,G} <: MultiSetMapBridge{T,S1,G} end

Consider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.

A SetMapBridge{T,S2,S1,F,G} is a bridge that maps G-in-S1 constraints into F-in-S2 by mapping the function through A.

The linear map A is described by;

Implementing a method for these two functions is sufficient to bridge constraints. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:

See the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.

source

Objective bridge API

MathOptInterface.Bridges.Objective.supports_objective_functionFunction
supports_objective_function(
+    BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging objective functions of type F.

Implementation notes

  • This method depends only on the type of the inputs, not the runtime values.
  • There is a default fallback, so you need only implement this method For objective functions that the bridge implements.
source
MathOptInterface.Bridges.set_objective_function_typeFunction
set_objective_function_type(
+    BT::Type{<:Objective.AbstractBridge},
+)::Type{<:MOI.AbstractFunction}

Return the type of objective function that bridges of concrete type BT set.

Implementation notes

  • This method depends only on the type of the bridge, not the runtime value.

Example

julia> MOI.Bridges.set_objective_function_type(
+           MOI.Bridges.Objective.FunctionizeBridge{Float64},
+       )
+MathOptInterface.ScalarAffineFunction{Float64}
source
MathOptInterface.Bridges.Objective.concrete_bridge_typeFunction
concrete_bridge_type(
+    BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
+    F::Type{<:MOI.AbstractFunction},
+)::Type

Return the concrete type of the bridge supporting objective functions of type F.

This function can only be called if MOI.supports_objective_function(BT, F) is true.

source
MathOptInterface.Bridges.Objective.bridge_objectiveFunction
bridge_objective(
+    BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
+    model::MOI.ModelLike,
+    func::MOI.AbstractFunction,
+)::BT

Bridge the objective function func using bridge BT to model and returns a bridge object of type BT.

Implementation notes

  • The bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.
source
MathOptInterface.Bridges.Objective.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)

Return AbstractBridgeOptimizer that always bridges any objective function supported by the bridge BT.

This is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the objective function if it is supported by the bridge BT and unsupported by model.

Example

julia> struct MyNewBridge{T} <: MOI.Bridges.Objective.AbstractBridge end
+
+julia> bridge = MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}}(
+           MOI.Utilities.Model{Float64}(),
+       )
+MOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 objective bridges
+with inner model MOIU.Model{Float64}

Implementation notes

All bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.

julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
+           MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{T},OT};

This enables users to create bridged models as follows:

julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
+MOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 objective bridges
+with inner model MOIU.Model{Float64}
source

Variable bridge API

MathOptInterface.Bridges.Variable.supports_constrained_variableFunction
supports_constrained_variable(
+    BT::Type{<:AbstractBridge},
+    S::Type{<:MOI.AbstractSet},
+)::Bool

Return a Bool indicating whether the bridges of type BT support bridging constrained variables in S. That is, it returns true if the bridge of type BT converts constrained variables of type S into a form supported by the solver.

Implementation notes

  • This method depends only on the type of the bridge and set, not the runtime values.
  • There is a default fallback, so you need only implement this method for sets that the bridge implements.

Example

julia> MOI.Bridges.Variable.supports_constrained_variable(
+           MOI.Bridges.Variable.NonposToNonnegBridge{Float64},
+           MOI.Nonpositives,
+       )
+true
+
+julia> MOI.Bridges.Variable.supports_constrained_variable(
+           MOI.Bridges.Variable.NonposToNonnegBridge{Float64},
+           MOI.Nonnegatives,
+       )
+false
source
MathOptInterface.Bridges.Variable.concrete_bridge_typeFunction
concrete_bridge_type(
+    BT::Type{<:AbstractBridge},
+    S::Type{<:MOI.AbstractSet},
+)::Type

Return the concrete type of the bridge supporting variables in S constraints.

This function can only be called if MOI.supports_constrained_variable(BT, S) is true.

Examples

As a variable in MOI.GreaterThan is bridged into variables in MOI.Nonnegatives by the VectorizeBridge:

julia> MOI.Bridges.Variable.concrete_bridge_type(
+           MOI.Bridges.Variable.VectorizeBridge{Float64},
+           MOI.GreaterThan{Float64},
+       )
+MathOptInterface.Bridges.Variable.VectorizeBridge{Float64, MathOptInterface.Nonnegatives}
source
MathOptInterface.Bridges.Variable.bridge_constrained_variableFunction
bridge_constrained_variable(
+    BT::Type{<:AbstractBridge},
+    model::MOI.ModelLike,
+    set::MOI.AbstractSet,
+)::BT

Bridge the constrained variable in set using bridge BT to model and returns a bridge object of type BT.

Implementation notes

  • The bridge type BT must be a concrete type, that is, all the type parameters of the bridge must be set.
source
MathOptInterface.Bridges.Variable.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)

Return MOI.Bridges.AbstractBridgeOptimizer that always bridges any variables constrained on creation supported by the bridge BT.

This is in contrast with the MOI.Bridges.LazyBridgeOptimizer, which only bridges the variables constrained on creation if they are supported by the bridge BT and unsupported by model.

Warning

Two SingleBridgeOptimizers cannot be used together as both of them assume that the underlying model only returns variable indices with nonnegative values. Use MOI.Bridges.LazyBridgeOptimizer instead.

Example

julia> struct MyNewBridge{T} <: MOI.Bridges.Variable.AbstractBridge end
+
+julia> bridge = MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}}(
+           MOI.Utilities.Model{Float64}(),
+       )
+MOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 variable bridges
+with inner model MOIU.Model{Float64}

Implementation notes

All bridges should simplify the creation of SingleBridgeOptimizers by defining a constant that wraps the bridge in a SingleBridgeOptimizer.

julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
+           MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{T},OT};

This enables users to create bridged models as follows:

julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
+MOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
+with 0 variable bridges
+with inner model MOIU.Model{Float64}
source
MathOptInterface.Bridges.Variable.SetMapBridgeType
abstract type SetMapBridge{T,S1,S2} <: AbstractBridge end

Consider two type of sets, S1 and S2, and a linear mapping A such that the image of a set of type S1 under A is a set of type S2.

A SetMapBridge{T,S1,S2} is a bridge that substitutes constrained variables in S2 into the image through A of constrained variables in S1.

The linear map A is described by:

Implementing a method for these two functions is sufficient to bridge constrained variables. However, in order for the getters and setters of attributes such as dual solutions and starting values to work as well, a method for the following functions must be implemented:

See the docstrings of each function to see which feature would be missing if it was not implemented for a given bridge.

source
MathOptInterface.Bridges.Variable.unbridged_mapFunction
unbridged_map(
+   bridge::MOI.Bridges.Variable.AbstractBridge,
+    vi::MOI.VariableIndex,
+)

For a bridged variable in a scalar set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi.

unbridged_map(
+    bridge::MOI.Bridges.Variable.AbstractBridge,
+    vis::Vector{MOI.VariableIndex},
+)

For a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vis. If this method is not implemented, it falls back to calling the following method for every variable of vis.

unbridged_map(
+    bridge::MOI.Bridges.Variable.AbstractBridge,
+    vi::MOI.VariableIndex,
+    i::MOI.Bridges.IndexInVector,
+)

For a bridged variable in a vector set, return a tuple of pairs mapping the variables created by the bridge to an affine expression in terms of the bridged variable vi corresponding to the ith variable of the vector.

If there is no way to recover the expression in terms of the bridged variable(s) vi(s), return nothing. See ZerosBridge for an example of bridge returning nothing.

source

AbstractBridgeOptimizer API

MathOptInterface.Bridges.bridged_variable_functionFunction
bridged_variable_function(
+    b::AbstractBridgeOptimizer,
+    vi::MOI.VariableIndex,
+)

Return a MOI.AbstractScalarFunction of variables of b.model that equals vi. That is, if the variable vi is bridged, it returns its expression in terms of the variables of b.model. Otherwise, it returns vi.

source
MathOptInterface.Bridges.unbridged_variable_functionFunction
unbridged_variable_function(
+    b::AbstractBridgeOptimizer,
+    vi::MOI.VariableIndex,
+)

Return a MOI.AbstractScalarFunction of variables of b that equals vi. That is, if the variable vi is an internal variable of b.model created by a bridge but not visible to the user, it returns its expression in terms of the variables of bridged variables. Otherwise, it returns vi.

source
MathOptInterface.Bridges.recursive_modelFunction
recursive_model(b::AbstractBridgeOptimizer)

If a variable, constraint, or objective is bridged, return the context of the inner variables. For most optimizers, this should be b.model.

source
MathOptInterface.Bridges.FirstBridgeType
struct FirstBridge <: MOI.AbstractConstraintAttribute end

Returns the first bridge used to bridge the constraint.

Warning

The indices of the bridge correspond to internal indices and may not correspond to indices of the model this attribute is got from.

source

LazyBridgeOptimizer API

MathOptInterface.Bridges.LazyBridgeOptimizerType
LazyBridgeOptimizer(model::MOI.ModelLike)

The LazyBridgeOptimizer is a bridge optimizer that supports multiple bridges, and only bridges things which are not supported by the internal model.

Internally, the LazyBridgeOptimizer solves a shortest hyper-path problem to determine which bridges to use.

In general, you should use full_bridge_optimizer instead of this constructor because full_bridge_optimizer automatically adds a large number of supported bridges.

See also: add_bridge, remove_bridge, has_bridge and full_bridge_optimizer.

Example

julia> model = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.Model{Float64}())
+MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}}
+with 0 variable bridges
+with 0 constraint bridges
+with 0 objective bridges
+with inner model MOIU.Model{Float64}
+
+julia> MOI.Bridges.add_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})
+
+julia> MOI.Bridges.has_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64})
+true
source
MathOptInterface.Bridges.full_bridge_optimizerFunction
full_bridge_optimizer(model::MOI.ModelLike, ::Type{T}) where {T}

Returns a LazyBridgeOptimizer bridging model for every bridge defined in this package (see below for the few exceptions) and for the coefficient type T, as well as the bridges in the list returned by the ListOfNonstandardBridges attribute.

Example

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> bridged_model = MOI.Bridges.full_bridge_optimizer(model, Float64);

Exceptions

The following bridges are not added by full_bridge_optimizer, except if they are in the list returned by the ListOfNonstandardBridges attribute:

See the docstring of the each bridge for the reason they are not added.

source
MathOptInterface.Bridges.ListOfNonstandardBridgesType
ListOfNonstandardBridges{T}() <: MOI.AbstractOptimizerAttribute

Any optimizer can be wrapped in a LazyBridgeOptimizer using full_bridge_optimizer. However, by default LazyBridgeOptimizer uses a limited set of bridges that are:

  1. implemented in MOI.Bridges
  2. generally applicable for all optimizers.

For some optimizers however, it is useful to add additional bridges, such as those that are implemented in external packages (for example, within the solver package itself) or only apply in certain circumstances (for example, Constraint.SOCtoNonConvexQuadBridge).

Such optimizers should implement the ListOfNonstandardBridges attribute to return a vector of bridge types that are added by full_bridge_optimizer in addition to the list of default bridges.

Note that optimizers implementing ListOfNonstandardBridges may require package-specific functions or sets to be used if the non-standard bridges are not added. Therefore, you are recommended to use model = MOI.instantiate(Package.Optimizer; with_bridge_type = T) instead of model = MOI.instantiate(Package.Optimizer). See MOI.instantiate.

Examples

An optimizer using a non-default bridge in MOI.Bridges

Solvers supporting MOI.ScalarQuadraticFunction can support MOI.SecondOrderCone and MOI.RotatedSecondOrderCone by defining:

function MOI.get(::MyQuadraticOptimizer, ::ListOfNonstandardBridges{Float64})
+    return Type[
+        MOI.Bridges.Constraint.SOCtoNonConvexQuadBridge{Float64},
+        MOI.Bridges.Constraint.RSOCtoNonConvexQuadBridge{Float64},
+    ]
+end

An optimizer defining an internal bridge

Suppose an optimizer can exploit specific structure of a constraint, for example, it can exploit the structure of the matrix A in the linear system of equations A * x = b.

The optimizer can define the function:

struct MatrixAffineFunction{T} <: MOI.AbstractVectorFunction
+    A::SomeStructuredMatrixType{T}
+    b::Vector{T}
+end

and then a bridge

struct MatrixAffineFunctionBridge{T} <: MOI.Constraint.AbstractBridge
+    # ...
+end
+# ...

from VectorAffineFunction{T} to the MatrixAffineFunction. Finally, it defines:

function MOI.get(::Optimizer{T}, ::ListOfNonstandardBridges{T}) where {T}
+    return Type[MatrixAffineFunctionBridge{T}]
+end
source
MathOptInterface.Bridges.print_active_bridgesFunction
print_active_bridges([io::IO=stdout,] b::MOI.Bridges.LazyBridgeOptimizer)

Print the set of bridges that are active in the model b.

source
print_active_bridges(
+    [io::IO=stdout,]
+    b::MOI.Bridges.LazyBridgeOptimizer,
+    F::Type{<:MOI.AbstractFunction}
+)

Print the set of bridges required for an objective function of type F.

source
print_active_bridges(
+    [io::IO=stdout,]
+    b::MOI.Bridges.LazyBridgeOptimizer,
+    F::Type{<:MOI.AbstractFunction},
+    S::Type{<:MOI.AbstractSet},
+)

Print the set of bridges required for a constraint of type F-in-S.

source
print_active_bridges(
+    [io::IO=stdout,]
+    b::MOI.Bridges.LazyBridgeOptimizer,
+    S::Type{<:MOI.AbstractSet}
+)

Print the set of bridges required for a variable constrained to set S.

source
MathOptInterface.Bridges.print_graphFunction
print_graph([io::IO = stdout,] b::LazyBridgeOptimizer)

Print the hyper-graph containing all variable, constraint, and objective types that could be obtained by bridging the variables, constraints, and objectives that are present in the model by all the bridges added to b.

Each node in the hyper-graph corresponds to a variable, constraint, or objective type.

  • Variable nodes are indicated by [ ]
  • Constraint nodes are indicated by ( )
  • Objective nodes are indicated by | |

The number inside each pair of brackets is an index of the node in the hyper-graph.

Note that this hyper-graph is the full list of possible transformations. When the bridged model is created, we select the shortest hyper-path from this graph, so many nodes may be un-used.

To see which nodes are used, call print_active_bridges.

For more information, see Legat, B., Dowson, O., Garcia, J., and Lubin, M. (2020). "MathOptInterface: a data structure for mathematical optimization problems." URL

source

SetMap API

MathOptInterface.Bridges.map_functionFunction
map_function(::Type{BT}, func) where {BT}

Return the image of func through the linear map A defined in Variable.SetMapBridge and Constraint.SetMapBridge. This is used for getting the MOI.ConstraintPrimal of variable bridges. For constraint bridges, this is used for bridging the constraint, setting the MOI.ConstraintFunction and MOI.ConstraintPrimalStart and modifying the function with MOI.modify.

map_function(::Type{BT}, func, i::IndexInVector) where {BT}

Return the scalar function at the ith index of the vector function that would be returned by map_function(BT, func) except that it may compute the ith element. This is used by bridged_function and for getting the MOI.VariablePrimal and MOI.VariablePrimalStart of variable bridges.

source

Bridging graph API

MathOptInterface.Bridges.GraphType
Graph()

A type-stable datastructure for computing the shortest hyperpath problem.

Nodes

There are three types of nodes in the graph:

Add nodes to the graph using add_node.

Edges

There are two types of edges in the graph:

Add edges to the graph using add_edge.

For the ability to add a variable constrained on creation as a free variable followed by a constraint, use set_variable_constraint_node.

Optimal hyper-edges

Use bridge_index to compute the minimum-cost bridge leaving a node.

Note that bridge_index lazy runs a Bellman-Ford algorithm to compute the set of minimum cost edges. Thus, the first call to bridge_index after adding new nodes or edges will take longer than subsequent calls.

source
MathOptInterface.Bridges.add_nodeFunction
add_node(graph::Graph, ::Type{VariableNode})::VariableNode
+add_node(graph::Graph, ::Type{ConstraintNode})::ConstraintNode
+add_node(graph::Graph, ::Type{ObjectiveNode})::ObjectiveNode

Add a new node to graph.

source
MathOptInterface.Bridges.add_edgeFunction
add_edge(graph::Graph, node::VariableNode, edge::Edge)::Nothing
+add_edge(graph::Graph, node::ConstraintNode, edge::Edge)::Nothing
+add_edge(graph::Graph, node::ObjectiveNode, edge::ObjectiveEdge)::Nothing

Add edge to graph, where edge starts at node and connects to the nodes defined in edge.

source
MathOptInterface.Bridges.set_variable_constraint_nodeFunction
set_variable_constraint_node(
+    graph::Graph,
+    variable_node::VariableNode,
+    constraint_node::ConstraintNode,
+    cost::Int,
+)

As an alternative to variable_node, add a virtual edge to graph that represents adding a free variable, followed by a constraint of type constraint_node, with bridging cost cost.

Why is this needed?

Variables can either be added as a variable constrained on creation, or as a free variable which then has a constraint added to it.

source
MathOptInterface.Bridges.bridge_indexFunction
bridge_index(graph::Graph, node::VariableNode)::Int
+bridge_index(graph::Graph, node::ConstraintNode)::Int
+bridge_index(graph::Graph, node::ObjectiveNode)::Int

Return the optimal index of the bridge to chose from node.

source
MathOptInterface.Bridges.is_variable_edge_bestFunction
is_variable_edge_best(graph::Graph, node::VariableNode)::Bool

Return a Bool indicating whether node should be added as a variable constrained on creation, or as a free variable followed by a constraint.

source
diff --git a/previews/PR2418/submodules/FileFormats/overview/index.html b/previews/PR2418/submodules/FileFormats/overview/index.html new file mode 100644 index 0000000000..51a0d48c52 --- /dev/null +++ b/previews/PR2418/submodules/FileFormats/overview/index.html @@ -0,0 +1,147 @@ + +Overview · MathOptInterface

The FileFormats submodule

The FileFormats module provides functions for reading and writing MOI models using write_to_file and read_from_file.

Supported file types

You must read and write files to a FileFormats.Model object. Specific the file-type by passing a FileFormats.FileFormat enum. For example:

The Conic Benchmark Format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)
+A Conic Benchmark Format (CBF) model

The LP file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_LP)
+A .LP-file model

The MathOptFormat file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)
+A MathOptFormat Model

The MPS file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)
+A Mathematical Programming System (MPS) model

The NL file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_NL)
+An AMPL (.nl) model

The REW file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_REW)
+A Mathematical Programming System (MPS) model

Note that the REW format is identical to the MPS file format, except that all names are replaced with generic identifiers.

The SDPA file format

julia> model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_SDPA)
+A SemiDefinite Programming Algorithm Format (SDPA) model

Write to file

To write a model src to a MathOptFormat file, use:

julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> MOI.add_variable(src)
+MOI.VariableIndex(1)
+
+julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)
+A MathOptFormat Model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap with 1 entry:
+  MOI.VariableIndex(1) => MOI.VariableIndex(1)
+
+julia> MOI.write_to_file(dest, "file.mof.json")
+
+julia> print(read("file.mof.json", String))
+{
+  "name": "MathOptFormat Model",
+  "version": {
+    "major": 1,
+    "minor": 7
+  },
+  "variables": [
+    {
+      "name": "x1"
+    }
+  ],
+  "objective": {
+    "sense": "feasibility"
+  },
+  "constraints": []
+}

Read from file

To read a MathOptFormat file, use:

julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF)
+A MathOptFormat Model
+
+julia> MOI.read_from_file(dest, "file.mof.json")
+
+julia> MOI.get(dest, MOI.ListOfVariableIndices())
+1-element Vector{MathOptInterface.VariableIndex}:
+ MOI.VariableIndex(1)
+
+julia> rm("file.mof.json")  # Clean up after ourselves.

Detecting the file-type automatically

Instead of the format keyword, you can also use the filename keyword argument to FileFormats.Model. This will attempt to automatically guess the format from the file extension. For example:

julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> dest = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap()
+
+julia> MOI.write_to_file(dest, "file.cbf.gz")
+
+julia> src_2 = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> dest = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap()
+
+julia> MOI.write_to_file(dest, "file.cbf.gz")
+
+julia> src_2 = MOI.FileFormats.Model(filename = "file.cbf.gz")
+A Conic Benchmark Format (CBF) model
+
+julia> MOI.read_from_file(src_2, "file.cbf.gz")
+
+julia> rm("file.cbf.gz")  # Clean up after ourselves.

Note how the compression format (GZip) is also automatically detected from the filename.

Unsupported constraints

In some cases src may contain constraints that are not supported by the file format (for example, the CBF format supports integer variables but not binary). If so, copy src to a bridged model using Bridges.full_bridge_optimizer:

src = MOI.Utilities.Model{Float64}()
+x = MOI.add_variable(model)
+MOI.add_constraint(model, x, MOI.ZeroOne())
+dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF)
+bridged = MOI.Bridges.full_bridge_optimizer(dest, Float64)
+MOI.copy_to(bridged, src)
+MOI.write_to_file(dest, "my_model.cbf")
Note

Even after bridging, it may still not be possible to write the model to file because of unsupported constraints (for example, PSD variables in the LP file format).

Read and write to io

In addition to write_to_file and read_from_file, you can read and write directly from IO streams using Base.write and Base.read!:

julia> src = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
+
+julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)
+A Mathematical Programming System (MPS) model
+
+julia> MOI.copy_to(dest, src)
+MathOptInterface.Utilities.IndexMap()
+
+julia> io = IOBuffer();
+
+julia> write(io, dest)
+
+julia> seekstart(io);
+
+julia> src_2 = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS)
+A Mathematical Programming System (MPS) model
+
+julia> read!(io, src_2);

ScalarNonlinearFunction

By default, reading a .nl or .mof.json that contains nonlinear expressions will create an NLPBlock.

To instead read nonlinear expressions as ScalarNonlinearFunction, pass the use_nlp_block = false keyword argument to the Model constructor:

julia> model = MOI.FileFormats.Model(;
+           format = MOI.FileFormats.FORMAT_MOF,
+           use_nlp_block = false,
+       )
+A MathOptFormat Model
+
+julia> model = MOI.FileFormats.Model(;
+           format = MOI.FileFormats.FORMAT_NL,
+           use_nlp_block = false,
+       )
+An AMPL (.nl) model

Validating MOF files

MathOptFormat files are governed by a schema. Use JSONSchema.jl to check if a .mof.json file satisfies the schema.

First, construct the schema object as follows:

julia> import JSON, JSONSchema
+
+julia> schema = JSONSchema.Schema(JSON.parsefile(MOI.FileFormats.MOF.SCHEMA_PATH))
+A JSONSchema

Then, check if a model file is valid using isvalid:

julia> good_model = JSON.parse("""
+       {
+         "version": {
+           "major": 1,
+           "minor": 5
+         },
+         "variables": [{"name": "x"}],
+         "objective": {"sense": "feasibility"},
+         "constraints": []
+       }
+       """);
+
+julia> isvalid(schema, good_model)
+true

If we construct an invalid file, for example by mis-typing name as NaMe, the validation fails:

julia> bad_model = JSON.parse("""
+       {
+         "version": {
+           "major": 1,
+           "minor": 5
+         },
+         "variables": [{"NaMe": "x"}],
+         "objective": {"sense": "feasibility"},
+         "constraints": []
+       }
+       """);
+
+julia> isvalid(schema, bad_model)
+false

Use JSONSchema.validate to obtain more insight into why the validation failed:

julia> JSONSchema.validate(schema, bad_model)
+Validation failed:
+path:         [variables][1]
+instance:     Dict{String, Any}("NaMe" => "x")
+schema key:   required
+schema value: Any["name"]
diff --git a/previews/PR2418/submodules/FileFormats/reference/index.html b/previews/PR2418/submodules/FileFormats/reference/index.html new file mode 100644 index 0000000000..42e67cab1a --- /dev/null +++ b/previews/PR2418/submodules/FileFormats/reference/index.html @@ -0,0 +1,18 @@ + +API Reference · MathOptInterface

File Formats

Functions to help read and write MOI models to/from various file formats. See The FileFormats submodule for more details.

MathOptInterface.FileFormats.ModelFunction
Model(
+    ;
+    format::FileFormat = FORMAT_AUTOMATIC,
+    filename::Union{Nothing, String} = nothing,
+    kwargs...
+)

Return model corresponding to the FileFormat format, or, if format == FORMAT_AUTOMATIC, guess the format from filename.

The filename argument is only needed if format == FORMAT_AUTOMATIC.

kwargs are passed to the underlying model constructor.

source
MathOptInterface.FileFormats.FileFormatType
FileFormat

List of accepted export formats.

  • FORMAT_AUTOMATIC: try to detect the file format based on the file name
  • FORMAT_CBF: the Conic Benchmark format
  • FORMAT_LP: the LP file format
  • FORMAT_MOF: the MathOptFormat file format
  • FORMAT_MPS: the MPS file format
  • FORMAT_NL: the AMPL .nl file format
  • FORMAT_REW: the .rew file format, which is MPS with generic names
  • FORMAT_SDPA: the SemiDefinite Programming Algorithm format
source
MathOptInterface.FileFormats.LP.ModelType
Model(; kwargs...)

Create an empty instance of FileFormats.LP.Model.

Keyword arguments are:

  • maximum_length::Int=255: the maximum length for the name of a variable. lp_solve 5.0 allows only 16 characters, while CPLEX 12.5+ allow 255.

  • warn::Bool=false: print a warning when variables or constraints are renamed.

source
MathOptInterface.FileFormats.MOF.ModelType
Model(; kwargs...)

Create an empty instance of FileFormats.MOF.Model.

Keyword arguments are:

  • print_compact::Bool=false: print the JSON file in a compact format without spaces or newlines.
  • warn::Bool=false: print a warning when variables or constraints are renamed
  • differentiation_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation = MOI.Nonlinear.SparseReverseMode(): automatic differentiation backend to use when reading models with nonlinear constraints and objectives.
  • use_nlp_block::Bool=true: if true parse "ScalarNonlinearFunction" into an MOI.NLPBlock. If false, "ScalarNonlinearFunction" are parsed as MOI.ScalarNonlinearFunction functions.
source
MathOptInterface.FileFormats.MPS.ModelType
Model(; kwargs...)

Create an empty instance of FileFormats.MPS.Model.

Keyword arguments are:

  • warn::Bool=false: print a warning when variables or constraints are renamed.
  • print_objsense::Bool=false: print the OBJSENSE section when writing
  • generic_names::Bool=false: strip all names in the model and replace them with the generic names C$i and R$i for the i'th column and row respectively.
  • quadratic_format::QuadraticFormat = kQuadraticFormatGurobi: specify the solver-specific extension used when writing the quadratic components of the model. Options are kQuadraticFormatGurobi, kQuadraticFormatCPLEX, and kQuadraticFormatMosek.
source
MathOptInterface.FileFormats.SDPA.ModelType
Model(; number_type::Type = Float64)

Create an empty instance of FileFormats.SDPA.Model{number_type}.

It is important to be aware that the SDPA file format is interpreted in geometric form and not standard conic form. The standard conic form and geometric conic form are two dual standard forms for semidefinite programs (SDPs). The geometric conic form of an SDP is as follows:

\[\begin{align} +& \min_{y \in \mathbb{R}^m} & b^T y +\\ +& \;\;\text{s.t.} & \sum_{i=1}^m A_i y_i - C & \in \mathbb{K} +\end{align}\]

where $\mathcal{K}$ is a cartesian product of nonnegative orthant and positive semidefinite matrices that align with a block diagonal structure shared with the matrices A_i and C.

In other words, the geometric conic form contains free variables and affine constraints in either the nonnegative orthant or the positive semidefinite cone. That is, in the MathOptInterface's terminology, MOI.VectorAffineFunction-in-MOI.Nonnegatives and MOI.VectorAffineFunction-in-MOI.PositiveSemidefiniteConeTriangle constraints.

The corresponding standard conic form of the dual SDP is as follows:

\[\begin{align} +& \max_{X \in \mathbb{K}} & \text{tr}(CX) +\\ +& \;\;\text{s.t.} & \text{tr}(A_iX) & = b_i & i = 1, \ldots, m. +\end{align}\]

In other words, the standard conic form contains nonnegative and positive semidefinite variables with equality constraints. That is, in the MathOptInterface's terminology, MOI.VectorOfVariables-in-MOI.Nonnegatives, MOI.VectorOfVariables-in-MOI.PositiveSemidefiniteConeTriangle and MOI.ScalarAffineFunction-in-MOI.EqualTo constraints.

If a model is in standard conic form, use Dualization.jl to transform it into the geometric conic form before writting it. Otherwise, the nonnegative (resp. positive semidefinite) variables will be bridged into free variables with affine constraints constraining them to belong to the nonnegative orthant (resp. positive semidefinite cone) by the MOI.Bridges.Constraint.VectorFunctionizeBridge. Moreover, equality constraints will be bridged into pairs of affine constraints in the nonnegative orthant by the MOI.Bridges.Constraint.SplitIntervalBridge and then the MOI.Bridges.Constraint.VectorizeBridge.

If a solver is in standard conic form, use Dualization.jl to transform the model read into standard conic form before copying it to the solver. Otherwise, the free variables will be bridged into pairs of variables in the nonnegative orthant by the MOI.Bridges.Variable.FreeBridge and affine constraints will be bridged into equality constraints by creating a slack variable by the MOI.Bridges.Constraint.VectorSlackBridge.

source

Other helpers

MathOptInterface.FileFormats.NL.SolFileResultsType
SolFileResults(filename::String, model::Model)

Parse the .sol file filename created by solving model and return a SolFileResults struct.

The returned struct supports the MOI.get API for querying result attributes such as MOI.TerminationStatus, MOI.VariablePrimal, and MOI.ConstraintDual.

source
SolFileResults(
+    raw_status::String,
+    termination_status::MOI.TerminationStatusCode,
+)

Return a SolFileResults struct with MOI.RawStatusString set to raw_status, MOI.TerminationStatus set to termination_status, and MOI.PrimalStatus and MOI.DualStatus set to NO_SOLUTION.

All other attributes are un-set.

source
diff --git a/previews/PR2418/submodules/Nonlinear/overview/index.html b/previews/PR2418/submodules/Nonlinear/overview/index.html new file mode 100644 index 0000000000..b943b4f44a --- /dev/null +++ b/previews/PR2418/submodules/Nonlinear/overview/index.html @@ -0,0 +1,183 @@ + +Overview · MathOptInterface

Nonlinear

Warning

The Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.

The Nonlinear submodule contains data structures and functions for working with a nonlinear optimization problem in the form of an expression graph. This page explains the API and describes the rationale behind its design.

Standard form

Nonlinear programs (NLPs) are a class of optimization problems in which some of the constraints or the objective function are nonlinear:

\[\begin{align} + \min_{x \in \mathbb{R}^n} & f_0(x) \\ + \;\;\text{s.t.} & l_j \le f_j(x) \le u_j & j = 1 \ldots m +\end{align}\]

There may be additional constraints, as well as things like variable bounds and integrality restrictions, but we do not consider them here because they are best dealt with by other components of MathOptInterface.

API overview

The core element of the Nonlinear submodule is Nonlinear.Model:

julia> const Nonlinear = MOI.Nonlinear;
+
+julia> model = Nonlinear.Model()
+A Nonlinear.Model with:
+ 0 objectives
+ 0 parameters
+ 0 expressions
+ 0 constraints

Nonlinear.Model is a mutable struct that stores all of the nonlinear information added to the model.

Decision variables

Decision variables are represented by VariableIndexes. The user is responsible for creating these using MOI.VariableIndex(i), where i is the column associated with the variable.

Expressions

The input data structure is a Julia Expr. The input expressions can incorporate VariableIndexes, but these must be interpolated into the expression with $:

julia> x = MOI.VariableIndex(1)
+MOI.VariableIndex(1)
+
+julia> input = :(1 + sin($x)^2)
+:(1 + sin(MathOptInterface.VariableIndex(1)) ^ 2)

There are a number of restrictions on the input Expr:

  • It cannot contain macros
  • It cannot contain broadcasting
  • It cannot contain splatting (except in limited situations)
  • It cannot contain linear algebra, such as matrix-vector products
  • It cannot contain generator expressions, including sum(i for i in S)

Given an input expression, add an expression using Nonlinear.add_expression:

julia> expr = Nonlinear.add_expression(model, input)
+MathOptInterface.Nonlinear.ExpressionIndex(1)

The return value, expr, is a Nonlinear.ExpressionIndex that can then be interpolated into other input expressions.

Looking again at model, we see:

julia> model
+A Nonlinear.Model with:
+ 0 objectives
+ 0 parameters
+ 1 expression
+ 0 constraints

Parameters

In addition to constant literals like 1 or 1.23, you can create parameters. Parameters are placeholders whose values can change before passing the expression to the solver. Create a parameter using Nonlinear.add_parameter, which accepts a default value:

julia> p = Nonlinear.add_parameter(model, 1.23)
+MathOptInterface.Nonlinear.ParameterIndex(1)

The return value, p, is a Nonlinear.ParameterIndex that can then be interpolated into other input expressions.

Looking again at model, we see:

julia> model
+A Nonlinear.Model with:
+ 0 objectives
+ 1 parameter
+ 1 expression
+ 0 constraints

Update a parameter as follows:

julia> model[p]
+1.23
+
+julia> model[p] = 4.56
+4.56
+
+julia> model[p]
+4.56

Objectives

Set a nonlinear objective using Nonlinear.set_objective:

julia> Nonlinear.set_objective(model, :($p + $expr + $x))
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 0 constraints

Clear a nonlinear objective by passing nothing:

julia> Nonlinear.set_objective(model, nothing)
+
+julia> model
+A Nonlinear.Model with:
+ 0 objectives
+ 1 parameter
+ 1 expression
+ 0 constraints

But we'll re-add the objective for later:

julia> Nonlinear.set_objective(model, :($p + $expr + $x));

Constraints

Add a constraint using Nonlinear.add_constraint:

julia> c = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.LessThan(2.0))
+MathOptInterface.Nonlinear.ConstraintIndex(1)
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 1 constraint

The return value, c, is a Nonlinear.ConstraintIndex that is a unique identifier for the constraint. Interval constraints are also supported:

julia> c2 = Nonlinear.add_constraint(model, :(1 + sqrt($x)), MOI.Interval(-1.0, 2.0))
+MathOptInterface.Nonlinear.ConstraintIndex(2)
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 2 constraints

Delete a constraint using Nonlinear.delete:

julia> Nonlinear.delete(model, c2)
+
+julia> model
+A Nonlinear.Model with:
+ 1 objective
+ 1 parameter
+ 1 expression
+ 1 constraint

User-defined operators

By default, Nonlinear supports a wide range of univariate and multivariate operators. However, you can also define your own operators by registering them.

Univariate operators

Register a univariate user-defined operator using Nonlinear.register_operator:

julia> f(x) = 1 + sin(x)^2
+f (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_f, 1, f)

Now, you can use :my_f in expressions:

julia> new_expr = Nonlinear.add_expression(model, :(my_f($x + 1)))
+MathOptInterface.Nonlinear.ExpressionIndex(2)

By default, Nonlinear will compute first- and second-derivatives of the registered operator using ForwardDiff.jl. Override this by passing functions which compute the respective derivative:

julia> f′(x) = 2 * sin(x) * cos(x)
+f′ (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_f2, 1, f, f′)

or

julia> f′′(x) = 2 * (cos(x)^2 - sin(x)^2)
+f′′ (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_f3, 1, f, f′, f′′)

Multivariate operators

Register a multivariate user-defined operator using Nonlinear.register_operator:

julia> g(x...) = x[1]^2 + x[1] * x[2] + x[2]^2
+g (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_g, 2, g)

Now, you can use :my_g in expressions:

julia> new_expr = Nonlinear.add_expression(model, :(my_g($x + 1, $x)))
+MathOptInterface.Nonlinear.ExpressionIndex(3)

By default, Nonlinear will compute the gradient of the registered operator using ForwardDiff.jl. (Hessian information is not supported.) Override this by passing a function to compute the gradient:

julia> function ∇g(ret, x...)
+           ret[1] = 2 * x[1] + x[2]
+           ret[2] = x[1] + 2 * x[2]
+           return
+       end
+∇g (generic function with 1 method)
+
+julia> Nonlinear.register_operator(model, :my_g2, 2, g, ∇g)

MathOptInterface

MathOptInterface communicates the nonlinear portion of an optimization problem to solvers using concrete subtypes of AbstractNLPEvaluator, which implement the Nonlinear programming API.

Create an AbstractNLPEvaluator from Nonlinear.Model using Nonlinear.Evaluator.

Nonlinear.Evaluator requires an Nonlinear.AbstractAutomaticDifferentiation backend and an ordered list of the variables that are included in the model.

There following backends are available to choose from within MOI, although other packages may add more options by sub-typing Nonlinear.AbstractAutomaticDifferentiation:

julia> evaluator = Nonlinear.Evaluator(model, Nonlinear.ExprGraphOnly(), [x])
+Nonlinear.Evaluator with available features:
+  * :ExprGraph

The functions of the Nonlinear programming API implemented by Nonlinear.Evaluator depends upon the chosen Nonlinear.AbstractAutomaticDifferentiation backend.

The :ExprGraph feature means we can call objective_expr and constraint_expr to retrieve the expression graph of the problem. However, we cannot call gradient terms such as eval_objective_gradient because Nonlinear.ExprGraphOnly does not have the capability to differentiate a nonlinear expression.

If, instead, we pass Nonlinear.SparseReverseMode, then we get access to :Grad, the gradient of the objective function, :Jac, the Jacobian matrix of the constraints, :JacVec, the ability to compute Jacobian-vector products, and :ExprGraph.

julia> evaluator = Nonlinear.Evaluator(
+           model,
+           Nonlinear.SparseReverseMode(),
+           [x],
+       )
+Nonlinear.Evaluator with available features:
+  * :Grad
+  * :Jac
+  * :JacVec
+  * :ExprGraph

However, before using the evaluator, we need to call initialize:

julia> MOI.initialize(evaluator, [:Grad, :Jac, :JacVec, :ExprGraph])

Now we can call methods like eval_objective:

julia> x = [1.0]
+1-element Vector{Float64}:
+ 1.0
+
+julia> MOI.eval_objective(evaluator, x)
+7.268073418273571

and eval_objective_gradient:

julia> grad = [0.0]
+1-element Vector{Float64}:
+ 0.0
+
+julia> MOI.eval_objective_gradient(evaluator, grad, x)
+
+julia> grad
+1-element Vector{Float64}:
+ 1.909297426825682

Instead of passing Nonlinear.Evaluator directly to solvers, solvers query the NLPBlock attribute, which returns an NLPBlockData. This object wraps an Nonlinear.Evaluator and includes other information such as constraint bounds and whether the evaluator has a nonlinear objective. Create and set NLPBlockData as follows:

julia> block = MOI.NLPBlockData(evaluator);
+
+julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}());
+
+julia> MOI.set(model, MOI.NLPBlock(), block);
Warning

Only call NLPBlockData once you have finished modifying the problem in model.

Putting everything together, you can create a nonlinear optimization problem in MathOptInterface as follows:

import MathOptInterface as MOI
+
+function build_model(
+    model::MOI.ModelLike;
+    backend::MOI.Nonlinear.AbstractAutomaticDifferentiation,
+)
+    x = MOI.add_variable(model)
+    y = MOI.add_variable(model)
+    MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+    nl_model = MOI.Nonlinear.Model()
+    MOI.Nonlinear.set_objective(nl_model, :($x^2 + $y^2))
+    evaluator = MOI.Nonlinear.Evaluator(nl_model, backend, [x, y])
+    MOI.set(model, MOI.NLPBlock(), MOI.NLPBlockData(evaluator))
+    return
+end
+
+# Replace `model` and `backend` with your optimizer and backend of choice.
+model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+build_model(model; backend = MOI.Nonlinear.SparseReverseMode())

Expression-graph representation

Nonlinear.Model stores nonlinear expressions in Nonlinear.Expressions. This section explains the design of the expression graph data structure in Nonlinear.Expression.

Given a nonlinear function like f(x) = sin(x)^2 + x, a conceptual aid for thinking about the graph representation of the expression is to convert it into Polish prefix notation:

f(x, y) = (+ (^ (sin x) 2) x)

This format identifies each operator (function), as well as a list of arguments. Operators can be univariate, like sin, or multivariate, like +.

A common way of representing Polish prefix notation in code is as follows:

julia> x = MOI.VariableIndex(1);
+
+julia> struct ExprNode
+           op::Symbol
+           children::Vector{Union{ExprNode,Float64,MOI.VariableIndex}}
+       end
+
+julia> expr = ExprNode(:+, [ExprNode(:^, [ExprNode(:sin, [x]), 2.0]), x]);

This data structure follows our Polish prefix notation very closely, and we can easily identify the arguments to an operator. However, it has a significant draw-back: each node in the graph requires a Vector, which is heap-allocated and tracked by Julia's garbage collector (GC). For large models, we can expect to have millions of nodes in the expression graph, so this overhead quickly becomes prohibitive for computation.

An alternative is to record the expression as a linear tape:

julia> expr = Any[:+, 2, :^, 2, :sin, 1, x, 2.0, x]
+9-element Vector{Any}:
+  :+
+ 2
+  :^
+ 2
+  :sin
+ 1
+  MOI.VariableIndex(1)
+ 2.0
+  MOI.VariableIndex(1)

The Int after each operator Symbol specifies the number of arguments.

This data-structure is a single vector, which resolves our problem with the GC, but each element is the abstract type, Any, and so any operations on it will lead to slower dynamic dispatch. It's also hard to identify the children of each operation without reading the entire tape.

To summarize, representing expression graphs in Julia has the following challenges:

  • Nodes in the expression graph should not contain a heap-allocated object
  • All data-structures should be concretely typed
  • It should be easy to identify the children of a node

Sketch of the design in Nonlinear

Nonlinear overcomes these problems by decomposing the data structure into a number of different concrete-typed vectors.

First, we create vectors of the supported uni- and multivariate operators.

julia> const UNIVARIATE_OPERATORS = [:sin];
+
+julia> const MULTIVARIATE_OPERATORS = [:+, :^];

In practice, there are many more supported operations than the ones listed here.

Second, we create an enum to represent the different types of nodes present in the expression graph:

julia> @enum(
+           NodeType,
+           NODE_CALL_MULTIVARIATE,
+           NODE_CALL_UNIVARIATE,
+           NODE_VARIABLE,
+           NODE_VALUE,
+       )

In practice, there are node types other than the ones listed here.

Third, we create two concretely typed structs as follows:

julia> struct Node
+           type::NodeType
+           parent::Int
+           index::Int
+       end
+
+julia> struct Expression
+           nodes::Vector{Node}
+           values::Vector{Float64}
+       end

For each node node in the .nodes field, if node.type is:

  • NODE_CALL_MULTIVARIATE, we look up MULTIVARIATE_OPERATORS[node.index] to retrieve the operator
  • NODE_CALL_UNIVARIATE, we look up UNIVARIATE_OPERATORS[node.index] to retrieve the operator
  • NODE_VARIABLE, we create MOI.VariableIndex(node.index)
  • NODE_VALUE, we look up values[node.index]

The .parent field of each node is the integer index of the parent node in .nodes. For the first node, the parent is -1 by convention.

Therefore, we can represent our function as:

julia> expr = Expression(
+           [
+               Node(NODE_CALL_MULTIVARIATE, -1, 1),
+               Node(NODE_CALL_MULTIVARIATE, 1, 2),
+               Node(NODE_CALL_UNIVARIATE, 2, 1),
+               Node(NODE_VARIABLE, 3, 1),
+               Node(NODE_VALUE, 2, 1),
+               Node(NODE_VARIABLE, 1, 1),
+           ],
+           [2.0],
+       );

The ordering of the nodes in the tape must satisfy two rules:

  • The children of a node must appear after the parent. This means that the tape is ordered topologically, so that a reverse pass of the nodes evaluates all children nodes before their parent
  • The arguments for a CALL node are ordered in the tape based on the order in which they appear in the function call.

Design goals

This is less readable than the other options, but does this data structure meet our design goals?

Instead of a heap-allocated object for each node, we only have two Vectors for each expression, nodes and values, as well as two constant vectors for the OPERATORS. In addition, all fields are concretely typed, and there are no Union or Any types.

For our third goal, it is not easy to identify the children of a node, but it is easy to identify the parent of any node. Therefore, we can use Nonlinear.adjacency_matrix to compute a sparse matrix that maps parents to their children.

The design in practice

In practice, Node and Expression are exactly Nonlinear.Node and Nonlinear.Expression. However, Nonlinear.NodeType has more fields to account for comparison operators such as :>= and :<=, logic operators such as :&& and :||, nonlinear parameters, and nested subexpressions.

Moreover, instead of storing the operators as global constants, they are stored in Nonlinear.OperatorRegistry, and it also stores a vector of logic operators and a vector of comparison operators. In addition to Nonlinear.DEFAULT_UNIVARIATE_OPERATORS and Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS, you can register user-defined functions using Nonlinear.register_operator.

Nonlinear.Model is a struct that stores the Nonlinear.OperatorRegistry, as well as a list of parameters and subexpressions in the model.

ReverseAD

Nonlinear.ReverseAD is a submodule for computing derivatives of a nonlinear optimization problem using sparse reverse-mode automatic differentiation (AD).

This section does not attempt to explain how sparse reverse-mode AD works, but instead explains why MOI contains its own implementation, and highlights notable differences from similar packages.

Warning

Don't use the API in ReverseAD to compute derivatives. Instead, create a Nonlinear.Evaluator object with Nonlinear.SparseReverseMode as the backend, and then query the MOI API methods.

Design goals

The JuliaDiff organization maintains a list of packages for doing AD in Julia. At last count, there were at least ten packages——not including ReverseAD——for reverse-mode AD in Julia. ReverseAD exists because it has a different set of design goals.

  • Goal: handle scale and sparsity. The types of nonlinear optimization problems that MOI represents can be large scale (10^5 or more functions across 10^5 or more variables) with very sparse derivatives. The ability to compute a sparse Hessian matrix is essential. To the best of our knowledge, ReverseAD is the only reverse-mode AD system in Julia that handles sparsity by default.
  • Goal: limit the scope to improve robustness. Most other AD packages accept arbitrary Julia functions as input and then trace an expression graph using operator overloading. This means they must deal (or detect and ignore) with control flow, I/O, and other vagaries of Julia. In contrast, ReverseAD only accepts functions in the form of Nonlinear.Expression, which greatly limits the range of syntax that it must deal with. By reducing the scope of what we accept as input to functions relevant for mathematical optimization, we can provide a simpler implementation with various performance optimizations.
  • Goal: provide outputs which match what solvers expect. Other AD packages focus on differentiating individual Julia functions. In contrast, ReverseAD has a very specific use-case: to generate outputs needed by the MOI nonlinear API. This means it needs to efficiently compute sparse Hessians, and it needs subexpression handling to avoid recomputing subexpressions that are shared between functions.

History

ReverseAD started life as ReverseDiffSparse.jl, development of which began in early 2014(!). This was well before the other AD packages started development. Because we had a well-tested, working AD in JuMP, there was less motivation to contribute to and explore other AD packages. The lack of historical interaction also meant that other packages were not optimized for the types of problems that JuMP is built for (that is, large-scale sparse problems). When we first created MathOptInterface, we kept the AD in JuMP to simplify the transition, and post-poned the development of a first-class nonlinear interface in MathOptInterface.

Prior to the introduction of Nonlinear, JuMP's nonlinear implementation was a confusing mix of functions and types spread across the code base and in the private _Derivatives submodule. This made it hard to swap the AD system for another. The main motivation for refactoring JuMP to create the Nonlinear submodule in MathOptInterface was to abstract the interface between JuMP and the AD system, allowing us to swap-in and test new AD systems in the future.

diff --git a/previews/PR2418/submodules/Nonlinear/reference/index.html b/previews/PR2418/submodules/Nonlinear/reference/index.html new file mode 100644 index 0000000000..2e8d593e88 --- /dev/null +++ b/previews/PR2418/submodules/Nonlinear/reference/index.html @@ -0,0 +1,147 @@ + +API Reference · MathOptInterface

Nonlinear Modeling

More information can be found in the Nonlinear section of the manual.

MathOptInterface.NonlinearModule
Nonlinear
Warning

The Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.

source
MathOptInterface.Nonlinear.ModelType
Model()

The core datastructure for representing a nonlinear optimization problem.

It has the following fields:

  • objective::Union{Nothing,Expression} : holds the nonlinear objective function, if one exists, otherwise nothing.
  • expressions::Vector{Expression} : a vector of expressions in the model.
  • constraints::OrderedDict{ConstraintIndex,Constraint} : a map from ConstraintIndex to the corresponding Constraint. An OrderedDict is used instead of a Vector to support constraint deletion.
  • parameters::Vector{Float64} : holds the current values of the parameters.
  • operators::OperatorRegistry : stores the operators used in the model.
source

Expressions

Parameters

MathOptInterface.Nonlinear.add_parameterFunction
add_parameter(model::Model, value::Float64)::ParameterIndex

Add a new parameter to model with the default value value. Returns a ParameterIndex that can be interpolated into other input expressions and used to modify the value of the parameter.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+p = add_parameter(model, 1.2)
+c = add_constraint(model, :($x^2 - $p), MOI.LessThan(0.0))
source

Objectives

MathOptInterface.Nonlinear.set_objectiveFunction
set_objective(model::Model, obj)::Nothing

Parse obj into a Expression and set as the objective function of model.

obj must be a type that is supported by parse_expression.

To remove the objective, pass nothing.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+set_objective(model, :($x^2 + 1))
+set_objective(model, x)
+set_objective(model, nothing)
source

Constraints

MathOptInterface.Nonlinear.add_constraintFunction
add_constraint(
+    model::Model,
+    func,
+    set::Union{
+        MOI.GreaterThan{Float64},
+        MOI.LessThan{Float64},
+        MOI.Interval{Float64},
+        MOI.EqualTo{Float64},
+    },
+)

Parse func and set into a Constraint and add to model. Returns a ConstraintIndex that can be used to delete the constraint or query solution information.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+c = add_constraint(model, :($x^2), MOI.LessThan(1.0))
source
MathOptInterface.Nonlinear.deleteFunction
delete(model::Model, c::ConstraintIndex)::Nothing

Delete the constraint index c from model.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+c = add_constraint(model, :($x^2), MOI.LessThan(1.0))
+delete(model, c)
source

User-defined operators

MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORSConstant
DEFAULT_UNIVARIATE_OPERATORS

The list of univariate operators that are supported by default.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS
+72-element Vector{Symbol}:
+ :+
+ :-
+ :abs
+ :sqrt
+ :cbrt
+ :abs2
+ :inv
+ :log
+ :log10
+ :log2
+ ⋮
+ :airybi
+ :airyaiprime
+ :airybiprime
+ :besselj0
+ :besselj1
+ :bessely0
+ :bessely1
+ :erfcx
+ :dawson
source
MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORSConstant
DEFAULT_MULTIVARIATE_OPERATORS

The list of multivariate operators that are supported by default.

Example

julia> import MathOptInterface as MOI
+
+julia> MOI.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS
+9-element Vector{Symbol}:
+ :+
+ :-
+ :*
+ :^
+ :/
+ :ifelse
+ :atan
+ :min
+ :max
source
MathOptInterface.Nonlinear.register_operatorFunction
register_operator(
+    model::Model,
+    op::Symbol,
+    nargs::Int,
+    f::Function,
+    [∇f::Function],
+    [∇²f::Function],
+)

Register the user-defined operator op with nargs input arguments in model.

Univariate functions

  • f(x::T)::T must be a function that takes a single input argument x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.
  • ∇f(x::T)::T is a function that takes a single input argument x and returns the first derivative of f with respect to x. If ∇²f is not provided, ∇f must support any Real input type T.
  • ∇²f(x::T)::T is a function that takes a single input argument x and returns the second derivative of f with respect to x.

Multivariate functions

  • f(x::T...)::T must be a function that takes a nargs input arguments x and returns the function evaluated at x. If ∇f and ∇²f are not provided, f must support any Real input type T.
  • ∇f(g::AbstractVector{T}, x::T...)::T is a function that takes a cache vector g of length length(x), and fills each element g[i] with the partial derivative of f with respect to x[i].
  • ∇²f(H::AbstractMatrix, x::T...)::T is a function that takes a matrix H and fills the lower-triangular components H[i, j] with the Hessian of f with respect to x[i] and x[j] for i >= j.

Notes for multivariate Hessians

  • H has size(H) == (length(x), length(x)), but you must not access elements H[i, j] for i > j.
  • H is dense, but you do not need to fill structural zeros.
source
MathOptInterface.Nonlinear.eval_multivariate_gradientFunction
eval_multivariate_gradient(
+    registry::OperatorRegistry,
+    op::Symbol,
+    g::AbstractVector{T},
+    x::AbstractVector{T},
+) where {T}

Evaluate the gradient of operator g .= ∇op(x), where op is a multivariate function in registry.

source
MathOptInterface.Nonlinear.eval_multivariate_hessianFunction
eval_multivariate_hessian(
+    registry::OperatorRegistry,
+    op::Symbol,
+    H::AbstractMatrix,
+    x::AbstractVector{T},
+) where {T}

Evaluate the Hessian of operator ∇²op(x), where op is a multivariate function in registry.

The Hessian is stored in the lower-triangular part of the matrix H.

Note

Implementations of the Hessian operators will not fill structural zeros. Therefore, before calling this function you should pre-populate the matrix H with 0.

source

Automatic-differentiation backends

MathOptInterface.Nonlinear.EvaluatorType
Evaluator(
+    model::Model,
+    backend::AbstractAutomaticDifferentiation,
+    ordered_variables::Vector{MOI.VariableIndex},
+)

Create Evaluator, a subtype of MOI.AbstractNLPEvaluator, from Model.

source
MathOptInterface.Nonlinear.SparseReverseModeType
SparseReverseMode() <: AbstractAutomaticDifferentiation

An implementation of AbstractAutomaticDifferentiation that uses sparse reverse-mode automatic differentiation to compute derivatives. Supports all features in the MOI nonlinear interface.

source

Data-structure

MathOptInterface.Nonlinear.NodeType
struct Node
+    type::NodeType
+    index::Int
+    parent::Int
+end

A single node in a nonlinear expression tree. Used by Expression.

See the MathOptInterface documentation for information on how the nodes and values form an expression tree.

source
MathOptInterface.Nonlinear.NodeTypeType
NodeType

An enum describing the possible node types. Each Node has a .index field, which should be interpreted as follows:

  • NODE_CALL_MULTIVARIATE: the index into operators.multivariate_operators
  • NODE_CALL_UNIVARIATE: the index into operators.univariate_operators
  • NODE_LOGIC: the index into operators.logic_operators
  • NODE_COMPARISON: the index into operators.comparison_operators
  • NODE_MOI_VARIABLE: the value of MOI.VariableIndex(index) in the user's space of the model.
  • NODE_VARIABLE: the 1-based index of the internal vector
  • NODE_VALUE: the index into the .values field of Expression
  • NODE_PARAMETER: the index into data.parameters
  • NODE_SUBEXPRESSION: the index into data.expressions
source
MathOptInterface.Nonlinear.ExpressionType
struct Expression
+    nodes::Vector{Node}
+    values::Vector{Float64}
+end

The core type that represents a nonlinear expression. See the MathOptInterface documentation for information on how the nodes and values form an expression tree.

source
MathOptInterface.Nonlinear.ConstraintType
struct Constraint
+    expression::Expression
+    set::Union{
+        MOI.LessThan{Float64},
+        MOI.GreaterThan{Float64},
+        MOI.EqualTo{Float64},
+        MOI.Interval{Float64},
+    }
+end

A type to hold information relating to the nonlinear constraint f(x) in S, where f(x) is defined by .expression, and S is .set.

source
MathOptInterface.Nonlinear.adjacency_matrixFunction
adjacency_matrix(nodes::Vector{Node})

Compute the sparse adjacency matrix describing the parent-child relationships in nodes.

The element (i, j) is true if there is an edge from node[j] to node[i]. Since we get a column-oriented matrix, this gives us a fast way to look up the edges leaving any node (that is, the children).

source
MathOptInterface.Nonlinear.parse_expressionFunction
parse_expression(data::Model, input)::Expression

Parse input into a Expression.

source
parse_expression(
+    data::Model,
+    expr::Expression,
+    input::Any,
+    parent_index::Int,
+)::Expression

Parse input into a Expression, and add it to expr as a child of expr.nodes[parent_index]. Existing subexpressions and parameters are stored in data.

You can extend parsing support to new types of objects by overloading this method with a different type on input::Any.

source
MathOptInterface.Nonlinear.convert_to_exprFunction
convert_to_expr(data::Model, expr::Expression)

Convert the Expression expr into a Julia Expr.

source
convert_to_expr(
+    evaluator::Evaluator,
+    expr::Expression;
+    moi_output_format::Bool,
+)

Convert the Expression expr into a Julia Expr.

If moi_output_format = true:

  • subexpressions will be converted to Julia Expr and substituted into the output expression.
  • the current value of each parameter will be interpolated into the expression
  • variables will be represented in the form x[MOI.VariableIndex(i)]

If moi_output_format = false:

Warning

To use moi_output_format = true, you must have first called MOI.initialize with :ExprGraph as a requested feature.

source
MathOptInterface.Nonlinear.ordinal_indexFunction
ordinal_index(evaluator::Evaluator, c::ConstraintIndex)::Int

Return the 1-indexed value of the constraint index c in evaluator.

Examples

model = Model()
+x = MOI.VariableIndex(1)
+c1 = add_constraint(model, :($x^2), MOI.LessThan(1.0))
+c2 = add_constraint(model, :($x^2), MOI.LessThan(1.0))
+evaluator = Evaluator(model)
+MOI.initialize(evaluator, Symbol[])
+ordinal_index(evaluator, c2)  # Returns 2
+delete(model, c1)
+evaluator = Evaluator(model)
+MOI.initialize(evaluator, Symbol[])
+ordinal_index(model, c2)  # Returns 1
source
diff --git a/previews/PR2418/submodules/Test/overview/index.html b/previews/PR2418/submodules/Test/overview/index.html new file mode 100644 index 0000000000..49b0e0d376 --- /dev/null +++ b/previews/PR2418/submodules/Test/overview/index.html @@ -0,0 +1,166 @@ + +Overview · MathOptInterface

The Test submodule

The Test submodule provides tools to help solvers implement unit tests in order to ensure they implement the MathOptInterface API correctly, and to check for solver-correctness.

We use a centralized repository of tests, so that if we find a bug in one solver, instead of adding a test to that particular repository, we add it here so that all solvers can benefit.

How to test a solver

The skeleton below can be used for the wrapper test file of a solver named FooBar.

# ============================ /test/MOI_wrapper.jl ============================
+module TestFooBar
+
+import FooBar
+using Test
+
+import MathOptInterface as MOI
+
+const OPTIMIZER = MOI.instantiate(
+    MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),
+)
+
+const BRIDGED = MOI.instantiate(
+    MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true),
+    with_bridge_type = Float64,
+)
+
+# See the docstring of MOI.Test.Config for other arguments.
+const CONFIG = MOI.Test.Config(
+    # Modify tolerances as necessary.
+    atol = 1e-6,
+    rtol = 1e-6,
+    # Use MOI.LOCALLY_SOLVED for local solvers.
+    optimal_status = MOI.OPTIMAL,
+    # Pass attributes or MOI functions to `exclude` to skip tests that
+    # rely on this functionality.
+    exclude = Any[MOI.VariableName, MOI.delete],
+)
+
+"""
+    runtests()
+
+This function runs all functions in the this Module starting with `test_`.
+"""
+function runtests()
+    for name in names(@__MODULE__; all = true)
+        if startswith("$(name)", "test_")
+            @testset "$(name)" begin
+                getfield(@__MODULE__, name)()
+            end
+        end
+    end
+end
+
+"""
+    test_runtests()
+
+This function runs all the tests in MathOptInterface.Test.
+
+Pass arguments to `exclude` to skip tests for functionality that is not
+implemented or that your solver doesn't support.
+"""
+function test_runtests()
+    MOI.Test.runtests(
+        BRIDGED,
+        CONFIG,
+        exclude = [
+            "test_attribute_NumberOfThreads",
+            "test_quadratic_",
+        ],
+        # This argument is useful to prevent tests from failing on future
+        # releases of MOI that add new tests. Don't let this number get too far
+        # behind the current MOI release though. You should periodically check
+        # for new tests to fix bugs and implement new features.
+        exclude_tests_after = v"0.10.5",
+    )
+    return
+end
+
+"""
+    test_SolverName()
+
+You can also write new tests for solver-specific functionality. Write each new
+test as a function with a name beginning with `test_`.
+"""
+function test_SolverName()
+    @test MOI.get(FooBar.Optimizer(), MOI.SolverName()) == "FooBar"
+    return
+end
+
+end # module TestFooBar
+
+# This line at tne end of the file runs all the tests!
+TestFooBar.runtests()

Then modify your runtests.jl file to include the MOI_wrapper.jl file:

# ============================ /test/runtests.jl ============================
+
+using Test
+
+@testset "MOI" begin
+    include("test/MOI_wrapper.jl")
+end
Info

The optimizer BRIDGED constructed with instantiate automatically bridges constraints that are not supported by OPTIMIZER using the bridges listed in Bridges. It is recommended for an implementation of MOI to only support constraints that are natively supported by the solver and let bridges transform the constraint to the appropriate form. For this reason it is expected that tests may not pass if OPTIMIZER is used instead of BRIDGED.

How to debug a failing test

When writing a solver, it's likely that you will initially fail many tests. Some failures will be bugs, but other failures you may choose to exclude.

There are two ways to exclude tests:

  • Exclude tests whose names contain a string using:

    MOI.Test.runtests(
    +    model,
    +    config;
    +    exclude = String["test_to_exclude", "test_conic_"],
    +)

    This will exclude tests whose name contains either of the two strings provided.

  • Exclude tests which rely on specific functionality using:

    MOI.Test.Config(exclude = Any[MOI.VariableName, MOI.optimize!])

    This will exclude tests which use the MOI.VariableName attribute, or which call MOI.optimize!.

Each test that fails can be independently called as:

model = FooBar.Optimizer()
+config = MOI.Test.Config()
+MOI.empty!(model)
+MOI.Test.test_category_name_that_failed(model, config)

You can look-up the source code of the test that failed by searching for it in the src/Test/test_category.jl file.

Tip

Each test function also has a docstring that explains what the test is for. Use ? MOI.Test.test_category_name_that_failed from the REPL to read it.

Periodically, you should re-run excluded tests to see if they now pass. The easiest way to do this is to swap the exclude keyword argument of runtests to include. For example:

MOI.Test.runtests(
+    model,
+    config;
+    exclude = String["test_to_exclude", "test_conic_"],
+)

becomes

MOI.Test.runtests(
+    model,
+    config;
+    include = String["test_to_exclude", "test_conic_"],
+)

How to add a test

To detect bugs in solvers, we add new tests to MOI.Test.

As an example, ECOS errored calling optimize! twice in a row. (See ECOS.jl PR #72.) We could add a test to ECOS.jl, but that would only stop us from re-introducing the bug to ECOS.jl in the future, but it would not catch other solvers in the ecosystem with the same bug. Instead, if we add a test to MOI.Test, then all solvers will also check that they handle a double optimize call.

For this test, we care about correctness, rather than performance. therefore, we don't expect solvers to efficiently decide that they have already solved the problem, only that calling optimize! twice doesn't throw an error or give the wrong answer.

Step 1

Install the MathOptInterface julia package in dev mode:

julia> ]
+(@v1.6) pkg> dev MathOptInterface

Step 2

From here on, proceed with making the following changes in the ~/.julia/dev/MathOptInterface folder (or equivalent dev path on your machine).

Step 3

Since the double-optimize error involves solving an optimization problem, add a new test to src/Test/test_solve.jl:

"""
+    test_unit_optimize!_twice(model::MOI.ModelLike, config::Config)
+
+Test that calling `MOI.optimize!` twice does not error.
+
+This problem was first detected in ECOS.jl PR#72:
+https://github.com/jump-dev/ECOS.jl/pull/72
+"""
+function test_unit_optimize!_twice(
+    model::MOI.ModelLike,
+    config::Config{T},
+) where {T}
+    # Use the `@requires` macro to check conditions that the test function
+    # requires to run. Models failing this `@requires` check will silently skip
+    # the test.
+    @requires MOI.supports_constraint(
+        model,
+        MOI.VariableIndex,
+        MOI.GreaterThan{Float64},
+    )
+    @requires _supports(config, MOI.optimize!)
+    # If needed, you can test that the model is empty at the start of the test.
+    # You can assume that this will be the case for tests run via `runtests`.
+    # User's calling tests individually need to call `MOI.empty!` themselves.
+    @test MOI.is_empty(model)
+    # Create a simple model. Try to make this as simple as possible so that the
+    # majority of solvers can run the test.
+    x = MOI.add_variable(model)
+    MOI.add_constraint(model, x, MOI.GreaterThan(one(T)))
+    MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+    MOI.set(
+        model,
+        MOI.ObjectiveFunction{MOI.VariableIndex}(),
+        x,
+    )
+    # The main component of the test: does calling `optimize!` twice error?
+    MOI.optimize!(model)
+    MOI.optimize!(model)
+    # Check we have a solution.
+    @test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMAL
+    # There is a three-argument version of `Base.isapprox` for checking
+    # approximate equality based on the tolerances defined in `config`:
+    @test isapprox(MOI.get(model, MOI.VariablePrimal(), x), one(T), config)
+    # For code-style, these tests should always `return` `nothing`.
+    return
+end
Info

Make sure the function is agnostic to the number type T; don't assume it is a Float64 capable solver.

We also need to write a test for the test. Place this function immediately below the test you just wrote in the same file:

function setup_test(
+    ::typeof(test_unit_optimize!_twice),
+    model::MOI.Utilities.MockOptimizer,
+    ::Config,
+)
+    MOI.Utilities.set_mock_optimize!(
+        model,
+        (mock::MOI.Utilities.MockOptimizer) -> MOIU.mock_optimize!(
+            mock,
+            MOI.OPTIMAL,
+            (MOI.FEASIBLE_POINT, [1.0]),
+        ),
+    )
+    return
+end

Finally, you also need to implement Test.version_added. If we added this test when the latest released version of MOI was v0.10.5, define:

version_added(::typeof(test_unit_optimize!_twice)) = v"0.10.6"

Step 6

Commit the changes to git from ~/.julia/dev/MathOptInterface and submit the PR for review.

Tip

If you need help writing a test, open an issue on GitHub, or ask the Developer Chatroom.

diff --git a/previews/PR2418/submodules/Test/reference/index.html b/previews/PR2418/submodules/Test/reference/index.html new file mode 100644 index 0000000000..d16c74cec7 --- /dev/null +++ b/previews/PR2418/submodules/Test/reference/index.html @@ -0,0 +1,52 @@ + +API Reference · MathOptInterface

The Test submodule

Functions to help test implementations of MOI. See The Test submodule for more details.

MathOptInterface.Test.ConfigType
Config(
+    ::Type{T} = Float64;
+    atol::Real = Base.rtoldefault(T),
+    rtol::Real = Base.rtoldefault(T),
+    optimal_status::MOI.TerminationStatusCode = MOI.OPTIMAL,
+    infeasible_status::MOI.TerminationStatusCode = MOI.INFEASIBLE,
+    exclude::Vector{Any} = Any[],
+) where {T}

Return an object that is used to configure various tests.

Configuration arguments

  • atol::Real = Base.rtoldefault(T): Control the absolute tolerance used when comparing solutions.
  • rtol::Real = Base.rtoldefault(T): Control the relative tolerance used when comparing solutions.
  • optimal_status = MOI.OPTIMAL: Set to MOI.LOCALLY_SOLVED if the solver cannot prove global optimality.
  • infeasible_status = MOI.INFEASIBLE: Set to MOI.LOCALLY_INFEASIBLE if the solver cannot prove global infeasibility.
  • exclude = Vector{Any}: Pass attributes or functions to exclude to skip parts of tests that require certain functionality. Common arguments include:
    • MOI.delete to skip deletion-related tests
    • MOI.optimize! to skip optimize-related tests
    • MOI.ConstraintDual to skip dual-related tests
    • MOI.VariableName to skip setting variable names
    • MOI.ConstraintName to skip setting constraint names

Examples

For a nonlinear solver that finds local optima and does not support finding dual variables or constraint names:

Config(
+    Float64;
+    optimal_status = MOI.LOCALLY_SOLVED,
+    exclude = Any[
+        MOI.ConstraintDual,
+        MOI.VariableName,
+        MOI.ConstraintName,
+        MOI.delete,
+    ],
+)
source
MathOptInterface.Test.runtestsFunction
runtests(
+    model::MOI.ModelLike,
+    config::Config;
+    include::Vector{Union{String,Regex}} = String[],
+    exclude::Vector{Union{String,Regex}} = String[],
+    warn_unsupported::Bool = false,
+    exclude_tests_after::VersionNumber = v"999.0.0",
+    verbose::Bool = false,
+)

Run all tests in MathOptInterface.Test on model.

Configuration arguments

  • config is a Test.Config object that can be used to modify the behavior of tests.
  • If include is not empty, only run tests if an element from include occursin the name of the test.
  • If exclude is not empty, skip tests if an element from exclude occursin the name of the test.
  • exclude takes priority over include.
  • If warn_unsupported is false, runtests will silently skip tests that fail with a MOI.NotAllowedError, MOI.UnsupportedError, or RequirementUnmet error. (The latter is thrown when an @requires statement returns false.) When warn_unsupported is true, a warning will be printed. For most cases the default behavior, false, is what you want, since these tests likely test functionality that is not supported by model. However, it can be useful to run warn_unsupported = true to check you are not skipping tests due to a missing supports_constraint method or equivalent.
  • exclude_tests_after is a version number that excludes any tests to MOI added after that version number. This is useful for solvers who can declare a fixed set of tests, and not cause their tests to break if a new patch of MOI is released with a new test.
  • verbose is a Bool that controls whether the name of the test is printed before executing it. This can be helpful when debugging.

See also: setup_test.

Example

config = MathOptInterface.Test.Config()
+MathOptInterface.Test.runtests(
+    model,
+    config;
+    include = ["test_linear_", r"^test_model_Name$"],
+    exclude = ["VariablePrimalStart"],
+    warn_unsupported = true,
+    verbose = true,
+    exclude_tests_after = v"0.10.5",
+)
source
MathOptInterface.Test.setup_testFunction
setup_test(::typeof(f), model::MOI.ModelLike, config::Config)

Overload this method to modify model before running the test function f on model with config. You can also modify the fields in config (for example, to loosen the default tolerances).

This function should either return nothing, or return a function which, when called with zero arguments, undoes the setup to return the model to its previous state. You do not need to undo any modifications to config.

This function is most useful when writing new tests of the tests for MOI, but it can also be used to set test-specific tolerances, etc.

See also: runtests

Example

function MOI.Test.setup_test(
+    ::typeof(MOI.Test.test_linear_VariablePrimalStart_partial),
+    mock::MOIU.MockOptimizer,
+    ::MOI.Test.Config,
+)
+    MOIU.set_mock_optimize!(
+        mock,
+        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 0.0]),
+    )
+    mock.eval_variable_constraint_dual = false
+
+    function reset_function()
+        mock.eval_variable_constraint_dual = true
+        return
+    end
+    return reset_function
+end
source
MathOptInterface.Test.version_addedFunction
version_added(::typeof(function_name))

Returns the version of MOI in which the test function_name was added.

This method should be implemented for all new tests.

See the exclude_tests_after keyword of runtests for more details.

source
MathOptInterface.Test.@requiresMacro
@requires(x)

Check that the condition x is true. Otherwise, throw an RequirementUnmet error to indicate that the model does not support something required by the test function.

Examples

@requires MOI.supports(model, MOI.Silent())
+@test MOI.get(model, MOI.Silent())
source
diff --git a/previews/PR2418/submodules/Utilities/overview/index.html b/previews/PR2418/submodules/Utilities/overview/index.html new file mode 100644 index 0000000000..a290501fb2 --- /dev/null +++ b/previews/PR2418/submodules/Utilities/overview/index.html @@ -0,0 +1,250 @@ + +Overview · MathOptInterface

The Utilities submodule

The Utilities submodule provides a variety of functions and datastructures for managing MOI.ModelLike objects.

Utilities.Model

Utilities.Model provides an implementation of a ModelLike that efficiently supports all functions and sets defined within MOI. However, given the extensibility of MOI, this might not cover all use cases.

Create a model as follows:

julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}

Utilities.UniversalFallback

Utilities.UniversalFallback is a layer that sits on top of any ModelLike and provides non-specialized (slower) fallbacks for constraints and attributes that the underlying ModelLike does not support.

For example, Utilities.Model doesn't support some variable attributes like VariablePrimalStart, so JuMP uses a combination of Universal fallback and Utilities.Model as a generic problem cache:

julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
+MOIU.UniversalFallback{MOIU.Model{Float64}}
+fallback for MOIU.Model{Float64}
Warning

Adding a UniversalFallback means that your model will now support all constraints, even if the inner-model does not. This can lead to unexpected behavior.

Utilities.@model

For advanced use cases that need efficient support for functions and sets defined outside of MOI (but still known at compile time), we provide the Utilities.@model macro.

The @model macro takes a name (for a new type, which must not exist yet), eight tuples specifying the types of constraints that are supported, and then a Bool indicating the type is a subtype of MOI.AbstractOptimizer (if true) or MOI.ModelLike (if false).

The eight tuples are in the following order:

  1. Un-typed scalar sets, for example, Integer
  2. Typed scalar sets, for example, LessThan
  3. Un-typed vector sets, for example, Nonnegatives
  4. Typed vector sets, for example, PowerCone
  5. Un-typed scalar functions, for example, VariableIndex
  6. Typed scalar functions, for example, ScalarAffineFunction
  7. Un-typed vector functions, for example, VectorOfVariables
  8. Typed vector functions, for example, VectorAffineFunction

The tuples can contain more than one element. Typed-sets must be specified without their type parameter, for example, MOI.LessThan, not MOI.LessThan{Float64}.

Here is an example:

julia> MOI.Utilities.@model(
+           MyNewModel,
+           (MOI.Integer,),                  # Un-typed scalar sets
+           (MOI.GreaterThan,),              # Typed scalar sets
+           (MOI.Nonnegatives,),             # Un-typed vector sets
+           (MOI.PowerCone,),                # Typed vector sets
+           (MOI.VariableIndex,),            # Un-typed scalar functions
+           (MOI.ScalarAffineFunction,),     # Typed scalar functions
+           (MOI.VectorOfVariables,),        # Un-typed vector functions
+           (MOI.VectorAffineFunction,),     # Typed vector functions
+           true,                            # <:MOI.AbstractOptimizer?
+       )
+MathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MyNewModelFunctionConstraints{T}} where T
+
+julia> model = MyNewModel{Float64}()
+MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MyNewModelFunctionConstraints{Float64}}
Warning

MyNewModel supports every VariableIndex-in-Set constraint, as well as VariableIndex, ScalarAffineFunction, and ScalarQuadraticFunction objective functions. Implement MOI.supports as needed to forbid constraint and objective function combinations.

As another example, PATHSolver, which only supports VectorAffineFunction-in-Complements defines its optimizer as:

julia> MOI.Utilities.@model(
+           PathOptimizer,
+           (),  # Scalar sets
+           (),  # Typed scalar sets
+           (MOI.Complements,),  # Vector sets
+           (),  # Typed vector sets
+           (),  # Scalar functions
+           (),  # Typed scalar functions
+           (),  # Vector functions
+           (MOI.VectorAffineFunction,),  # Typed vector functions
+           true,  # is_optimizer
+       )
+MathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.ObjectiveContainer{T}, MathOptInterface.Utilities.VariablesContainer{T}, MathOptInterface.Utilities.VectorOfConstraints{MathOptInterface.VectorAffineFunction{T}, MathOptInterface.Complements}} where T

However, PathOptimizer does not support some VariableIndex-in-Set constraints, so we must explicitly define:

julia> function MOI.supports_constraint(
+           ::PathOptimizer,
+           ::Type{MOI.VariableIndex},
+           ::Type{Union{<:MOI.Semiinteger,MOI.Semicontinuous,MOI.ZeroOne,MOI.Integer}}
+       )
+           return false
+       end

Finally, PATH doesn't support an objective function, so we need to add:

julia> MOI.supports(::PathOptimizer, ::MOI.ObjectiveFunction) = false
Warning

This macro creates a new type, so it must be called from the top-level of a module, for example, it cannot be called from inside a function.

Utilities.CachingOptimizer

A [Utilities.CachingOptimizer] is an MOI layer that abstracts the difference between solvers that support incremental modification (for example, they support adding variables one-by-one), and solvers that require the entire problem in a single API call (for example, they only accept the A, b and c matrices of a linear program).

It has two parts:

  1. A cache, where the model can be built and modified incrementally
  2. An optimizer, which is used to solve the problem
julia> model = MOI.Utilities.CachingOptimizer(
+           MOI.Utilities.Model{Float64}(),
+           PathOptimizer{Float64}(),
+       )
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}

A Utilities.CachingOptimizer may be in one of three possible states:

  • NO_OPTIMIZER: The CachingOptimizer does not have any optimizer.
  • EMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer, and it is not synchronized with the cached model. Modifications are forwarded to the cache, but not to the optimizer.
  • ATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model. Modifications are forwarded to the optimizer. If the optimizer does not support modifications, and error will be thrown.

Use Utilities.attach_optimizer to go from EMPTY_OPTIMIZER to ATTACHED_OPTIMIZER:

julia> MOI.Utilities.attach_optimizer(model)
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state ATTACHED_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}
Info

You must be in ATTACHED_OPTIMIZER to use optimize!.

Use Utilities.reset_optimizer to go from ATTACHED_OPTIMIZER to EMPTY_OPTIMIZER:

julia> MOI.Utilities.reset_optimizer(model)
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}
Info

Calling MOI.empty!(model) also resets the state to EMPTY_OPTIMIZER. So after emptying a model, the modification will only be applied to the cache.

Use Utilities.drop_optimizer to go from any state to NO_OPTIMIZER:

julia> MOI.Utilities.drop_optimizer(model)
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state NO_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer nothing

Pass an empty optimizer to Utilities.reset_optimizer to go from NO_OPTIMIZER to EMPTY_OPTIMIZER:

julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())
+
+julia> model
+MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode AUTOMATIC
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}

Deciding when to attach and reset the optimizer is tedious, and you will often write code like this:

try
+    # modification
+catch
+    MOI.Utilities.reset_optimizer(model)
+    # Re-try modification
+end

To make this easier, Utilities.CachingOptimizer has two modes of operation:

  • AUTOMATIC: The CachingOptimizer changes its state when necessary. Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.
  • MANUAL: The user must change the state of the CachingOptimizer. Attempting to perform an operation in the incorrect state results in an error.

By default, AUTOMATIC mode is chosen. However, you can create a CachingOptimizer in MANUAL mode as follows:

julia> model = MOI.Utilities.CachingOptimizer(
+           MOI.Utilities.Model{Float64}(),
+           MOI.Utilities.MANUAL,
+       )
+MOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}
+in state NO_OPTIMIZER
+in mode MANUAL
+with model cache MOIU.Model{Float64}
+with optimizer nothing
+
+julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}())
+
+julia> model
+MOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}}
+in state EMPTY_OPTIMIZER
+in mode MANUAL
+with model cache MOIU.Model{Float64}
+with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}

Printing

Use print to print the formulation of the model.

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model)
+MOI.VariableIndex(1)
+
+julia> MOI.set(model, MOI.VariableName(), x, "x_var")
+
+julia> MOI.add_constraint(model, x, MOI.ZeroOne())
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)
+
+julia> MOI.set(model, MOI.ObjectiveFunction{typeof(x)}(), x)
+
+julia> MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
+
+julia> print(model)
+Maximize VariableIndex:
+ x_var
+
+Subject to:
+
+VariableIndex-in-ZeroOne
+ x_var ∈ {0, 1}

Use Utilities.latex_formulation to display the model in LaTeX form:

julia> MOI.Utilities.latex_formulation(model)
+$$ \begin{aligned}
+\max\quad & x\_var \\
+\text{Subject to}\\
+ & \text{VariableIndex-in-ZeroOne} \\
+ & x\_var \in \{0, 1\} \\
+\end{aligned} $$
Tip

In IJulia, calling print or ending a cell with Utilities.latex_formulation will render the model in LaTeX.

Utilities.PenaltyRelaxation

Pass Utilities.PenaltyRelaxation to modify to relax the problem by adding penalized slack variables to the constraints. This is helpful when debugging sources of infeasible models.

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> MOI.set(model, MOI.VariableName(), x, "x")
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 2.0)));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 x - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> map[c]
+0.0 + 1.0 MOI.VariableIndex(2)

You can also modify a single constraint using Utilities.ScalarPenaltyRelaxation:

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> MOI.set(model, MOI.VariableName(), x, "x")
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 x - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> f
+0.0 + 1.0 MOI.VariableIndex(2)

Utilities.MatrixOfConstraints

The constraints of Utilities.Model are stored as a vector of tuples of function and set in a Utilities.VectorOfConstraints. Other representations can be used by parameterizing the type Utilities.GenericModel (resp. Utilities.GenericOptimizer). For instance, if all non-VariableIndex constraints are affine, the coefficients of all the constraints can be stored in a single sparse matrix using Utilities.MatrixOfConstraints. The constraints storage can even be customized up to a point where it exactly matches the storage of the solver of interest, in which case copy_to can be implemented for the solver by calling copy_to to this custom model.

For instance, Clp defines the following model:

MOI.Utilities.@product_of_scalar_sets(LP, MOI.EqualTo{T}, MOI.LessThan{T}, MOI.GreaterThan{T})
+const Model = MOI.Utilities.GenericModel{
+    Float64,
+    MOI.Utilities.MatrixOfConstraints{
+        Float64,
+        MOI.Utilities.MutableSparseMatrixCSC{Float64,Cint,MOI.Utilities.ZeroBasedIndexing},
+        MOI.Utilities.Hyperrectangle{Float64},
+        LP{Float64},
+    },
+}

The copy_to operation can now be implemented as follows:

function _copy_to(dest::Optimizer, src::Model)
+    @assert MOI.is_empty(dest)
+    A = src.constraints.coefficients
+    row_bounds = src.constraints.constants
+    Clp_loadProblem(
+        dest,
+        A.n,
+        A.m,
+        A.colptr,
+        A.rowval,
+        A.nzval,
+        src.lower_bound,
+        src.upper_bound,
+        # (...) objective vector (omitted),
+        row_bounds.lower,
+        row_bounds.upper,
+    )
+    # Set objective sense and constant (omitted)
+    return
+end
+
+function MOI.copy_to(dest::Optimizer, src::Model)
+    _copy_to(dest, src)
+    return MOI.Utilities.identity_index_map(src)
+end
+
+function MOI.copy_to(
+    dest::Optimizer,
+    src::MOI.Utilities.UniversalFallback{Model},
+)
+    # Copy attributes from `src` to `dest` and error in case any unsupported
+    # constraints or attributes are set in `UniversalFallback`.
+    return MOI.copy_to(dest, src.model)
+end
+
+function MOI.copy_to(
+    dest::Optimizer,
+    src::MOI.ModelLike,
+)
+    model = Model()
+    index_map = MOI.copy_to(model, src)
+    _copy_to(dest, model)
+    return index_map
+end

ModelFilter

Utilities provides Utilities.ModelFilter as a useful tool to copy a subset of a model. For example, given an infeasible model, we can copy the irreducible infeasible subsystem (for models implementing ConstraintConflictStatus) as follows:

my_filter(::Any) = true
+function my_filter(ci::MOI.ConstraintIndex)
+    status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)
+    return status != MOI.NOT_IN_CONFLICT
+end
+filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
+index_map = MOI.copy_to(dest, filtered_src)

Fallbacks

The value of some attributes can be inferred from the value of other attributes.

For example, the value of ObjectiveValue can be computed using ObjectiveFunction and VariablePrimal.

When a solver gives direct access to an attribute, it is better to return this value. However, if this is not the case, Utilities.get_fallback can be used instead. For example:

function MOI.get(model::Optimizer, attr::MOI.ObjectiveFunction)
+    return MOI.Utilities.get_fallback(model, attr)
+end

DoubleDicts

When writing MOI interfaces, we often need to handle situations in which we map ConstraintIndexs to different values. For example, to a string for ConstraintName.

One option is to use a dictionary like Dict{MOI.ConstraintIndex,String}. However, this incurs a performance cost because the key is not a concrete type.

The DoubleDicts submodule helps this situation by providing two types main types Utilities.DoubleDicts.DoubleDict and Utilities.DoubleDicts.IndexDoubleDict. These types act like normal dictionaries, but internally they use more efficient dictionaries specialized to the type of the function-set pair.

The most common usage of a DoubleDict is in the index_map returned by copy_to. Performance can be improved, by using a function barrier. That is, instead of code like:

index_map = MOI.copy_to(dest, src)
+for (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())
+    for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())
+        dest_ci = index_map[ci]
+        # ...
+    end
+end

use instead:

function function_barrier(
+    dest,
+    src,
+    index_map::MOI.Utilities.DoubleDicts.IndexDoubleDictInner{F,S},
+) where {F,S}
+    for ci in MOI.get(src, MOI.ListOfConstraintIndices{F,S}())
+        dest_ci = index_map[ci]
+        # ...
+    end
+    return
+end
+
+index_map = MOI.copy_to(dest, src)
+for (F, S) in MOI.get(src, MOI.ListOfConstraintTypesPresent())
+    function_barrier(dest, src, index_map[F, S])
+end
diff --git a/previews/PR2418/submodules/Utilities/reference/index.html b/previews/PR2418/submodules/Utilities/reference/index.html new file mode 100644 index 0000000000..ac41529202 --- /dev/null +++ b/previews/PR2418/submodules/Utilities/reference/index.html @@ -0,0 +1,296 @@ + +API Reference · MathOptInterface

Utilities.Model

MathOptInterface.Utilities.ModelType
MOI.Utilities.Model{T}() where {T}

An implementation of ModelLike that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.

Examples

julia> import MathOptInterface as MOI
+
+julia> model = MOI.Utilities.Model{Float64}()
+MOIU.Model{Float64}
source

Utilities.UniversalFallback

MathOptInterface.Utilities.UniversalFallbackType
UniversalFallback

The UniversalFallback can be applied on a MOI.ModelLike model to create the model UniversalFallback(model) supporting any constraint and attribute. This allows to have a specialized implementation in model for performance critical constraints and attributes while still supporting other attributes with a small performance penalty. Note that model is unaware of constraints and attributes stored by UniversalFallback so this is not appropriate if model is an optimizer (for this reason, MOI.optimize! has not been implemented). In that case, optimizer bridges should be used instead.

source

Utilities.@model

MathOptInterface.Utilities.@modelMacro
macro model(
+    model_name,
+    scalar_sets,
+    typed_scalar_sets,
+    vector_sets,
+    typed_vector_sets,
+    scalar_functions,
+    typed_scalar_functions,
+    vector_functions,
+    typed_vector_functions,
+    is_optimizer = false
+)

Creates a type model_name implementing the MOI model interface and supporting all combinations of the provided functions and sets.

Each typed_ scalar/vector sets/functions argument is a tuple of types. A type is "typed" if it has a coefficient {T} as the first type parameter.

Tuple syntax

To give no set/function, write (). To give one set or function X, write (X,).

is_optimizer

If is_optimizer = true, the resulting struct is a of GenericOptimizer, which is a subtype of MOI.AbstractOptimizer, otherwise, it is a GenericModel, which is a subtype of MOI.ModelLike.

VariableIndex

Examples

The model describing a linear program would be:

@model(
+    LPModel,                                          # model_name
+    (),                                               # untyped scalar sets
+    (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), #   typed scalar sets
+    (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives),  # untyped vector sets
+    (),                                               #   typed vector sets
+    (),                                               # untyped scalar functions
+    (MOI.ScalarAffineFunction,),                      #   typed scalar functions
+    (MOI.VectorOfVariables,),                         # untyped vector functions
+    (MOI.VectorAffineFunction,),                      #   typed vector functions
+    false,                                            # is_optimizer
+)
source
MathOptInterface.Utilities.GenericModelType
mutable struct GenericModel{T,O,V,C} <: AbstractModelLike{T}

Implements a model supporting coefficients of type T and:

  • An objective function stored in .objective::O
  • Variables and VariableIndex constraints stored in .variable_bounds::V
  • F-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C

All interactions take place via the MOI interface, so the types O, V, and C must implement the API as needed for their functionality.

source
MathOptInterface.Utilities.GenericOptimizerType
mutable struct GenericOptimizer{T,O,V,C} <: AbstractOptimizer{T}

Implements a model supporting coefficients of type T and:

  • An objective function stored in .objective::O
  • Variables and VariableIndex constraints stored in .variable_bounds::V
  • F-in-S constraints (excluding VariableIndex constraints) stored in .constraints::C

All interactions take place via the MOI interface, so the types O, V, and C must implement the API as needed for their functionality.

source

.objective

.variables

MathOptInterface.Utilities.VariablesContainerType
struct VariablesContainer{T} <: AbstractVectorBounds
+    set_mask::Vector{UInt16}
+    lower::Vector{T}
+    upper::Vector{T}
+end

A struct for storing variables and VariableIndex-related constraints. Used in MOI.Utilities.Model by default.

source
MathOptInterface.Utilities.FreeVariablesType
mutable struct FreeVariables <: MOI.ModelLike
+    n::Int64
+    FreeVariables() = new(0)
+end

A struct for storing free variables that can be used as the variables field of GenericModel or GenericModel. It represents a model that does not support any constraint nor objective function.

Example

The following model type represents a conic model in geometric form. As opposed to VariablesContainer, FreeVariables does not support constraint bounds so they are bridged into an affine constraint in the MOI.Nonnegatives cone as expected for the geometric conic form.

julia> MOI.Utilities.@product_of_sets(
+    Cones,
+    MOI.Zeros,
+    MOI.Nonnegatives,
+    MOI.SecondOrderCone,
+    MOI.PositiveSemidefiniteConeTriangle,
+);
+
+julia> const ConicModel{T} = MOI.Utilities.GenericOptimizer{
+    T,
+    MOI.Utilities.ObjectiveContainer{T},
+    MOI.Utilities.FreeVariables,
+    MOI.Utilities.MatrixOfConstraints{
+        T,
+        MOI.Utilities.MutableSparseMatrixCSC{
+            T,
+            Int,
+            MOI.Utilities.OneBasedIndexing,
+        },
+        Vector{T},
+        Cones{T},
+    },
+};
+
+julia> model = MOI.instantiate(ConicModel{Float64}, with_bridge_type=Float64);
+
+julia> x = MOI.add_variable(model)
+MathOptInterface.VariableIndex(1)
+
+julia> c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))
+MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
+
+julia> MOI.Bridges.is_bridged(model, c)
+true
+
+julia> bridge = MOI.Bridges.bridge(model, c)
+MathOptInterface.Bridges.Constraint.VectorizeBridge{Float64, MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives, MathOptInterface.VariableIndex}(MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1), 1.0)
+
+julia> bridge.vector_constraint
+MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
+
+julia> MOI.Bridges.is_bridged(model, bridge.vector_constraint)
+false
source

.constraints

MathOptInterface.Utilities.VectorOfConstraintsType
mutable struct VectorOfConstraints{
+    F<:MOI.AbstractFunction,
+    S<:MOI.AbstractSet,
+} <: MOI.ModelLike
+    constraints::CleverDicts.CleverDict{
+        MOI.ConstraintIndex{F,S},
+        Tuple{F,S},
+        typeof(CleverDicts.key_to_index),
+        typeof(CleverDicts.index_to_key),
+    }
+end

A struct storing F-in-S constraints as a mapping between the constraint indices to the corresponding tuple of function and set.

source
MathOptInterface.Utilities.@struct_of_constraints_by_function_typesMacro
Utilities.@struct_of_constraints_by_function_types(name, func_types...)

Given a vector of n function types (F1, F2,..., Fn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of function type Fi.

The expression Fi can also be a union in which case any constraint for which the function type is in the union is stored in the field with type Ci.

source
MathOptInterface.Utilities.@struct_of_constraints_by_set_typesMacro
Utilities.@struct_of_constraints_by_set_types(name, func_types...)

Given a vector of n set types (S1, S2,..., Sn) in func_types, defines a subtype of StructOfConstraints of name name and which type parameters {T, C1, C2, ..., Cn}. It contains n field where the ith field has type Ci and stores the constraints of set type Si. The expression Si can also be a union in which case any constraint for which the set type is in the union is stored in the field with type Ci. This can be useful if Ci is a MatrixOfConstraints in order to concatenate the coefficients of constraints of several different set types in the same matrix.

source
MathOptInterface.Utilities.struct_of_constraint_codeFunction
struct_of_constraint_code(struct_name, types, field_types = nothing)

Given a vector of n Union{SymbolFun,_UnionSymbolFS{SymbolFun}} or Union{SymbolSet,_UnionSymbolFS{SymbolSet}} in types, defines a subtype of StructOfConstraints of name name and which type parameters {T, F1, F2, ..., Fn} if field_types is nothing and a {T} otherwise. It contains n field where the ith field has type Ci if field_types is nothing and type field_types[i] otherwise. If types is vector of Union{SymbolFun,_UnionSymbolFS{SymbolFun}} (resp. Union{SymbolSet,_UnionSymbolFS{SymbolSet}}) then the constraints of that function (resp. set) type are stored in the corresponding field.

This function is used by the macros @model, @struct_of_constraints_by_function_types and @struct_of_constraints_by_set_types.

source

Caching optimizer

MathOptInterface.Utilities.CachingOptimizerType
CachingOptimizer

CachingOptimizer is an intermediate layer that stores a cache of the model and links it with an optimizer. It supports incremental model construction and modification even when the optimizer doesn't.

Constructors

    CachingOptimizer(cache::MOI.ModelLike, optimizer::AbstractOptimizer)

Creates a CachingOptimizer in AUTOMATIC mode, with the optimizer optimizer.

The type of the optimizer returned is CachingOptimizer{typeof(optimizer), typeof(cache)} so it does not support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.

    CachingOptimizer(cache::MOI.ModelLike, mode::CachingOptimizerMode)

Creates a CachingOptimizer in the NO_OPTIMIZER state and mode mode.

The type of the optimizer returned is CachingOptimizer{MOI.AbstractOptimizer,typeof(cache)} so it does support the function reset_optimizer(::CachingOptimizer, new_optimizer) if the type of new_optimizer is different from the type of optimizer.

About the type

States

A CachingOptimizer may be in one of three possible states (CachingOptimizerState):

  • NO_OPTIMIZER: The CachingOptimizer does not have any optimizer.
  • EMPTY_OPTIMIZER: The CachingOptimizer has an empty optimizer. The optimizer is not synchronized with the cached model.
  • ATTACHED_OPTIMIZER: The CachingOptimizer has an optimizer, and it is synchronized with the cached model.

Modes

A CachingOptimizer has two modes of operation (CachingOptimizerMode):

  • MANUAL: The only methods that change the state of the CachingOptimizer are Utilities.reset_optimizer, Utilities.drop_optimizer, and Utilities.attach_optimizer. Attempting to perform an operation in the incorrect state results in an error.
  • AUTOMATIC: The CachingOptimizer changes its state when necessary. For example, optimize! will automatically call attach_optimizer (an optimizer must have been previously set). Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to EMPTY_OPTIMIZER mode.
source
MathOptInterface.Utilities.attach_optimizerFunction
attach_optimizer(model::CachingOptimizer)

Attaches the optimizer to model, copying all model data into it. Can be called only from the EMPTY_OPTIMIZER state. If the copy succeeds, the CachingOptimizer will be in state ATTACHED_OPTIMIZER after the call, otherwise an error is thrown; see MOI.copy_to for more details on which errors can be thrown.

source
MathOptInterface.Utilities.reset_optimizerFunction
reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)

Sets or resets m to have the given empty optimizer optimizer.

Can be called from any state. An assertion error will be thrown if optimizer is not empty.

The CachingOptimizer m will be in state EMPTY_OPTIMIZER after the call.

source
reset_optimizer(m::CachingOptimizer)

Detaches and empties the current optimizer. Can be called from ATTACHED_OPTIMIZER or EMPTY_OPTIMIZER state. The CachingOptimizer will be in state EMPTY_OPTIMIZER after the call.

source

Mock optimizer

Printing

MathOptInterface.Utilities.latex_formulationFunction
latex_formulation(model::MOI.ModelLike; kwargs...)

Wrap model in a type so that it can be pretty-printed as text/latex in a notebook like IJulia, or in Documenter.

To render the model, end the cell with latex_formulation(model), or call display(latex_formulation(model)) in to force the display of the model from inside a function.

Possible keyword arguments are:

  • simplify_coefficients : Simplify coefficients if possible by omitting them or removing trailing zeros.
  • default_name : The name given to variables with an empty name.
  • print_types : Print the MOI type of each function and set for clarity.
source

Copy utilities

MathOptInterface.Utilities.ModelFilterType
ModelFilter(filter::Function, model::MOI.ModelLike)

A layer to filter out various components of model.

The filter function takes a single argument, which is each element from the list returned by the attributes below. It returns true if the element should be visible in the filtered model and false otherwise.

The components that are filtered are:

  • Entire constraint types via:
    • MOI.ListOfConstraintTypesPresent
  • Individual constraints via:
    • MOI.ListOfConstraintIndices{F,S}
  • Specific attributes via:
    • MOI.ListOfModelAttributesSet
    • MOI.ListOfConstraintAttributesSet
    • MOI.ListOfVariableAttributesSet
Warning

The list of attributes filtered may change in a future release. You should write functions that are generic and not limited to the five types listed above. Thus, you should probably define a fallback filter(::Any) = true.

See below for examples of how this works.

Note

This layer has a limited scope. It is intended by be used in conjunction with MOI.copy_to.

Example: copy model excluding integer constraints

Use the do syntax to provide a single function.

filtered_src = MOI.Utilities.ModelFilter(src) do item
+    return item != (MOI.VariableIndex, MOI.Integer)
+end
+MOI.copy_to(dest, filtered_src)

Example: copy model excluding names

Use type dispatch to simplify the implementation:

my_filter(::Any) = true  # Note the generic fallback
+my_filter(::MOI.VariableName) = false
+my_filter(::MOI.ConstraintName) = false
+filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
+MOI.copy_to(dest, filtered_src)

Example: copy irreducible infeasible subsystem

my_filter(::Any) = true  # Note the generic fallback
+function my_filter(ci::MOI.ConstraintIndex)
+    status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)
+    return status != MOI.NOT_IN_CONFLICT
+end
+filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
+MOI.copy_to(dest, filtered_src)
source
MathOptInterface.Utilities.loadfromstring!Function
loadfromstring!(model, s)

A utility function to aid writing tests.

Warning

This function is not intended for widespread use. It is mainly used as a tool to simplify writing tests in MathOptInterface. Do not use it as an exchange format for storing or transmitting problem instances. Use the FileFormats submodule instead.

Example

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> MOI.Utilities.loadfromstring!(model, """
+       variables: x, y, z
+       constrainedvariable: [a, b, c] in Nonnegatives(3)
+       minobjective::Float64: 2x + 3y
+       con1: x + y <= 1.0
+       con2: [x, y] in Nonnegatives(2)
+       x >= 0.0
+       """)

Notes

Special labels are:

  • variables
  • minobjective
  • maxobjectives

Everything else denotes a constraint with a name.

Append ::T to use an element type of T when parsing the function.

Do not name VariableIndex constraints.

Exceptions

  • x - y does NOT currently parse. Instead, write x + -1.0 * y.
  • x^2 does NOT currently parse. Instead, write x * x.
source

Penalty relaxation

MathOptInterface.Utilities.PenaltyRelaxationType
PenaltyRelaxation(
+    penalties = Dict{MOI.ConstraintIndex,Float64}();
+    default::Union{Nothing,T} = 1.0,
+)

A problem modifier that, when passed to MOI.modify, destructively modifies the model in-place to create a penalized relaxation of the constraints.

Warning

This is a destructive routine that modifies the model in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.

Reformulation

See Utilities.ScalarPenaltyRelaxation for details of the reformulation.

For each constraint ci, the penalty passed to Utilities.ScalarPenaltyRelaxation is get(penalties, ci, default). If the value is nothing, because ci does not exist in penalties and default = nothing, then the constraint is skipped.

Return value

MOI.modify(model, PenaltyRelaxation()) returns a Dict{MOI.ConstraintIndex,MOI.ScalarAffineFunction} that maps each constraint index to the corresponding y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of these functions to compute the violation of each constraint.

Relax a subset of constraints

To relax a subset of constraints, pass a penalties dictionary and set default = nothing.

Supported constraint types

The penalty relaxation is currently limited to modifying MOI.ScalarAffineFunction and MOI.ScalarQuadraticFunction constraints in the linear sets MOI.LessThan, MOI.GreaterThan, MOI.EqualTo and MOI.Interval.

It does not include variable bound or integrality constraints, because these cannot be modified in-place.

To modify variable bounds, rewrite them as linear constraints.

Examples

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(default = 2.0));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> map[c] isa MOI.ScalarAffineFunction{Float64}
+true
julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 3.0)));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 3.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> map[c] isa MOI.ScalarAffineFunction{Float64}
+true
source
MathOptInterface.Utilities.ScalarPenaltyRelaxationType
ScalarPenaltyRelaxation(penalty::T) where {T}

A problem modifier that, when passed to MOI.modify, destructively modifies the constraint in-place to create a penalized relaxation of the constraint.

Warning

This is a destructive routine that modifies the constraint in-place. If you don't want to modify the original model, use JuMP.copy_model to create a copy before calling MOI.modify.

Reformulation

The penalty relaxation modifies constraints of the form $f(x) \in S$ into $f(x) + y - z \in S$, where $y, z \ge 0$, and then it introduces a penalty term into the objective of $a \times (y + z)$ (if minimizing, else $-a$), where $a$ is penalty

When S is MOI.LessThan or MOI.GreaterThan, we omit y or z respectively as a performance optimization.

Return value

MOI.modify(model, ci, ScalarPenaltyRelaxation(penalty)) returns y + z as a MOI.ScalarAffineFunction. In an optimal solution, query the value of this function to compute the violation of the constraint.

Examples

julia> model = MOI.Utilities.Model{Float64}();
+
+julia> x = MOI.add_variable(model);
+
+julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
+
+julia> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));
+
+julia> print(model)
+Minimize ScalarAffineFunction{Float64}:
+ 0.0 + 2.0 v[2]
+
+Subject to:
+
+ScalarAffineFunction{Float64}-in-LessThan{Float64}
+ 0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
+
+VariableIndex-in-GreaterThan{Float64}
+ v[2] >= 0.0
+
+julia> f isa MOI.ScalarAffineFunction{Float64}
+true
source

MatrixOfConstraints

MathOptInterface.Utilities.MatrixOfConstraintsType
mutable struct MatrixOfConstraints{T,AT,BT,ST} <: MOI.ModelLike
+    coefficients::AT
+    constants::BT
+    sets::ST
+    caches::Vector{Any}
+    are_indices_mapped::Vector{BitSet}
+    final_touch::Bool
+end

Represent ScalarAffineFunction and VectorAffinefunction constraints in a matrix form where the linear coefficients of the functions are stored in the coefficients field, the constants of the functions or sets are stored in the constants field. Additional information about the sets are stored in the sets field.

This model can only be used as the constraints field of a MOI.Utilities.AbstractModel.

When the constraints are added, they are stored in the caches field. They are only loaded in the coefficients and constants fields once MOI.Utilities.final_touch is called. For this reason, MatrixOfConstraints should not be used by an incremental interface. Use MOI.copy_to instead.

The constraints can be added in two different ways:

  1. With add_constraint, in which case a canonicalized copy of the function is stored in caches.
  2. With pass_nonvariable_constraints, in which case the functions and sets are stored themselves in caches without mapping the variable indices. The corresponding index in caches is added in are_indices_mapped. This avoids doing a copy of the function in case the getter of CanonicalConstraintFunction does not make a copy for the source model, for example, this is the case of VectorOfConstraints.

We illustrate this with an example. Suppose a model is copied from a src::MOI.Utilities.Model to a bridged model with a MatrixOfConstraints. For all the types that are not bridged, the constraints will be copied with pass_nonvariable_constraints. Hence the functions stored in caches are exactly the same as the ones stored in src. This is ok since this is only during the copy_to operation during which src cannot be modified. On the other hand, for the types that are bridged, the functions added may contain duplicates even if the functions did not contain duplicates in src so duplicates are removed with MOI.Utilities.canonical.

Interface

The .coefficients::AT type must implement:

The .constants::BT type must implement:

The .sets::ST type must implement:

source

.coefficients

MathOptInterface.Utilities.load_termsFunction
load_terms(coefficients, index_map, func, offset)::Nothing

Loads the terms of func to coefficients, mapping the variable indices with index_map.

The ith dimension of func is loaded at the (offset + i)th row of coefficients.

The function must be allocated first with allocate_terms.

The function func must be canonicalized, see is_canonical.

source
MathOptInterface.Utilities.final_touchFunction
final_touch(coefficients)::Nothing

Informs the coefficients that all functions have been added with load_terms. No more modification is allowed unless MOI.empty! is called.

final_touch(sets)::Nothing

Informs the sets that all functions have been added with add_set. No more modification is allowed unless MOI.empty! is called.

source
MathOptInterface.Utilities.extract_functionFunction
extract_function(coefficients, row::Integer, constant::T) where {T}

Return the MOI.ScalarAffineFunction{T} function corresponding to row row in coefficients.

extract_function(
+    coefficients,
+    rows::UnitRange,
+    constants::Vector{T},
+) where{T}

Return the MOI.VectorAffineFunction{T} function corresponding to rows rows in coefficients.

source
MathOptInterface.Utilities.MutableSparseMatrixCSCType
mutable struct MutableSparseMatrixCSC{Tv,Ti<:Integer,I<:AbstractIndexing}
+    indexing::I
+    m::Int
+    n::Int
+    colptr::Vector{Ti}
+    rowval::Vector{Ti}
+    nzval::Vector{Tv}
+    nz_added::Vector{Ti}
+end

Matrix type loading sparse matrices in the Compressed Sparse Column format. The indexing used is indexing, see AbstractIndexing. The other fields have the same meaning than for SparseArrays.SparseMatrixCSC except that the indexing is different unless indexing is OneBasedIndexing. In addition, nz_added is used to cache the number of non-zero terms that have been added to each column due to the incremental nature of load_terms.

The matrix is loaded in 5 steps:

  1. MOI.empty! is called.
  2. MOI.Utilities.add_column and MOI.Utilities.allocate_terms are called in any order.
  3. MOI.Utilities.set_number_of_rows is called.
  4. MOI.Utilities.load_terms is called for each affine function.
  5. MOI.Utilities.final_touch is called.
source
MathOptInterface.Utilities.ZeroBasedIndexingType
struct ZeroBasedIndexing <: AbstractIndexing end

Zero-based indexing: the ith row or column has index i - 1. This is useful when the vectors of row and column indices need to be communicated to a library using zero-based indexing such as C libraries.

source

.constants

MathOptInterface.Utilities.load_constantsFunction
load_constants(constants, offset, func_or_set)::Nothing

This function loads the constants of func_or_set in constants at an offset of offset. Where offset is the sum of the dimensions of the constraints already loaded. The storage should be preallocated with resize! before calling this function.

This function should be implemented to be usable as storage of constants for MatrixOfConstraints.

The constants are loaded in three steps:

  1. Base.empty! is called.
  2. Base.resize! is called with the sum of the dimensions of all constraints.
  3. MOI.Utilities.load_constants is called for each function for vector constraint or set for scalar constraint.
source

.sets

MathOptInterface.Utilities.set_indexFunction
set_index(sets, ::Type{S})::Union{Int,Nothing} where {S<:MOI.AbstractSet}

Return an integer corresponding to the index of the set type in the list given by set_types.

If S is not part of the list, return nothing.

source
MathOptInterface.Utilities.add_setFunction
add_set(sets, i)::Int64

Add a scalar set of type index i.

add_set(sets, i, dim)::Int64

Add a vector set of type index i and dimension dim.

Both methods return a unique Int64 of the set that can be used to reference this set.

source
MathOptInterface.Utilities.rowsFunction
rows(sets, ci::MOI.ConstraintIndex)::Union{Int,UnitRange{Int}}

Return the rows in 1:MOI.dimension(sets) corresponding to the set of id ci.value.

For scalar sets, this returns an Int. For vector sets, this returns an UnitRange{Int}.

source
MathOptInterface.Utilities.num_rowsFunction
num_rows(sets::OrderedProductOfSets, ::Type{S}) where {S}

Return the number of rows corresponding to a set of type S. That is, it is the sum of the dimensions of the sets of type S.

source

Fallbacks

MathOptInterface.Utilities.get_fallbackFunction
get_fallback(model::MOI.ModelLike, ::MOI.ObjectiveValue)

Compute the objective function value using the VariablePrimal results and the ObjectiveFunction value.

source
get_fallback(
+    model::MOI.ModelLike,
+    ::MOI.DualObjectiveValue,
+    ::Type{T},
+)::T where {T}

Compute the dual objective value of type T using the ConstraintDual results and the ConstraintFunction and ConstraintSet values.

Note that the nonlinear part of the model is ignored.

source
get_fallback(
+    model::MOI.ModelLike,
+    ::MOI.ConstraintPrimal,
+    constraint_index::MOI.ConstraintIndex,
+)

Compute the value of the function of the constraint of index constraint_index using the VariablePrimal results and the ConstraintFunction values.

source
get_fallback(
+    model::MOI.ModelLike,
+    attr::MOI.ConstraintDual,
+    ci::MOI.ConstraintIndex{Union{MOI.VariableIndex,MOI.VectorOfVariables}},
+    ::Type{T} = Float64,
+) where {T}

Compute the dual of the constraint of index ci using the ConstraintDual of other constraints and the ConstraintFunction values.

Throws an error if some constraints are quadratic or if there is one another MOI.VariableIndex-in-S or MOI.VectorOfVariables-in-S constraint with one of the variables in the function of the constraint ci.

source

Function utilities

The following utilities are available for functions:

MathOptInterface.Utilities.eval_variablesFunction
eval_variables(value_fn::Function, f::MOI.AbstractFunction)

Returns the value of function f if each variable index vi is evaluated as value_fn(vi).

Note that value_fn must return a Number. See substitute_variables for a similar function where value_fn returns an MOI.AbstractScalarFunction.

Warning

The two-argument version of eval_variables is deprecated and may be removed in MOI v2.0.0. Use the three-argument method eval_variables(::Function, ::MOI.ModelLike, ::MOI.AbstractFunction) instead.

source
MathOptInterface.Utilities.map_indicesFunction
map_indices(index_map::Function, attr::MOI.AnyAttribute, x::X)::X where {X}

Substitute any MOI.VariableIndex (resp. MOI.ConstraintIndex) in x by the MOI.VariableIndex (resp. MOI.ConstraintIndex) of the same type given by index_map(x).

When to implement this method for new types X

This function is used by implementations of MOI.copy_to on constraint functions, attribute values and submittable values. If you define a new attribute whose values x::X contain variable or constraint indices, you must also implement this function.

source
map_indices(
+    variable_map::AbstractDict{T,T},
+    x::X,
+)::X where {T<:MOI.Index,X}

Shortcut for map_indices(vi -> variable_map[vi], x).

source
MathOptInterface.Utilities.substitute_variablesFunction
substitute_variables(variable_map::Function, x)

Substitute any MOI.VariableIndex in x by variable_map(x). The variable_map function returns either MOI.VariableIndex or MOI.ScalarAffineFunction, see eval_variables for a similar function where variable_map returns a number.

This function is used by bridge optimizers on constraint functions, attribute values and submittable values when at least one variable bridge is used hence it needs to be implemented for custom types that are meant to be used as attribute or submittable value.

Note

When implementing a new method, don't use substitute_variables(::Function, because Julia will not specialize on it. Use instead substitute_variables(::F, ...) where {F<:Function}.

source
MathOptInterface.Utilities.filter_variablesFunction
filter_variables(keep::Function, f::AbstractFunction)

Return a new function f with the variable vi such that !keep(vi) removed.

WARNING: Don't define filter_variables(::Function, ...) because Julia will not specialize on this. Define instead filter_variables(::F, ...) where {F<:Function}.

source
MathOptInterface.Utilities.remove_variableFunction
remove_variable(f::AbstractFunction, vi::VariableIndex)

Return a new function f with the variable vi removed.

source
remove_variable(
+    f::MOI.AbstractFunction,
+    s::MOI.AbstractSet,
+    vi::MOI.VariableIndex,
+)

Return a tuple (g, t) representing the constraint f-in-s with the variable vi removed. That is, the terms containing the variable vi in the function f are removed and the dimension of the set s is updated if needed (for example, when f is a VectorOfVariables with vi being one of the variables).

source
MathOptInterface.Utilities.all_coefficientsFunction
all_coefficients(p::Function, f::MOI.AbstractFunction)

Determine whether predicate p returns true for all coefficients of f, returning false as soon as the first coefficient of f for which p returns false is encountered (short-circuiting). Similar to all.

source
MathOptInterface.Utilities.unsafe_addFunction
unsafe_add(t1::MOI.ScalarAffineTerm, t2::MOI.ScalarAffineTerm)

Sums the coefficients of t1 and t2 and returns an output MOI.ScalarAffineTerm. It is unsafe because it uses the variable of t1 as the variable of the output without checking that it is equal to that of t2.

source
unsafe_add(t1::MOI.ScalarQuadraticTerm, t2::MOI.ScalarQuadraticTerm)

Sums the coefficients of t1 and t2 and returns an output MOI.ScalarQuadraticTerm. It is unsafe because it uses the variable's of t1 as the variable's of the output without checking that they are the same (up to permutation) to those of t2.

source
unsafe_add(t1::MOI.VectorAffineTerm, t2::MOI.VectorAffineTerm)

Sums the coefficients of t1 and t2 and returns an output MOI.VectorAffineTerm. It is unsafe because it uses the output_index and variable of t1 as the output_index and variable of the output term without checking that they are equal to those of t2.

source
MathOptInterface.Utilities.isapprox_zeroFunction
isapprox_zero(f::MOI.AbstractFunction, tol)

Return a Bool indicating whether the function f is approximately zero using tol as a tolerance.

Important note

This function assumes that f does not contain any duplicate terms, you might want to first call canonical if that is not guaranteed. For instance, given

f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1, -1], [x, x]), 0)

then isapprox_zero(f) is false but isapprox_zero(MOIU.canonical(f)) is true.

source
MathOptInterface.Utilities.zero_with_output_dimensionFunction
zero_with_output_dimension(::Type{T}, output_dimension::Integer) where {T}

Create an instance of type T with the output dimension output_dimension.

This is mostly useful in Bridges, when code needs to be agnostic to the type of vector-valued function that is passed in.

source

The following functions can be used to canonicalize a function:

MathOptInterface.Utilities.is_canonicalFunction
is_canonical(f::Union{ScalarAffineFunction, VectorAffineFunction})

Returns a Bool indicating whether the function is in canonical form. See canonical.

source
is_canonical(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})

Returns a Bool indicating whether the function is in canonical form. See canonical.

source
MathOptInterface.Utilities.canonicalFunction
canonical(f::MOI.AbstractFunction)

Returns the function in a canonical form, that is,

  • A term appear only once.
  • The coefficients are nonzero.
  • The terms appear in increasing order of variable where there the order of the variables is the order of their value.
  • For a AbstractVectorFunction, the terms are sorted in ascending order of output index.

The output of canonical can be assumed to be a copy of f, even for VectorOfVariables.

Examples

If x (resp. y, z) is VariableIndex(1) (resp. 2, 3). The canonical representation of ScalarAffineFunction([y, x, z, x, z], [2, 1, 3, -2, -3], 5) is ScalarAffineFunction([x, y], [-1, 2], 5).

source
MathOptInterface.Utilities.canonicalize!Function
canonicalize!(f::Union{ScalarAffineFunction, VectorAffineFunction})

Convert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.

source
canonicalize!(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})

Convert a function to canonical form in-place, without allocating a copy to hold the result. See canonical.

source

The following functions can be used to manipulate functions with basic algebra:

MathOptInterface.Utilities.scalarizeFunction
scalarize(func::MOI.VectorOfVariables, ignore_constants::Bool = false)

Returns a vector of scalar functions making up the vector function in the form of a Vector{MOI.SingleVariable}.

See also eachscalar.

source
scalarize(func::MOI.VectorAffineFunction{T}, ignore_constants::Bool = false)

Returns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarAffineFunction{T}}.

See also eachscalar.

source
scalarize(func::MOI.VectorQuadraticFunction{T}, ignore_constants::Bool = false)

Returns a vector of scalar functions making up the vector function in the form of a Vector{MOI.ScalarQuadraticFunction{T}}.

See also eachscalar.

source
MathOptInterface.Utilities.promote_operationFunction
promote_operation(
+    op::Function,
+    ::Type{T},
+    ArgsTypes::Type{<:Union{T,AbstractVector{T},MOI.AbstractFunction}}...,
+) where {T<:Number}

Compute the return type of the call operate(op, T, args...), where the types of the arguments args are ArgsTypes.

One assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.

There are six methods for which we implement Utilities.promote_operation:

  1. + a. promote_operation(::typeof(+), ::Type{T}, ::Type{F1}, ::Type{F2})
  2. - a. promote_operation(::typeof(-), ::Type{T}, ::Type{F}) b. promote_operation(::typeof(-), ::Type{T}, ::Type{F1}, ::Type{F2})
  3. * a. promote_operation(::typeof(*), ::Type{T}, ::Type{T}, ::Type{F}) b. promote_operation(::typeof(*), ::Type{T}, ::Type{F}, ::Type{T}) c. promote_operation(::typeof(*), ::Type{T}, ::Type{F1}, ::Type{F2}) where F1 and F2 are VariableIndex or ScalarAffineFunction d. promote_operation(::typeof(*), ::Type{T}, ::Type{<:Diagonal{T}}, ::Type{F}
  4. / a. promote_operation(::typeof(/), ::Type{T}, ::Type{F}, ::Type{T})
  5. vcat a. promote_operation(::typeof(vcat), ::Type{T}, ::Type{F}...)
  6. imag a. promote_operation(::typeof(imag), ::Type{T}, ::Type{F}) where F is VariableIndex or VectorOfVariables

In each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:

  1. ::T
  2. ::VariableIndex
  3. ::ScalarAffineFunction{T}
  4. ::ScalarQuadraticFunction{T}
  5. ::ScalarNonlinearFunction
  6. ::AbstractVector{T}
  7. ::VectorOfVariables
  8. ::VectorAffineFunction{T}
  9. ::VectorQuadraticFunction{T}
  10. ::VectorNonlinearFunction
source
MathOptInterface.Utilities.operateFunction
operate(
+    op::Function,
+    ::Type{T},
+    args::Union{T,MOI.AbstractFunction}...,
+)::MOI.AbstractFunction where {T<:Number}

Returns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.

No argument can be modified.

Methods

  1. + a. operate(::typeof(+), ::Type{T}, ::F1) b. operate(::typeof(+), ::Type{T}, ::F1, ::F2) c. operate(::typeof(+), ::Type{T}, ::F1...)
  2. - a. operate(::typeof(-), ::Type{T}, ::F) b. operate(::typeof(-), ::Type{T}, ::F1, ::F2)
  3. * a. operate(::typeof(*), ::Type{T}, ::T, ::F) b. operate(::typeof(*), ::Type{T}, ::F, ::T) c. operate(::typeof(*), ::Type{T}, ::F1, ::F2) where F1 and F2 are VariableIndex or ScalarAffineFunction d. operate(::typeof(*), ::Type{T}, ::Diagonal{T}, ::F)
  4. / a. operate(::typeof(/), ::Type{T}, ::F, ::T)
  5. vcat a. operate(::typeof(vcat), ::Type{T}, ::F...)
  6. imag a. operate(::typeof(imag), ::Type{T}, ::F) where F is VariableIndex or VectorOfVariables

One assumption is that the element type T is invariant under each operation. That is, op(::T, ::T)::T where op is a +, -, *, and /.

In each case, F (or F1 and F2) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define promote_operation(-, T, F1, F2) where F1 is a scalar-valued function and F2 is a vector-valued function. The ten supported types are:

  1. ::T
  2. ::VariableIndex
  3. ::ScalarAffineFunction{T}
  4. ::ScalarQuadraticFunction{T}
  5. ::ScalarNonlinearFunction
  6. ::AbstractVector{T}
  7. ::VectorOfVariables
  8. ::VectorAffineFunction{T}
  9. ::VectorQuadraticFunction{T}
  10. ::VectorNonlinearFunction
source
MathOptInterface.Utilities.operate!Function
operate!(
+    op::Function,
+    ::Type{T},
+    args::Union{T,MOI.AbstractFunction}...,
+)::MOI.AbstractFunction where {T<:Number}

Returns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T.

The first argument may be modified, in which case the return value is identical to the first argument. For operations which cannot be implemented in-place, this function returns a new object.

source
MathOptInterface.Utilities.operate_output_index!Function
operate_output_index!(
+    op::Union{typeof(+),typeof(-)},
+    ::Type{T},
+    output_index::Integer,
+    f::Union{AbstractVector{T},MOI.AbstractVectorFunction}
+    g::Union{T,MOI.AbstractScalarFunction}...
+) where {T<:Number}

Return an MOI.AbstractVectorFunction in which the scalar function in row output_index is the result of op(f[output_index], g).

The functions at output index different to output_index are the same as the functions at the same output index in func. The first argument may be modified.

Methods

  1. + a. operate_output_index!(+, ::Type{T}, ::Int, ::VectorF, ::ScalarF)
  2. - a. operate_output_index!(-, ::Type{T}, ::Int, ::VectorF, ::ScalarF)
source
MathOptInterface.Utilities.vectorizeFunction
vectorize(x::AbstractVector{<:Number})

Returns x.

source
vectorize(x::AbstractVector{MOI.VariableIndex})

Returns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.

source
vectorize(funcs::AbstractVector{MOI.ScalarAffineFunction{T}}) where T

Returns the vector of scalar affine functions in the form of a MOI.VectorAffineFunction{T}.

source
vectorize(funcs::AbstractVector{MOI.ScalarQuadraticFunction{T}}) where T

Returns the vector of scalar quadratic functions in the form of a MOI.VectorQuadraticFunction{T}.

source

Constraint utilities

The following utilities are available for moving the function constant to the set for scalar constraints:

MathOptInterface.Utilities.shift_constantFunction
shift_constant(set::MOI.AbstractScalarSet, offset)

Returns a new scalar set new_set such that func-in-set is equivalent to func + offset-in-new_set.

Only define this function if it makes sense to.

Use supports_shift_constant to check if the set supports shifting:

if supports_shift_constant(typeof(old_set))
+    new_set = shift_constant(old_set, offset)
+    f.constant = 0
+    add_constraint(model, f, new_set)
+else
+    add_constraint(model, f, old_set)
+end

See also supports_shift_constant.

Examples

The call shift_constant(MOI.Interval(-2, 3), 1) is equal to MOI.Interval(-1, 4).

source
MathOptInterface.Utilities.normalize_and_add_constraintFunction
normalize_and_add_constraint(
+    model::MOI.ModelLike,
+    func::MOI.AbstractScalarFunction,
+    set::MOI.AbstractScalarSet;
+    allow_modify_function::Bool = false,
+)

Adds the scalar constraint obtained by moving the constant term in func to the set in model. If allow_modify_function is true then the function func can be modified.

source

The following utility identifies those constraints imposing bounds on a given variable, and returns those bound values:

MathOptInterface.Utilities.get_boundsFunction
get_bounds(model::MOI.ModelLike, ::Type{T}, x::MOI.VariableIndex)

Return a tuple (lb, ub) of type Tuple{T, T}, where lb and ub are lower and upper bounds, respectively, imposed on x in model.

source
get_bounds(
+    model::MOI.ModelLike,
+    bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},
+    f::MOI.ScalarAffineFunction{T},
+) where {T} --> Union{Nothing,NTuple{2,T}}

Return the lower and upper bound of f as a tuple. If the domain is not bounded, return nothing.

source
get_bounds(
+    model::MOI.ModelLike,
+    bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},
+    x::MOI.VariableIndex,
+) where {T} --> Union{Nothing,NTuple{2,T}}

Return the lower and upper bound of x as a tuple. If the domain is not bounded, return nothing.

Similar to get_bounds(::MOI.ModelLike, ::Type{T}, ::MOI.VariableIndex), except that the second argument is a cache which maps variables to their bounds and avoids repeated lookups.

source

The following utilities are useful when working with symmetric matrix cones.

Set utilities

The following utilities are available for sets:

MathOptInterface.Utilities.ProjectionUpperBoundDistanceType
ProjectionUpperBoundDistance() <: AbstractDistance

An upper bound on the minimum distance between point and the closest feasible point in set.

Definition of distance

The minimum distance is computed as:

\[d(x, \mathcal{K}) = \min_{y \in \mathcal{K}} || x - y ||\]

where $x$ is point and $\mathcal{K}$ is set. The norm is computed as:

\[||x|| = \sqrt{f(x, x, \mathcal{K})}\]

where $f$ is Utilities.set_dot.

In the default case, where the set does not have a specialized method for Utilities.set_dot, the norm is equivalent to the Euclidean norm $||x|| = \sqrt{\sum x_i^2}$.

Why an upper bound?

In most cases, distance_to_set should return the smallest upper bound, but it may return a larger value if the smallest upper bound is expensive to compute.

For example, given an epigraph from of a conic set, $\{(t, x) | f(x) \le t\}$, it may be simpler to return $\delta$ such that $f(x) \le t + \delta$, rather than computing the nearest projection onto the set.

If the distance is not the smallest upper bound, the docstring of the appropriate distance_to_set method must describe the way that the distance is computed.

source
MathOptInterface.Utilities.distance_to_setFunction
distance_to_set(
+    [d::AbstractDistance = ProjectionUpperBoundDistance()],]
+    point::T,
+    set::MOI.AbstractScalarSet,
+) where {T}
+
+distance_to_set(
+    [d::AbstractDistance = ProjectionUpperBoundDistance(),]
+    point::AbstractVector{T},
+    set::MOI.AbstractVectorSet,
+) where {T}

Compute the distance between point and set using the distance metric d. If point is in the set set, this function must return zero(T).

If d is omitted, the default distance is Utilities.ProjectionUpperBoundDistance.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RotatedSecondOrderCone)

Let (t, u, y...) = x. Return the 2-norm of the vector d such that in x + d, u is projected to 1 if u <= 0, and t is increased such that x + d belongs to the set.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.ExponentialCone)

Let (u, v, w) = x. If v > 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.

If v <= 0 return the 2-norm of the vector d such that x + d = (u, 1, z) where z satisfies the constraints.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualExponentialCone)

Let (u, v, w) = x. If u < 0, return the epigraph distance d such that (u, v, w + d) belongs to the set.

If u >= 0 return the 2-norm of the vector d such that x + d = (u, -1, z) where z satisfies the constraints.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.GeometricMeanCone)

Let (t, y...) = x. If all y are non-negative, return the epigraph distance d such that (t + d, y...) belongs to the set.

If any y are strictly negative, return the 2-norm of the vector d that projects negative y elements to 0 and t to ℝ₋.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.PowerCone)

Let (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.

If a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualPowerCone)

Let (a, b, c) = x. If a and b are non-negative, return the epigraph distance required to increase c such that the constraint is satisfied.

If a or b is strictly negative, return the 2-norm of the vector d such that in the vector x + d: c, and any negative a and b are projected to 0.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormOneCone)

Let (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormInfinityCone)

Let (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.

source
distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RelativeEntropyCone)

Let (u, v..., w...) = x. If v and w are strictly positive, return the epigraph distance required to increase u such that the constraint is satisfied.

If any elements in v or w are non-positive, return the 2-norm of the vector d such that in the vector x + d: any non-positive elements in v and w are projected to 1, and u is projected such that the epigraph constraint holds.

source
distance_to_set(::ProjectionUpperBoundDistance, x, set::MOI.NormCone)

Let (t, y...) = x. Return the epigraph distance d such that (t + d, y...) belongs to the set.

source
MathOptInterface.Utilities.set_dotFunction
set_dot(x::AbstractVector, y::AbstractVector, set::AbstractVectorSet)

Return the scalar product between a vector x of the set set and a vector y of the dual of the set s.

source
set_dot(x, y, set::AbstractScalarSet)

Return the scalar product between a number x of the set set and a number y of the dual of the set s.

source

DoubleDicts

MathOptInterface.Utilities.DoubleDicts.DoubleDictType
DoubleDict{V}

An optimized dictionary to map MOI.ConstraintIndex to values of type V.

Works as a AbstractDict{MOI.ConstraintIndex,V} with minimal differences.

If V is also a MOI.ConstraintIndex, use IndexDoubleDict.

Note that MOI.ConstraintIndex is not a concrete type, opposed to MOI.ConstraintIndex{MOI.VariableIndex, MOI.Integers}, which is a concrete type.

When looping through multiple keys of the same Function-in-Set type, use

inner = dict[F, S]

to return a type-stable DoubleDictInner.

source
MathOptInterface.Utilities.DoubleDicts.outer_keysFunction
outer_keys(d::AbstractDoubleDict)

Return an iterator over the outer keys of the AbstractDoubleDict d. Each outer key is a Tuple{Type,Type} so that a double loop can be easily used:

for (F, S) in DoubleDicts.outer_keys(dict)
+    for (k, v) in dict[F, S]
+        # ...
+    end
+end

For performance, it is recommended that the inner loop lies in a separate function to guarantee type-stability. Some outer keys (F, S) might lead to an empty dict[F, S]. If you want only nonempty dict[F, S], use nonempty_outer_keys.

source
MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keysFunction
nonempty_outer_keys(d::AbstractDoubleDict)

Return a vector of outer keys of the AbstractDoubleDict d.

Only outer keys that have a nonempty set of inner keys will be returned.

Each outer key is a Tuple{Type,Type} so that a double loop can be easily used

for (F, S) in DoubleDicts.nonempty_outer_keys(dict)
+    for (k, v) in dict[F, S]
+        # ...
+    end
+end
+For performance, it is recommended that the inner loop lies in a separate
+function to guarantee type-stability.
+
+If you want an iterator of all current outer keys, use [`outer_keys`](@ref).
source
diff --git a/previews/PR2418/tutorials/bridging_constraint/index.html b/previews/PR2418/tutorials/bridging_constraint/index.html new file mode 100644 index 0000000000..4e1c7aa345 --- /dev/null +++ b/previews/PR2418/tutorials/bridging_constraint/index.html @@ -0,0 +1,102 @@ + +Implementing a constraint bridge · MathOptInterface

Implementing a constraint bridge

This guide outlines the basic steps to create a new bridge from a constraint expressed in the formalism Function-in-Set.

Preliminaries

First, decide on the set you want to bridge. Then, study its properties: the most important one is whether the set is scalar or vector, which impacts the dimensionality of the functions that can be used with the set.

  • A scalar function only has one dimension. MOI defines three types of scalar functions: a variable (VariableIndex), an affine function (ScalarAffineFunction), or a quadratic function (ScalarQuadraticFunction).
  • A vector function has several dimensions (at least one). MOI defines three types of vector functions: several variables (VectorOfVariables), an affine function (VectorAffineFunction), or a quadratic function (VectorQuadraticFunction). The main difference with scalar functions is that the order of dimensions can be very important: for instance, in an indicator constraint (Indicator), the first dimension indicates whether the constraint about the second dimension is active.

To explain how to implement a bridge, we present the example of Bridges.Constraint.FlipSignBridge. This bridge maps <= (LessThan) constraints to >= (GreaterThan) constraints. This corresponds to reversing the sign of the inequality. We focus on scalar affine functions (we disregard the cases of a single variable or of quadratic functions). This example is a simplified version of the code included in MOI.

Four mandatory parts in a constraint bridge

The first part of a constraint bridge is a new concrete subtype of Bridges.Constraint.AbstractBridge. This type must have fields to store all the new variables and constraints that the bridge will add. Typically, these types are parametrized by the type of the coefficients in the model.

Then, three sets of functions must be defined:

  1. Bridges.Constraint.bridge_constraint: this function implements the bridge and creates the required variables and constraints.
  2. supports_constraint: these functions must return true when the combination of function and set is supported by the bridge. By default, the base implementation always returns false and the bridge does not have to provide this implementation.
  3. Bridges.added_constrained_variable_types and Bridges.added_constraint_types: these functions return the types of variables and constraints that this bridge adds. They are used to compute the set of other bridges that are required to use the one you are defining, if need be.

More functions can be implemented, for instance to retrieve properties from the bridge or deleting a bridged constraint.

1. Structure for the bridge

A typical struct behind a bridge depends on the type of the coefficients that are used for the model (typically Float64, but coefficients might also be integers or complex numbers).

This structure must hold a reference to all the variables and the constraints that are created as part of the bridge.

The type of this structure is used throughout MOI as an identifier for the bridge. It is passed as argument to most functions related to bridges.

The best practice is to have the name of this type end with Bridge.

In our example, the bridge maps any ScalarAffineFunction{T}-in-LessThan{T} constraint to a single ScalarAffineFunction{T}-in-GreaterThan{T} constraint. The affine function has coefficients of type T. The bridge is parametrized with T, so that the constraint that the bridge creates also has coefficients of type T.

struct SignBridge{T<:Number} <: Bridges.Constraint.AbstractBridge
+    constraint::ConstraintIndex{ScalarAffineFunction{T}, GreaterThan{T}}
+end

2. Bridge creation

The function Bridges.Constraint.bridge_constraint is called whenever the bridge is instantiated for a specific model, with the given function and set. The arguments to bridge_constraint are similar to add_constraint, with the exception of the first argument: it is the Type of the struct defined in the first step (for our example, Type{SignBridge{T}}).

bridge_constraint returns an instance of the struct defined in the first step. the first step.

In our example, the bridge constraint could be defined as:

function Bridges.Constraint.bridge_constraint(
+    ::Type{SignBridge{T}}, # Bridge to use.
+    model::ModelLike, # Model to which the constraint is being added.
+    f::ScalarAffineFunction{T}, # Function to rewrite.
+    s::LessThan{T}, # Set to rewrite.
+) where {T}
+    # Create the variables and constraints required for the bridge.
+    con = add_constraint(model, -f, GreaterThan(-s.upper))
+
+    # Return an instance of the bridge type with a reference to all the
+    # variables and constraints that were created in this function.
+    return SignBridge(con)
+end

3. Supported constraint types

The function supports_constraint determines whether the bridge type supports a given combination of function and set.

This function must closely match bridge_constraint, because it will not be called if supports_constraint returns false.

function supports_constraint(
+    ::Type{SignBridge{T}}, # Bridge to use.
+    ::Type{ScalarAffineFunction{T}}, # Function to rewrite.
+    ::Type{LessThan{T}}, # Set to rewrite.
+) where {T}
+    # Do some computation to ensure that the constraint is supported.
+    # Typically, you can directly return true.
+    return true
+end

4. Metadata about the bridge

To determine whether a bridge can be used, MOI uses a shortest-path algorithm that uses the variable types and the constraints that the bridge can create. This information is communicated from the bridge to MOI using the functions Bridges.added_constrained_variable_types and Bridges.added_constraint_types. Both return lists of tuples: either a list of 1-tuples containing the variable types (typically, ZeroOne or Integer) or a list of 2-tuples contained the functions and sets (like ScalarAffineFunction{T}-GreaterThan).

For our example, the bridge does not create any constrained variables, and only ScalarAffineFunction{T}-in-GreaterThan{T} constraints:

function Bridges.added_constrained_variable_types(::Type{SignBridge{T}}) where {T}
+    # The bridge does not create variables, return an empty list of tuples:
+    return Tuple{Type}[]
+end
+
+function Bridges.added_constraint_types(::Type{SignBridge{T}}) where {T}
+    return Tuple{Type,Type}[
+        # One element per F-in-S the bridge creates.
+        (ScalarAffineFunction{T}, GreaterThan{T}),
+    ]
+end

A bridge that creates binary variables would rather have this definition of added_constrained_variable_types:

function Bridges.added_constrained_variable_types(::Type{SomeBridge{T}}) where {T}
+    # The bridge only creates binary variables:
+    return Tuple{Type}[(ZeroOne,)]
+end
Warning

If you declare the creation of constrained variables in added_constrained_variable_types, the corresponding constraint type VariableIndex must not be indicated in added_constraint_types. This would restrict the use of the bridge to solvers that can add such a constraint after the variable is created.

More concretely, if you declare in added_constrained_variable_types that your bridge creates binary variables (ZeroOne), and if you never add such a constraint afterward (you do not call add_constraint(model, var, ZeroOne())), then you must not list (VariableIndex, ZeroOne) in added_constraint_types.

Typically, the function Bridges.Constraint.concrete_bridge_type does not have to be defined for most bridges.

Bridge registration

For a bridge to be used by MOI, it must be known by MOI.

SingleBridgeOptimizer

The first way to do so is to create a single-bridge optimizer. This type of optimizer wraps another optimizer and adds the possibility to use only one bridge. It is especially useful when unit testing bridges.

It is common practice to use the same name as the type defined for the bridge (SignBridge, in our example) without the suffix Bridge.

const Sign{T,OT<: ModelLike} =
+    SingleBridgeOptimizer{SignBridge{T}, OT}

In the context of unit tests, this bridge is used in conjunction with a Utilities.MockOptimizer:

mock = Utilities.MockOptimizer(
+    Utilities.UniversalFallback(Utilities.Model{Float64}()),
+)
+bridged_mock = Sign{Float64}(mock)

New bridge for a LazyBridgeOptimizer

Typical user-facing models for MOI are based on Bridges.LazyBridgeOptimizer. For instance, this type of model is returned by Bridges.full_bridge_optimizer. These models can be added more bridges by using Bridges.add_bridge:

inner_optimizer = Utilities.Model{Float64}()
+optimizer = Bridges.full_bridge_optimizer(inner_optimizer, Float64)
+Bridges.add_bridge(optimizer, SignBridge{Float64})

Bridge improvements

Attribute retrieval

Like models, bridges have attributes that can be retrieved using get and set. The most important ones are the number of variables and constraints, but also the lists of variables and constraints.

In our example, we only have one constraint and only have to implement the NumberOfConstraints and ListOfConstraintIndices attributes:

function get(
+    ::SignBridge{T},
+    ::NumberOfConstraints{
+        ScalarAffineFunction{T},
+        GreaterThan{T},
+    },
+) where {T}
+    return 1
+end
+
+function get(
+    bridge::SignBridge{T},
+    ::ListOfConstraintIndices{
+        ScalarAffineFunction{T},
+        GreaterThan{T},
+    },
+) where {T}
+    return [bridge.constraint]
+end

You must implement one such pair of functions for each type of constraint the bridge adds to the model.

Warning

Avoid returning a list from the bridge object without copying it. Users must be able to change the contents of the returned list without altering the bridge object.

For variables, the situation is simpler. If your bridge creates new variables, you must implement the NumberOfVariables and ListOfVariableIndices attributes. However, these attributes do not have parameters, unlike their constraint counterparts. Only two functions suffice:

function get(
+    ::SignBridge{T},
+    ::NumberOfVariables,
+) where {T}
+    return 0
+end
+
+function get(
+    ::SignBridge{T},
+    ::ListOfVariableIndices,
+) where {T}
+    return VariableIndex[]
+end

In order for the user to be able to access the function and set of the original constraint, the bridge needs to implement getters for the ConstraintFunction and ConstraintSet attributes:

function get(
+    model::MOI.ModelLike,
+    attr::MOI.ConstraintFunction,
+    bridge::SignBridge,
+)
+    return -MOI.get(model, attr, bridge.constraint)
+end
+
+function get(
+    model::MOI.ModelLike,
+    attr::MOI.ConstraintSet,
+    bridge::SignBridge,
+)
+    set = MOI.get(model, attr, bridge.constraint)
+    return MOI.LessThan(-set.lower)
+end
Warning

Alternatively, one could store the original function and set in SignBridge during Bridges.Constraint.bridge_constraint to make these getters simpler and more efficient. On the other hand, this will increase the memory footprint of the bridges as the garbage collector won't be able to delete that object. The convention is to not store the function in the bridge and not care too much about the efficiency of these getters. If the user needs efficient getters for ConstraintFunction then they should use a Utilities.CachingOptimizer.

Model modifications

To avoid copying the model when the user request to change a constraint, MOI provides modify. Bridges can also implement this API to allow certain changes, such as coefficient changes.

In our case, a modification of a coefficient in the original constraint (for example, replacing the value of the coefficient of a variable in the affine function) must be transmitted to the constraint created by the bridge, but with a sign change.

function modify(
+    model::ModelLike,
+    bridge::SignBridge,
+    change::ScalarCoefficientChange,
+)
+    modify(
+        model,
+        bridge.constraint,
+        ScalarCoefficientChange(change.variable, -change.new_coefficient),
+    )
+    return
+end

Bridge deletion

When a bridge is deleted, the constraints it added must be deleted too.

function delete(model::ModelLike, bridge::SignBridge)
+    delete(model, bridge.constraint)
+    return
+end
diff --git a/previews/PR2418/tutorials/example/index.html b/previews/PR2418/tutorials/example/index.html new file mode 100644 index 0000000000..fa99c23905 --- /dev/null +++ b/previews/PR2418/tutorials/example/index.html @@ -0,0 +1,45 @@ + +Solving a problem using MathOptInterface · MathOptInterface

Solving a problem using MathOptInterface

In this tutorial we demonstrate how to use MathOptInterface to solve the binary-constrained knapsack problem:

\[\begin{aligned} +\max \; & c^\top x \\ +s.t. \; & w^\top x \le C \\ + & x_i \in \{0,1\},\quad \forall i=1,\ldots,n +\end{aligned}\]

Required packages

Load the MathOptInterface module and define the shorthand MOI:

import MathOptInterface as MOI

As an optimizer, we choose GLPK:

using GLPK
+optimizer = GLPK.Optimizer()

Define the data

We first define the constants of the problem:

julia> c = [1.0, 2.0, 3.0]
+3-element Vector{Float64}:
+ 1.0
+ 2.0
+ 3.0
+
+julia> w = [0.3, 0.5, 1.0]
+3-element Vector{Float64}:
+ 0.3
+ 0.5
+ 1.0
+
+julia> C = 3.2
+3.2

Add the variables

julia> x = MOI.add_variables(optimizer, length(c));

Set the objective

julia> MOI.set(
+           optimizer,
+           MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
+           MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0),
+       );
+
+julia> MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
Tip

MOI.ScalarAffineTerm.(c, x) is a shortcut for [MOI.ScalarAffineTerm(c[i], x[i]) for i = 1:3]. This is Julia's broadcast syntax in action, and is used quite often throughout MOI.

Add the constraints

We add the knapsack constraint and integrality constraints:

julia> MOI.add_constraint(
+           optimizer,
+           MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(w, x), 0.0),
+           MOI.LessThan(C),
+       );

Add integrality constraints:

julia> for x_i in x
+           MOI.add_constraint(optimizer, x_i, MOI.ZeroOne())
+       end

Optimize the model

julia> MOI.optimize!(optimizer)

Understand why the solver stopped

The first thing to check after optimization is why the solver stopped, for example, did it stop because of a time limit or did it stop because it found the optimal solution?

julia> MOI.get(optimizer, MOI.TerminationStatus())
+OPTIMAL::TerminationStatusCode = 1

Looks like we found an optimal solution.

Understand what solution was returned

julia> MOI.get(optimizer, MOI.ResultCount())
+1
+
+julia> MOI.get(optimizer, MOI.PrimalStatus())
+FEASIBLE_POINT::ResultStatusCode = 1
+
+julia> MOI.get(optimizer, MOI.DualStatus())
+NO_SOLUTION::ResultStatusCode = 0

Query the objective

What is its objective value?

julia> MOI.get(optimizer, MOI.ObjectiveValue())
+6.0

Query the primal solution

And what is the value of the variables x?

julia> MOI.get(optimizer, MOI.VariablePrimal(), x)
+3-element Vector{Float64}:
+ 1.0
+ 1.0
+ 1.0
diff --git a/previews/PR2418/tutorials/implementing/index.html b/previews/PR2418/tutorials/implementing/index.html new file mode 100644 index 0000000000..702412febf --- /dev/null +++ b/previews/PR2418/tutorials/implementing/index.html @@ -0,0 +1,114 @@ + +Implementing a solver interface · MathOptInterface

Implementing a solver interface

This guide outlines the basic steps to implement an interface to MathOptInterface for a new solver.

Danger

Implementing an interface to MathOptInterface for a new solver is a lot of work. Before starting, we recommend that you join the Developer chatroom and explain a little bit about the solver you are wrapping. If you have questions that are not answered by this guide, please ask them in the Developer chatroom so we can improve this guide.

A note on the API

The API of MathOptInterface is large and varied. In order to support the diversity of solvers and use-cases, we make heavy use of duck-typing. That is, solvers are not expected to implement the full API, nor is there a well-defined minimal subset of what must be implemented. Instead, you should implement the API as necessary to make the solver function as you require.

The main reason for using duck-typing is that solvers work in different ways and target different use-cases.

For example:

  • Some solvers support incremental problem construction, support modification after a solve, and have native support for things like variable names.
  • Other solvers are "one-shot" solvers that require all of the problem data to construct and solve the problem in a single function call. They do not support modification or things like variable names.
  • Other "solvers" are not solvers at all, but things like file readers. These may only support functions like read_from_file, and may not even support the ability to add variables or constraints directly.
  • Finally, some "solvers" are layers which take a problem as input, transform it according to some rules, and pass the transformed problem to an inner solver.

Preliminaries

Before starting on your wrapper, you should do some background research and make the solver accessible via Julia.

Decide if MathOptInterface is right for you

The first step in writing a wrapper is to decide whether implementing an interface is the right thing to do.

MathOptInterface is an abstraction layer for unifying constrained mathematical optimization solvers. If your solver doesn't fit in the category, for example, it implements a derivative-free algorithm for unconstrained objective functions, MathOptInterface may not be the right tool for the job.

Tip

If you're not sure whether you should write an interface, ask in the Developer chatroom.

Find a similar solver already wrapped

The next step is to find (if possible) a similar solver that is already wrapped. Although not strictly necessary, this will be a good place to look for inspiration when implementing your wrapper.

The JuMP documentation has a good list of solvers, along with the problem classes they support.

Tip

If you're not sure which solver is most similar, ask in the Developer chatroom.

Create a low-level interface

Before writing a MathOptInterface wrapper, you first need to be able to call the solver from Julia.

Wrapping solvers written in Julia

If your solver is written in Julia, there's nothing to do here. Go to the next section.

Wrapping solvers written in C

Julia is well suited to wrapping solvers written in C.

Info

This is not true for C++. If you have a solver written in C++, first write a C interface, then wrap the C interface.

Before writing a MathOptInterface wrapper, there are a few extra steps.

Create a JLL

If the C code is publicly available under an open source license, create a JLL package via Yggdrasil. The easiest way to do this is to copy an existing solver. Good examples to follow are the COIN-OR solvers.

Warning

Building the solver via Yggdrasil is non-trivial. Please ask the Developer chatroom for help.

If the code is commercial or not publicly available, the user will need to manually install the solver. See Gurobi.jl or CPLEX.jl for examples of how to structure this.

Use Clang.jl to wrap the C API

The next step is to use Clang.jl to automatically wrap the C API. The easiest way to do this is to follow an example. Good examples to follow are Cbc.jl and HiGHS.jl.

Sometimes, you will need to make manual modifications to the resulting files.

Solvers written in other languages

Ask the Developer chatroom for advice. You may be able to use one of the JuliaInterop packages to call out to the solver.

For example, SeDuMi.jl uses MATLAB.jl to call the SeDuMi solver written in MATLAB.

Structuring the package

Structure your wrapper as a Julia package. Consult the Julia documentation if you haven't done this before.

MOI solver interfaces may be in the same package as the solver itself (either the C wrapper if the solver is accessible through C, or the Julia code if the solver is written in Julia, for example), or in a separate package which depends on the solver package.

Note

The JuMP core contributors request that you do not use "JuMP" in the name of your package without prior consent.

Your package should have the following structure:

/.github
+    /workflows
+        ci.yml
+        format_check.yml
+        TagBot.yml
+/gen
+    gen.jl  # Code to wrap the C API
+/src
+    NewSolver.jl
+    /gen
+        libnewsolver_api.jl
+        libnewsolver_common.jl
+    /MOI_wrapper
+        MOI_wrapper.jl
+        other_files.jl
+/test
+    runtests.jl
+    /MOI_wrapper
+        MOI_wrapper.jl
+.gitignore
+.JuliaFormatter.toml
+README.md
+LICENSE.md
+Project.toml
  • The /.github folder contains the scripts for GitHub actions. The easiest way to write these is to copy the ones from an existing solver.
  • The /gen and /src/gen folders are only needed if you are wrapping a solver written in C.
  • The /src/MOI_wrapper folder contains the Julia code for the MOI wrapper.
  • The /test folder contains code for testing your package. See Setup tests for more information.
  • The .JuliaFormatter.toml and .github/workflows/format_check.yml enforce code formatting using JuliaFormatter.jl. Check existing solvers or JuMP.jl for details.

Documentation

Your package must include documentation explaining how to use the package. The easiest approach is to include documentation in your README.md. A more involved option is to use Documenter.jl.

Examples of packages with README-based documentation include:

Examples of packages with Documenter-based documentation include:

Setup tests

The best way to implement an interface to MathOptInterface is via test-driven development.

The MOI.Test submodule contains a large test suite to help check that you have implemented things correctly.

Follow the guide How to test a solver to set up the tests for your package.

Tip

Run the tests frequently when developing. However, at the start there is going to be a lot of errors. Start by excluding large classes of tests (for example, exclude = ["test_basic_", "test_model_"], implement any missing methods until the tests pass, then remove an exclusion and repeat.

Initial code

By this point, you should have a package setup with tests, formatting, and access to the underlying solver. Now it's time to start writing the wrapper.

The Optimizer object

The first object to create is a subtype of AbstractOptimizer. This type is going to store everything related to the problem.

By convention, these optimizers should not be exported and should be named PackageName.Optimizer.

import MathOptInterface as MOI
+
+struct Optimizer <: MOI.AbstractOptimizer
+    # Fields go here
+end

Optimizer objects for C solvers

Warning

This section is important if you wrap a solver written in C.

Wrapping a solver written in C will require the use of pointers, and for you to manually free the solver's memory when the Optimizer is garbage collected by Julia.

Never pass a pointer directly to a Julia ccall function.

Instead, store the pointer as a field in your Optimizer, and implement Base.cconvert and Base.unsafe_convert. Then you can pass Optimizer to any ccall function that expects the pointer.

In addition, make sure you implement a finalizer for each model you create.

If newsolver_createProblem() is the low-level function that creates the problem pointer in C, and newsolver_freeProblem(::Ptr{Cvoid}) is the low-level function that frees memory associated with the pointer, your Optimizer() function should look like this:

struct Optimizer <: MOI.AbstractOptimizer
+    ptr::Ptr{Cvoid}
+
+    function Optimizer()
+        ptr = newsolver_createProblem()
+        model = Optimizer(ptr)
+        finalizer(model) do m
+            newsolver_freeProblem(m)
+            return
+        end
+        return model
+    end
+end
+
+Base.cconvert(::Type{Ptr{Cvoid}}, model::Optimizer) = model
+Base.unsafe_convert(::Type{Ptr{Cvoid}}, model::Optimizer) = model.ptr

Implement methods for Optimizer

All Optimizers must implement the following methods:

Other methods, detailed below, are optional or depend on how you implement the interface.

Tip

For this and all future methods, read the docstrings to understand what each method does, what it expects as input, and what it produces as output. If it isn't clear, let us know and we will improve the docstrings. It is also very helpful to look at an existing wrapper for a similar solver.

You should also implement Base.show(::IO, ::Optimizer) to print a nice string when someone prints your model. For example

function Base.show(io::IO, model::Optimizer)
+    return print(io, "NewSolver with the pointer $(model.ptr)")
+end

Implement attributes

MathOptInterface uses attributes to manage different aspects of the problem.

For each attribute

  • get gets the current value of the attribute
  • set sets a new value of the attribute. Not all attributes can be set. For example, the user can't modify the SolverName.
  • supports returns a Bool indicating whether the solver supports the attribute.
Info

Use attribute_value_type to check the value expected by a given attribute. You should make sure that your get function correctly infers to this type (or a subtype of it).

Each column in the table indicates whether you need to implement the particular method for each attribute.

Attributegetsetsupports
SolverNameYesNoNo
SolverVersionYesNoNo
RawSolverYesNoNo
NameYesYesYes
SilentYesYesYes
TimeLimitSecYesYesYes
ObjectiveLimitYesYesYes
SolutionLimitYesYesYes
RawOptimizerAttributeYesYesYes
NumberOfThreadsYesYesYes
AbsoluteGapToleranceYesYesYes
RelativeGapToleranceYesYesYes

For example:

function MOI.get(model::Optimizer, ::MOI.Silent)
+    return # true if MOI.Silent is set
+end
+
+function MOI.set(model::Optimizer, ::MOI.Silent, v::Bool)
+    if v
+        # Set a parameter to turn off printing
+    else
+        # Restore the default printing
+    end
+    return
+end
+
+MOI.supports(::Optimizer, ::MOI.Silent) = true

Define supports_constraint

The next step is to define which constraints and objective functions you plan to support.

For each function-set constraint pair, define supports_constraint:

function MOI.supports_constraint(
+    ::Optimizer,
+    ::Type{MOI.VariableIndex},
+    ::Type{MOI.ZeroOne},
+)
+    return true
+end

To make this easier, you may want to use Unions:

function MOI.supports_constraint(
+    ::Optimizer,
+    ::Type{MOI.VariableIndex},
+    ::Type{<:Union{MOI.LessThan,MOI.GreaterThan,MOI.EqualTo}},
+)
+    return true
+end
Tip

Only support a constraint if your solver has native support for it.

The big decision: incremental modification?

Now you need to decide whether to support incremental modification or not.

Incremental modification means that the user can add variables and constraints one-by-one without needing to rebuild the entire problem, and they can modify the problem data after an optimize! call. Supporting incremental modification means implementing functions like add_variable and add_constraint.

The alternative is to accept the problem data in a single optimize! or copy_to function call. Because these functions see all of the data at once, it can typically call a more efficient function to load data into the underlying solver.

Good examples of solvers supporting incremental modification are MILP solvers like GLPK.jl and Gurobi.jl. Examples of non-incremental solvers are AmplNLWriter.jl and SCS.jl

It is possible for a solver to implement both approaches, but you should probably start with one for simplicity.

Tip

Only support incremental modification if your solver has native support for it.

In general, supporting incremental modification is more work, and it usually requires some extra book-keeping. However, it provides a more efficient interface to the solver if the problem is going to be resolved multiple times with small modifications. Moreover, once you've implemented incremental modification, it's usually not much extra work to add a copy_to interface. The converse is not true.

Tip

If this is your first time writing an interface, start with the one-shot optimize!.

The non-incremental interface

There are two ways to implement the non-incremental interface. The first uses a two-argument version of optimize!, the second implements copy_to followed by the one-argument version of optimize!.

If your solver does not support modification, and requires all data to solve the problem in a single function call, you should implement the "one-shot" optimize!.

If your solver separates data loading and the actual optimization into separate steps, implement the copy_to interface.

The incremental interface

Warning

Writing this interface is a lot of work. The easiest way is to consult the source code of a similar solver.

To implement the incremental interface, implement the following functions:

Info

Solvers do not have to support AbstractScalarFunction in GreaterThan, LessThan, EqualTo, or Interval with a nonzero constant in the function. Throw ScalarFunctionConstantNotZero if the function constant is not zero.

In addition, you should implement the following model attributes:

Attributegetsetsupports
ListOfModelAttributesSetYesNoNo
ObjectiveFunctionTypeYesNoNo
ObjectiveFunctionYesYesYes
ObjectiveSenseYesYesYes
NameYesYesYes

Variable-related attributes:

Attributegetsetsupports
ListOfVariableAttributesSetYesNoNo
ListOfVariablesWithAttributeSetYesNoNo
NumberOfVariablesYesNoNo
ListOfVariableIndicesYesNoNo

Constraint-related attributes:

Attributegetsetsupports
ListOfConstraintAttributesSetYesNoNo
ListOfConstraintsWithAttributeSetYesNoNo
NumberOfConstraintsYesNoNo
ListOfConstraintTypesPresentYesNoNo
ConstraintFunctionYesYesNo
ConstraintSetYesYesNo

Modifications

If your solver supports modifying data in-place, implement modify for the following AbstractModifications:

Variables constrained on creation

Some solvers require variables be associated with a set when they are created. This conflicts with the incremental modification approach, since you cannot first add a free variable and then constrain it to the set.

If this is the case, implement:

By default, MathOptInterface assumes solvers support free variables. If your solver does not support free variables, define:

MOI.supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false

Incremental and copy_to

If you implement the incremental interface, you have the option of also implementing copy_to.

If you don't want to implement copy_to, for example, because the solver has no API for building the problem in a single function call, define the following fallback:

MOI.supports_incremental_interface(::Optimizer) = true
+
+function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
+    return MOI.Utilities.default_copy_to(dest, src)
+end

Names

Regardless of which interface you implement, you have the option of implementing the Name attribute for variables and constraints:

Attributegetsetsupports
VariableNameYesYesYes
ConstraintNameYesYesYes

If you implement names, you must also implement the following three methods:

function MOI.get(model::Optimizer, ::Type{MOI.VariableIndex}, name::String)
+    return # The variable named `name`.
+end
+
+function MOI.get(model::Optimizer, ::Type{MOI.ConstraintIndex}, name::String)
+    return # The constraint any type named `name`.
+end
+
+function MOI.get(
+    model::Optimizer,
+    ::Type{MOI.ConstraintIndex{F,S}},
+    name::String,
+) where {F,S}
+    return # The constraint of type F-in-S named `name`.
+end

These methods have the following rules:

  • If there is no variable or constraint with the name, return nothing
  • If there is a single variable or constraint with that name, return the variable or constraint
  • If there are multiple variables or constraints with the name, throw an error.
Warning

You should not implement ConstraintName for VariableIndex constraints. If you implement ConstraintName for other constraints, you can add the following two methods to disable ConstraintName for VariableIndex constraints.

function MOI.supports(
+    ::Optimizer,
+    ::MOI.ConstraintName,
+    ::Type{<:MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet}},
+)
+    return throw(MOI.VariableIndexConstraintNameError())
+end
+function MOI.set(
+    ::Optimizer,
+    ::MOI.ConstraintName,
+    ::MOI.ConstraintIndex{MOI.VariableIndex,<:MOI.AbstractScalarSet},
+    ::String,
+)
+    return throw(MOI.VariableIndexConstraintNameError())
+end

Solutions

Implement optimize! to solve the model:

All Optimizers must implement the following attributes:

Info

You only need to implement get for solution attributes. Don't implement set or supports.

Note

Solver wrappers should document how the low-level statuses map to the MOI statuses. Statuses like NEARLY_FEASIBLE_POINT and INFEASIBLE_POINT, are designed to be used when the solver explicitly indicates that relaxed tolerances are satisfied or the returned point is infeasible, respectively.

You should also implement the following attributes:

Tip

Attributes like VariablePrimal and ObjectiveValue are indexed by the result count. Use MOI.check_result_index_bounds(model, attr) to throw an error if the attribute is not available.

If your solver returns dual solutions, implement:

For integer solvers, implement:

If applicable, implement:

If your solver uses the Simplex method, implement:

If your solver accepts primal or dual warm-starts, implement:

Other tips

Here are some other points to be aware of when writing your wrapper.

Unsupported constraints at runtime

In some cases, your solver may support a particular type of constraint (for example, quadratic constraints), but only if the data meets some condition (for example, it is convex).

In this case, declare that you support the constraint, and throw AddConstraintNotAllowed.

Dealing with multiple variable bounds

MathOptInterface uses VariableIndex constraints to represent variable bounds. Defining multiple variable bounds on a single variable is not allowed.

Throw LowerBoundAlreadySet or UpperBoundAlreadySet if the user adds a constraint that results in multiple bounds.

Only throw if the constraints conflict. It is okay to add VariableIndex-in-GreaterThan and then VariableIndex-in-LessThan, but not VariableIndex-in-Interval and then VariableIndex-in-LessThan,

Expect duplicate coefficients

Solvers must expect that functions such as ScalarAffineFunction and VectorQuadraticFunction may contain duplicate coefficients.

For example, ScalarAffineFunction([ScalarAffineTerm(x, 1), ScalarAffineTerm(x, 1)], 0.0).

Use Utilities.canonical to return a new function with the duplicate coefficients aggregated together.

Don't modify user-data

All data passed to the solver must be copied immediately to internal data structures. Solvers may not modify any input vectors and must assume that input vectors will not be modified by users in the future.

This applies, for example, to the terms vector in ScalarAffineFunction. Vectors returned to the user, for example, via ObjectiveFunction or ConstraintFunction attributes, must not be modified by the solver afterwards. The in-place version of get! can be used by users to avoid extra copies in this case.

Column Generation

There is no special interface for column generation. If the solver has a special API for setting coefficients in existing constraints when adding a new variable, it is possible to queue modifications and new variables and then call the solver's API once all of the new coefficients are known.

Solver-specific attributes

You don't need to restrict yourself to the attributes defined in the MathOptInterface.jl package.

Solver-specific attributes should be specified by creating an appropriate subtype of AbstractModelAttribute, AbstractOptimizerAttribute, AbstractVariableAttribute, or AbstractConstraintAttribute.

For example, Gurobi.jl adds attributes for multiobjective optimization by defining:

struct NumberOfObjectives <: MOI.AbstractModelAttribute end
+
+function MOI.set(model::Optimizer, ::NumberOfObjectives, n::Integer)
+    # Code to set NumberOfObjectives
+    return
+end
+
+function MOI.get(model::Optimizer, ::NumberOfObjectives)
+    n = # Code to get NumberOfObjectives
+    return n
+end

Then, the user can write:

model = Gurobi.Optimizer()
+MOI.set(model, Gurobi.NumberofObjectives(), 3)
diff --git a/previews/PR2418/tutorials/latency/index.html b/previews/PR2418/tutorials/latency/index.html new file mode 100644 index 0000000000..db3242ffef --- /dev/null +++ b/previews/PR2418/tutorials/latency/index.html @@ -0,0 +1,129 @@ + +Latency · MathOptInterface

Latency

MathOptInterface suffers the "time-to-first-solve" problem of start-up latency.

This hurts both the user- and developer-experience of MathOptInterface. In the first case, because simple models have a multi-second delay before solving, and in the latter, because our tests take so long to run.

This page contains some advice on profiling and fixing latency-related problems in the MathOptInterface.jl repository.

Background

Before reading this part of the documentation, you should familiarize yourself with the reasons for latency in Julia and how to fix them.

Causes

There are three main causes of latency in MathOptInterface:

  1. A large number of types
  2. Lack of method ownership
  3. Type-instability in the bridge layer

A large number of types

Julia is very good at specializing method calls based on the input type. Each specialization has a compilation cost, but the benefit of faster run-time performance.

The best-case scenario is for a method to be called a large number of times with a single set of argument types. The worst-case scenario is for a method to be called a single time for a large set of argument types.

Because of MathOptInterface's function-in-set formulation, we fall into the worst-case situation.

This is a fundamental limitation of Julia, so there isn't much we can do about it. However, if we can precompile MathOptInterface, much of the cost can be shifted from start-up latency to the time it takes to precompile a package on installation.

However, there are two things which make MathOptInterface hard to precompile.

Lack of method ownership

Lack of method ownership happens when a call is made using a mix of structs and methods from different modules. Because of this, no single module "owns" the method that is being dispatched, and so it cannot be precompiled.

Tip

This is a slightly simplified explanation. Read the precompilation tutorial for a more in-depth discussion on back-edges.

Unfortunately, the design of MOI means that this is a frequent occurrence: we have a bunch of types in MOI.Utilities that wrap types defined in external packages (for example, the Optimizers), which implement methods of functions defined in MOI (for example, add_variable, add_constraint).

Here's a simple example of method-ownership in practice:

module MyMOI
+struct Wrapper{T}
+    inner::T
+end
+optimize!(x::Wrapper) = optimize!(x.inner)
+end  # MyMOI
+
+module MyOptimizer
+using ..MyMOI
+struct Optimizer end
+MyMOI.optimize!(x::Optimizer) = 1
+end  # MyOptimizer
+
+using SnoopCompile
+model = MyMOI.Wrapper(MyOptimizer.Optimizer())
+
+julia> tinf = @snoopi_deep MyMOI.optimize!(model)
+InferenceTimingNode: 0.008256/0.008543 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 1 direct children

The result is that there was one method that required type inference. If we visualize tinf:

using ProfileView
+ProfileView.view(flamegraph(tinf))

we see a flamegraph with a large red-bar indicating that the method MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) cannot be precompiled.

To fix this, we need to designate a module to "own" that method (that is, create a back-edge). The easiest way to do this is for MyOptimizer to call MyMOI.optimize(MyMOI.Wrapper{MyOptimizer.Optimizer}) during using MyOptimizer. Let's see that in practice:

module MyMOI
+struct Wrapper{T}
+    inner::T
+end
+optimize(x::Wrapper) = optimize(x.inner)
+end  # MyMOI
+
+module MyOptimizer
+using ..MyMOI
+struct Optimizer end
+MyMOI.optimize(x::Optimizer) = 1
+# The syntax of this let-while loop is very particular:
+#  * `let ... end` keeps everything local to avoid polluting the MyOptimizer
+#    namespace
+#  * `while true ... break end` runs the code once, and forces Julia to compile
+#    the inner loop, rather than interpret it.
+let
+    while true
+        model = MyMOI.Wrapper(Optimizer())
+        MyMOI.optimize(model)
+        break
+    end
+end
+end  # MyOptimizer
+
+using SnoopCompile
+model = MyMOI.Wrapper(MyOptimizer.Optimizer())
+
+julia> tinf = @snoopi_deep MyMOI.optimize(model)
+InferenceTimingNode: 0.006822/0.006822 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 0 direct children

There are now 0 direct children that required type inference because the method was already stored in MyOptimizer!

Unfortunately, this trick only works if the call-chain is fully inferrable. If there are breaks (due to type instability), then the benefit of doing this is reduced. And unfortunately for us, the design of MathOptInterface has a lot of type instabilities.

Type instability in the bridge layer

Most of MathOptInterface is pretty good at ensuring type-stability. However, a key component is not type stable, and that is the bridging layer.

In particular, the bridging layer defines Bridges.LazyBridgeOptimizer, which has fields like:

struct LazyBridgeOptimizer
+    constraint_bridge_types::Vector{Any}
+    constraint_node::Dict{Tuple{Type,Type},ConstraintNode}
+    constraint_types::Vector{Tuple{Type,Type}}
+end

This is because the LazyBridgeOptimizer needs to be able to deal with any function-in-set type passed to it, and we also allow users to pass additional bridges that they defined in external packages.

So to recap, MathOptInterface suffers package latency because:

  1. there are a large number of types and functions
  2. and these are split between multiple modules, including external packages
  3. and there are type-instabilities like those in the bridging layer.

Resolutions

There are no magic solutions to reduce latency. Issue #1313 tracks progress on reducing latency in MathOptInterface.

A useful script is the following (replace GLPK as needed):

import GLPK
+import MathOptInterface as MOI
+
+function example_diet(optimizer, bridge)
+    category_data = [
+        1800.0 2200.0;
+          91.0    Inf;
+           0.0   65.0;
+           0.0 1779.0
+    ]
+    cost = [2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59]
+    food_data = [
+        410 24 26 730;
+        420 32 10 1190;
+        560 20 32 1800;
+        380  4 19 270;
+        320 12 10 930;
+        320 15 12 820;
+        320 31 12 1230;
+        100  8 2.5 125;
+        330  8 10 180
+    ]
+    bridge_model = if bridge
+        MOI.instantiate(optimizer; with_bridge_type=Float64)
+    else
+        MOI.instantiate(optimizer)
+    end
+    model = MOI.Utilities.CachingOptimizer(
+        MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
+        MOI.Utilities.AUTOMATIC,
+    )
+    MOI.Utilities.reset_optimizer(model, bridge_model)
+    MOI.set(model, MOI.Silent(), true)
+    nutrition = MOI.add_variables(model, size(category_data, 1))
+    for (i, v) in enumerate(nutrition)
+        MOI.add_constraint(model, v, MOI.GreaterThan(category_data[i, 1]))
+        MOI.add_constraint(model, v, MOI.LessThan(category_data[i, 2]))
+    end
+    buy = MOI.add_variables(model, size(food_data, 1))
+    MOI.add_constraint.(model, buy, MOI.GreaterThan(0.0))
+    MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
+    f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(cost, buy), 0.0)
+    MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
+    for (j, n) in enumerate(nutrition)
+        f = MOI.ScalarAffineFunction(
+            MOI.ScalarAffineTerm.(food_data[:, j], buy),
+            0.0,
+        )
+        push!(f.terms, MOI.ScalarAffineTerm(-1.0, n))
+        MOI.add_constraint(model, f, MOI.EqualTo(0.0))
+    end
+    MOI.optimize!(model)
+    term_status = MOI.get(model, MOI.TerminationStatus())
+    @assert term_status == MOI.OPTIMAL
+    MOI.add_constraint(
+        model,
+        MOI.ScalarAffineFunction(
+            MOI.ScalarAffineTerm.(1.0, [buy[end-1], buy[end]]),
+            0.0,
+        ),
+        MOI.LessThan(6.0),
+    )
+    MOI.optimize!(model)
+    @assert MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
+    return
+end
+
+if length(ARGS) > 0
+    bridge = get(ARGS, 2, "") != "--no-bridge"
+    println("Running: $(ARGS[1]) $(get(ARGS, 2, ""))")
+    @time example_diet(GLPK.Optimizer, bridge)
+    @time example_diet(GLPK.Optimizer, bridge)
+    exit(0)
+end

You can create a flame-graph via

using SnoopCompile
+tinf = @snoopi_deep example_diet(GLPK.Optimizer, true)
+using ProfileView
+ProfileView.view(flamegraph(tinf))

Here's how things looked in mid-August 2021: flamegraph

There are a few opportunities for improvement (non-red flames, particularly on the right). But the main problem is a large red (non-precompilable due to method ownership) flame.

diff --git a/previews/PR2418/tutorials/manipulating_expressions/index.html b/previews/PR2418/tutorials/manipulating_expressions/index.html new file mode 100644 index 0000000000..15aef54784 --- /dev/null +++ b/previews/PR2418/tutorials/manipulating_expressions/index.html @@ -0,0 +1,22 @@ + +Manipulating expressions · MathOptInterface

Manipulating expressions

This guide highlights a syntactically appealing way to build expressions at the MOI level, but also to look at their contents. It may be especially useful when writing models or bridge code.

Creating functions

This section details the ways to create functions with MathOptInterface.

Creating scalar affine functions

The simplest scalar function is simply a variable:

julia> x = MOI.add_variable(model) # Create the variable x
+MOI.VariableIndex(1)

This type of function is extremely simple; to express more complex functions, other types must be used. For instance, a ScalarAffineFunction is a sum of linear terms (a factor times a variable) and a constant. Such an object can be built using the standard constructor:

julia> f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1, x)], 2) # x + 2
+(2) + (1) MOI.VariableIndex(1)

However, you can also use operators to build the same scalar function:

julia> f = x + 2
+(2) + (1) MOI.VariableIndex(1)

Creating scalar quadratic functions

Scalar quadratic functions are stored in ScalarQuadraticFunction objects, in a way that is highly similar to scalar affine functions. You can obtain a quadratic function as a product of affine functions:

julia> 1 * x * x
+(0) + 1.0 MOI.VariableIndex(1)²
+
+julia> f * f  # (x + 2)²
+(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²
+
+julia> f^2  # (x + 2)² too
+(4) + (2) MOI.VariableIndex(1) + (2) MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)²

Creating vector functions

A vector function is a function with several values, irrespective of the number of input variables. Similarly to scalar functions, there are three main types of vector functions: VectorOfVariables, VectorAffineFunction, and VectorQuadraticFunction.

The easiest way to create a vector function is to stack several scalar functions using Utilities.vectorize. It takes a vector as input, and the generated vector function (of the most appropriate type) has each dimension corresponding to a dimension of the vector.

julia> g = MOI.Utilities.vectorize([f, 2 * f])
+┌                              ┐
+│(2) + (1) MOI.VariableIndex(1)│
+│(4) + (2) MOI.VariableIndex(1)│
+└                              ┘
Warning

Utilities.vectorize only takes a vector of similar scalar functions: you cannot mix VariableIndex and ScalarAffineFunction, for instance. In practice, it means that Utilities.vectorize([x, f]) does not work; you should rather use Utilities.vectorize([1 * x, f]) instead to only have ScalarAffineFunction objects.

Canonicalizing functions

In more advanced use cases, you might need to ensure that a function is "canonical." Functions are stored as an array of terms, but there is no check that these terms are redundant: a ScalarAffineFunction object might have two terms with the same variable, like x + x + 1. These terms could be merged without changing the semantics of the function: 2x + 1.

Working with these objects might be cumbersome. Canonicalization helps maintain redundancy to zero.

Utilities.is_canonical checks whether a function is already in its canonical form:

julia> MOI.Utilities.is_canonical(f + f) # (x + 2) + (x + 2) is stored as x + x + 4
+false

Utilities.canonical returns the equivalent canonical version of the function:

julia> MOI.Utilities.canonical(f + f) # Returns 2x + 4
+(4) + (2) MOI.VariableIndex(1)

Exploring functions

At some point, you might need to dig into a function, for instance to map it into solver constructs.

Vector functions

Utilities.scalarize returns a vector of scalar functions from a vector function:

julia> MOI.Utilities.scalarize(g) # Returns a vector [f, 2 * f].
+2-element Vector{MathOptInterface.ScalarAffineFunction{Int64}}:
+ (2) + (1) MOI.VariableIndex(1)
+ (4) + (2) MOI.VariableIndex(1)
Note

Utilities.eachscalar returns an iterator on the dimensions, which serves the same purpose as Utilities.scalarize.

output_dimension returns the number of dimensions of the output of a function:

julia> MOI.output_dimension(g)
+2
diff --git a/previews/PR2418/tutorials/mathprogbase/index.html b/previews/PR2418/tutorials/mathprogbase/index.html new file mode 100644 index 0000000000..bb59e3d2f7 --- /dev/null +++ b/previews/PR2418/tutorials/mathprogbase/index.html @@ -0,0 +1,54 @@ + +Transitioning from MathProgBase · MathOptInterface

Transitioning from MathProgBase

MathOptInterface is a replacement for MathProgBase.jl. However, it is not a direct replacement.

Transitioning a solver interface

MathOptInterface is more extensive than MathProgBase which may make its implementation seem daunting at first. There are however numerous utilities in MathOptInterface that the simplify implementation process.

For more information, read Implementing a solver interface.

Transitioning the high-level functions

MathOptInterface doesn't provide replacements for the high-level interfaces in MathProgBase. We recommend you use JuMP as a modeling interface instead.

Tip

If you haven't used JuMP before, start with the tutorial Getting started with JuMP

linprog

Here is one way of transitioning from linprog:

using JuMP
+
+function linprog(c, A, sense, b, l, u, solver)
+    N = length(c)
+    model = Model(solver)
+    @variable(model, l[i] <= x[i=1:N] <= u[i])
+    @objective(model, Min, c' * x)
+    eq_rows, ge_rows, le_rows = sense .== '=', sense .== '>', sense .== '<'
+    @constraint(model, A[eq_rows, :] * x .== b[eq_rows])
+    @constraint(model, A[ge_rows, :] * x .>= b[ge_rows])
+    @constraint(model, A[le_rows, :] * x .<= b[le_rows])
+    optimize!(model)
+    return (
+        status = termination_status(model),
+        objval = objective_value(model),
+        sol = value.(x)
+    )
+end

mixintprog

Here is one way of transitioning from mixintprog:

using JuMP
+
+function mixintprog(c, A, rowlb, rowub, vartypes, lb, ub, solver)
+    N = length(c)
+    model = Model(solver)
+    @variable(model, lb[i] <= x[i=1:N] <= ub[i])
+    for i in 1:N
+        if vartypes[i] == :Bin
+            set_binary(x[i])
+        elseif vartypes[i] == :Int
+            set_integer(x[i])
+        end
+    end
+    @objective(model, Min, c' * x)
+    @constraint(model, rowlb .<= A * x .<= rowub)
+    optimize!(model)
+    return (
+        status = termination_status(model),
+        objval = objective_value(model),
+        sol = value.(x)
+    )
+end

quadprog

Here is one way of transitioning from quadprog:

using JuMP
+
+function quadprog(c, Q, A, rowlb, rowub, lb, ub, solver)
+    N = length(c)
+    model = Model(solver)
+    @variable(model, lb[i] <= x[i=1:N] <= ub[i])
+    @objective(model, Min, c' * x + 0.5 * x' * Q * x)
+    @constraint(model, rowlb .<= A * x .<= rowub)
+    optimize!(model)
+    return (
+        status = termination_status(model),
+        objval = objective_value(model),
+        sol = value.(x)
+    )
+end