text:
using JuMP, EAGO

                     m = Model()

                     EAGO.register_eago_operators!(m)

                     @variable(m, -1 <= x[i=1:5] <= 1)

                     @variable(m, -58.37772561872491 <= q <= 51.748312049639644)

                     add_NL_constraint(m, :(log(1 + exp(-0.3976822916974827 + -0.11888104611683081*log(1 + exp(-0.09559544092481564 + 0.23201220435158865*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.9126138494455787*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.24324641666113456*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.1690500900766101*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.20833731206579253*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.8277675607937618*log(1 + exp(-0.41653739657549194 + 0.7547021537813423*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.5787262183714494*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.11492508246438904*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.30062983013792843*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.1276250114011983*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.37430250255255215*log(1 + exp(0.9557400948867283 + -0.3128610884258398*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.29518845150992634*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.18188148649835556*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.8330182900675651*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.8804319372999063*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.9159784725268092*log(1 + exp(-0.32868009819829513 + 0.7041500634234112*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.44147758504740464*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.5937281428689025*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.3198554528784734*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.047330375221362964*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.21239133839693736*log(1 + exp(-0.6560670298284208 + 0.11579976545709414*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.7227941593613254*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.5041216754022764*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.9501104307252297*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.7033943599032555*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))))) + log(1 + exp(-0.962366690533889 + 0.21288820713294498*log(1 + exp(-0.09559544092481564 + 0.23201220435158865*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.9126138494455787*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.24324641666113456*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.1690500900766101*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.20833731206579253*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.04621026197884115*log(1 + exp(-0.41653739657549194 + 0.7547021537813423*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.5787262183714494*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.11492508246438904*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.30062983013792843*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.1276250114011983*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.3579305330052933*log(1 + exp(0.9557400948867283 + -0.3128610884258398*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.29518845150992634*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.18188148649835556*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.8330182900675651*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.8804319372999063*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.40247732796428703*log(1 + exp(-0.32868009819829513 + 0.7041500634234112*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.44147758504740464*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.5937281428689025*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.3198554528784734*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.047330375221362964*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.3937461182921762*log(1 + exp(-0.6560670298284208 + 0.11579976545709414*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.7227941593613254*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.5041216754022764*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.9501104307252297*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.7033943599032555*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))))) + log(1 + exp(-0.9189915189234159 + -0.5125130010222394*log(1 + exp(-0.09559544092481564 + 0.23201220435158865*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.9126138494455787*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.24324641666113456*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.1690500900766101*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.20833731206579253*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.3502499398907637*log(1 + exp(-0.41653739657549194 + 0.7547021537813423*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.5787262183714494*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.11492508246438904*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.30062983013792843*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.1276250114011983*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.8274375080497247*log(1 + exp(0.9557400948867283 + -0.3128610884258398*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.29518845150992634*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.18188148649835556*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.8330182900675651*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.8804319372999063*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.7757421130805153*log(1 + exp(-0.32868009819829513 + 0.7041500634234112*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.44147758504740464*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.5937281428689025*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.3198554528784734*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.047330375221362964*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.6602598595684599*log(1 + exp(-0.6560670298284208 + 0.11579976545709414*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.7227941593613254*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.5041216754022764*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.9501104307252297*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.7033943599032555*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))))) + log(1 + exp(-0.760456357412739 + 0.8974231726544617*log(1 + exp(-0.09559544092481564 + 0.23201220435158865*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.9126138494455787*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.24324641666113456*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.1690500900766101*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.20833731206579253*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.7589867374120325*log(1 + exp(-0.41653739657549194 + 0.7547021537813423*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.5787262183714494*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.11492508246438904*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.30062983013792843*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.1276250114011983*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.3014899851721653*log(1 + exp(0.9557400948867283 + -0.3128610884258398*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.29518845150992634*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.18188148649835556*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.8330182900675651*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.8804319372999063*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.03263132145111802*log(1 + exp(-0.32868009819829513 + 0.7041500634234112*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.44147758504740464*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.5937281428689025*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.3198554528784734*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.047330375221362964*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.8460059521417822*log(1 + exp(-0.6560670298284208 + 0.11579976545709414*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.7227941593613254*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.5041216754022764*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.9501104307252297*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.7033943599032555*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))))) + log(1 + exp(-0.1364886291423204 + -0.7689732133011344*log(1 + exp(-0.09559544092481564 + 0.23201220435158865*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.9126138494455787*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.24324641666113456*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.1690500900766101*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.20833731206579253*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.9275671307049969*log(1 + exp(-0.41653739657549194 + 0.7547021537813423*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.5787262183714494*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.11492508246438904*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.30062983013792843*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.1276250114011983*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.311285022430249*log(1 + exp(0.9557400948867283 + -0.3128610884258398*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.29518845150992634*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.18188148649835556*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + 0.8330182900675651*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.8804319372999063*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + -0.2373305013184268*log(1 + exp(-0.32868009819829513 + 0.7041500634234112*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + -0.44147758504740464*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + -0.5937281428689025*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.3198554528784734*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + -0.047330375221362964*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))) + 0.7676258102518863*log(1 + exp(-0.6560670298284208 + 0.11579976545709414*log(1 + exp(0.22080335056838862 + -0.11207096478827117*$(x[1]) + 0.9802919969431398*$(x[2]) + -0.17783835331857878*$(x[3]) + 0.5553411614422452*$(x[4]) + 0.8384080073044262*$(x[5]))) + 0.7227941593613254*log(1 + exp(-0.03619259662306584 + -0.3774088093292831*$(x[1]) + 0.859114754276578*$(x[2]) + -0.4844223734792257*$(x[3]) + 0.08654340008535533*$(x[4]) + -0.46594229223618644*$(x[5]))) + 0.5041216754022764*log(1 + exp(-0.05960623749041094 + -0.4311407494411239*$(x[1]) + -0.025139997052890273*$(x[2]) + 0.060401892548068936*$(x[3]) + 0.5875386419954256*$(x[4]) + 0.5553096462934759*$(x[5]))) + -0.9501104307252297*log(1 + exp(0.12047524138880839 + -0.4988789730921872*$(x[1]) + -0.41177595995379823*$(x[2]) + -0.6913890776083331*$(x[3]) + 0.032955544793602076*$(x[4]) + -0.5657303188428733*$(x[5]))) + 0.7033943599032555*log(1 + exp(-0.14422850857319736 + 0.5362813944125526*$(x[1]) + 0.29620144485119626*$(x[2]) + -0.18264867223264059*$(x[3]) + 0.5265937438977235*$(x[4]) + 0.6008528580664168*$(x[5]))))))) - $q <= 0.0))

                     @objective(m, Min, q)

                     return m

max_stars_repo_name: PSORLab/RSActivationFunctions

max_issues_repo_name: PSORLab/RSActivationFunctions

max_forks_repo_name: PSORLab/RSActivationFunctions


text:
## Test invalid sequences

# Continuation byte not after lead
for byt in 0x80:0xbf
    @test_throws UnicodeError check_string(UInt8[byt])
end

# Test lead bytes
for byt in 0xc0:0xff
    # Single lead byte at end of string
    @test_throws UnicodeError check_string(UInt8[byt])
    # Lead followed by non-continuation character < 0x80
    @test_throws UnicodeError check_string(UInt8[byt,0])
    # Lead followed by non-continuation character > 0xbf
    @test_throws UnicodeError check_string(UInt8[byt,0xc0])
end

# Test overlong 2-byte
for byt in 0x81:0xbf
    @test_throws UnicodeError check_string(UInt8[0xc0,byt])
end
for byt in 0x80:0xbf
    @test_throws UnicodeError check_string(UInt8[0xc1,byt])
end

# Test overlong 3-byte
for byt in 0x80:0x9f
    @test_throws UnicodeError check_string(UInt8[0xe0,byt,0x80])
end

# Test overlong 4-byte
for byt in 0x80:0x8f
    @test_throws UnicodeError check_string(UInt8[0xef,byt,0x80,0x80])
end

# Test 4-byte > 0x10ffff
for byt in 0x90:0xbf
    @test_throws UnicodeError check_string(UInt8[0xf4,byt,0x80,0x80])
end
for byt in 0xf5:0xf7
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0x80,0x80])
end

# Test 5-byte
for byt in 0xf8:0xfb
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0x80,0x80,0x80])
end

# Test 6-byte
for byt in 0xfc:0xfd
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0x80,0x80,0x80,0x80])
end

# Test 7-byte
@test_throws UnicodeError check_string(UInt8[0xfe,0x80,0x80,0x80,0x80,0x80,0x80])

# Three and above byte sequences
for byt in 0xe0:0xef
    # Lead followed by only 1 continuation byte
    @test_throws UnicodeError check_string(UInt8[byt,0x80])
    # Lead ended by non-continuation character < 0x80
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0])
    # Lead ended by non-continuation character > 0xbf
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0xc0])
end

# 3-byte encoded surrogate character(s)
# Single surrogate
@test_throws UnicodeError check_string(UInt8[0xed,0xa0,0x80])
# Not followed by surrogate
@test_throws UnicodeError check_string(UInt8[0xed,0xa0,0x80,0xed,0x80,0x80])
# Trailing surrogate first
@test_throws UnicodeError check_string(UInt8[0xed,0xb0,0x80,0xed,0xb0,0x80])
# Followed by lead surrogate
@test_throws UnicodeError check_string(UInt8[0xed,0xa0,0x80,0xed,0xa0,0x80])

# Four byte sequences
for byt in 0xf0:0xf4
    # Lead followed by only 2 continuation bytes
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0x80])
    # Lead followed by non-continuation character < 0x80
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0x80,0])
    # Lead followed by non-continuation character > 0xbf
    @test_throws UnicodeError check_string(UInt8[byt,0x80,0x80,0xc0])
end

# Long encoding of 0x01

@test_throws UnicodeError utf8([0xf0, 0x80, 0x80, 0x80])
# Test ends of long encoded surrogates
@test_throws UnicodeError utf8([0xf0, 0x8d, 0xa0, 0x80])
@test_throws UnicodeError utf8([0xf0, 0x8d, 0xbf, 0xbf])
@test_throws UnicodeError check_string([0xf0, 0x80, 0x80, 0x80])
@test check_string([0xc0, 0x81]; accept_long_char=true) == (1,0x1,0,0,0,0,0)
@test check_string([0xf0, 0x80, 0x80, 0x80]; accept_long_char=true) == (1,0x1,0,0,0,0,0)

# Surrogates
@test_throws UnicodeError check_string(UInt16[0xd800])
@test_throws UnicodeError check_string(UInt16[0xdc00])
@test_throws UnicodeError check_string(UInt16[0xdc00,0xd800])

# Surrogates in UTF-32
@test_throws UnicodeError check_string(UInt32[0xd800])
@test_throws UnicodeError check_string(UInt32[0xdc00])
@test_throws UnicodeError check_string(UInt32[0xdc00,0xd800])

# Characters > 0x10ffff
@test_throws UnicodeError check_string(UInt32[0x110000])

# Test more invalid (overlong) sequences
for (seq, res) in (
    ([0xc0,0x80],          (1,1,0,0,0,0,0)),  # Long encoded Nul byte (Modified UTF-8, Java)
    ([0xed,0xa0,0x80,0xed,0xb0,0x80], (1,0x30,1,0,0,0,0)), # Overlong \U10000, (CESU-8)
    ([0xed,0xaf,0xbf,0xed,0xbf,0xbf], (1,0x30,1,0,0,0,0)), # Overlong \U10ffff, (CESU-8)
    ([0x0d800,0x0dc00],    (1,0x30,1,0,0,0,0)), # Overlong \U10000, (CESU-8)
    ([0x0dbff,0x0dfff],    (1,0x30,1,0,0,0,0))) # Overlong \U10ffff, (CESU-8)
    @test_throws UnicodeError check_string(seq)
    @test check_string(seq;accept_long_null=true, accept_surrogates=true, accept_long_char=true) == res
end

# Test conversions of invalid sequences

strval(::Type{UTF8Str}, dat) = dat
strval(::Union{Type{UTF16Str},Type{UTF32Str}}, dat) = convert(UTF8Str, dat)

for T in (UTF8Str, UTF16Str, UTF32Str)
    @testset "$T invalid sequences" begin
    # Continuation byte not after lead
    for byt in 0x80:0xbf
        @test_throws UnicodeError convert(T,  strval(T, UInt8[byt]))
    end

    # Test lead bytes
    for byt in 0xc0:0xff
        # Single lead byte at end of string
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt]))
        # Lead followed by non-continuation character < 0x80
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0]))
        # Lead followed by non-continuation character > 0xbf
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0xc0]))
    end

    # Test overlong 2-byte
    for byt in 0x81:0xbf
        @test_throws UnicodeError convert(T, strval(T, UInt8[0xc0,byt]))
    end
    for byt in 0x80:0xbf
        @test_throws UnicodeError convert(T, strval(T, UInt8[0xc1,byt]))
    end

    # Test overlong 3-byte
    for byt in 0x80:0x9f
        @test_throws UnicodeError convert(T, strval(T, UInt8[0xe0,byt,0x80]))
    end

    # Test overlong 4-byte
    for byt in 0x80:0x8f
        @test_throws UnicodeError convert(T, strval(T, UInt8[0xef,byt,0x80,0x80]))
    end

    # Test 4-byte > 0x10ffff
    for byt in 0x90:0xbf
        @test_throws UnicodeError convert(T, strval(T, UInt8[0xf4,byt,0x80,0x80]))
    end
    for byt in 0xf5:0xf7
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0x80,0x80]))
    end

    # Test 5-byte
    for byt in 0xf8:0xfb
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0x80,0x80,0x80]))
    end

    # Test 6-byte
    for byt in 0xfc:0xfd
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0x80,0x80,0x80,0x80]))
    end

    # Test 7-byte
    @test_throws UnicodeError convert(T, strval(T, UInt8[0xfe,0x80,0x80,0x80,0x80,0x80,0x80]))

    # Three and above byte sequences
    for byt in 0xe0:0xef
        # Lead followed by only 1 continuation byte
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80]))
        # Lead ended by non-continuation character < 0x80
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0]))
        # Lead ended by non-continuation character > 0xbf
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0xc0]))
    end

    # 3-byte encoded surrogate character(s)
    # Single surrogate
    @test_throws UnicodeError convert(T, strval(T, UInt8[0xed,0xa0,0x80]))
    # Not followed by surrogate
    @test_throws UnicodeError convert(T, strval(T, UInt8[0xed,0xa0,0x80,0xed,0x80,0x80]))
    # Trailing surrogate first
    @test_throws UnicodeError convert(T, strval(T, UInt8[0xed,0xb0,0x80,0xed,0xb0,0x80]))
    # Followed by lead surrogate
    @test_throws UnicodeError convert(T, strval(T, UInt8[0xed,0xa0,0x80,0xed,0xa0,0x80]))

    # Four byte sequences
    for byt in 0xf0:0xf4
        # Lead followed by only 2 continuation bytes
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0x80]))
        # Lead followed by non-continuation character < 0x80
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0x80,0]))
        # Lead followed by non-continuation character > 0xbf
        @test_throws UnicodeError convert(T, strval(T, UInt8[byt,0x80,0x80,0xc0]))
    end
    end
end

ext: jl


text:
module BooleanNetworks
export zerocfg, load_bnet, fasync_simulations, outputs_ratios, resolve

struct BooleanNetwork
    nodes::Vector{String}
    index::Dict{String,Int64}
    f::Vector{Function}
    out_influences::Vector{Vector{Int64}} # out-going influences
end

resolve(bn, indexes) = [bn.nodes[i] for i in indexes]

zerocfg(bn) = zeros(Bool, length(bn.f))

BNET_SYMBOL_RE = r"[\w\.:]+"

function load_bnet(filename, sep=",", impl_binary=true)
    data = [split(line, sep) for line in eachline(filename)]
    n = length(data)
    nodes = [strip(d[1]) for d in data]
    index = Dict(((n,i) for (i,n) in enumerate(nodes)))

    impl_expr_bin(expr) = "x -> " * replace(replace(expr,
            "!" => "~"),
             BNET_SYMBOL_RE => x -> "x[$(index[x])]")
    impl_expr_bool(expr) = "x -> " * replace(replace(replace(expr,
            "|" => "||"),
            "&" => "&&"),
             BNET_SYMBOL_RE => x -> "x[$(index[x])]")
    impl_expr = impl_binary ? impl_expr_bin : impl_expr_bool
    make_expr = eval ∘ Meta.parse ∘ impl_expr
    f = [make_expr(d[2]) for d in data]

    make_influences(expr) = [index[m.match] for m in eachmatch(BNET_SYMBOL_RE, expr)]
    influences = [make_influences(d[2]) for d in data]

    BooleanNetwork(nodes, index, f, influences)
end

struct FAsyncSimulationContext
    x::Vector{Bool}
    c::Vector{Int64}
end
new_fasync_simulation(n) = FAsyncSimulationContext(Vector{Bool}(undef, n), Vector{Int64}(undef, n))

function _fasync_step!(x, c, f, n)
    nc = 0
    for i in 1:n
        if f[i](x) ⊻ x[i]
            nc += 1
            c[nc] = i
        end
    end
    if nc == 0
        0
    else
        if nc == 1
            i = c[1]
        else
            i = c[rand(1:nc)]
        end
        x[i] = !x[i]
        i
    end
end

_fasync_unroll!(ctx, f, n, maxsteps) =
    for _ in 1:maxsteps
        if _fasync_step!(ctx.x, ctx.c, f, n) == 0
            break
        end
    end

function _fasync_simulation!(ctx, f, n, x, maxsteps, outputs)
    ctx.x[1:n] = x
    _fasync_unroll!(ctx, f, n, maxsteps)
    @view ctx.x[outputs]
end

function pack_output(binarray)
    x::Int64 = 0
    for i in 1:length(binarray)
        x |= binarray[i] << (i-1)
    end
    x
end
unpack_output(x, letters) = [a for (i,a) in enumerate(letters) if x & (1 << (i-1)) > 0]

function fasync_simulations(bn, outputs, nb_sims, maxsteps, x)
    f = bn.f
    n = length(f)
    res = Array{Int64}(undef, nb_sims)
    ctx = [new_fasync_simulation(n) for _ in 1:Threads.nthreads()]
    Threads.@threads :static for i in 1:nb_sims
        res[i] = pack_output(_fasync_simulation!(ctx[Threads.threadid()], f, n, x, maxsteps, outputs))
    end
    res
end

function outputs_ratios(result, outputs, bn)
    cv = zeros(Int64, 2^length(outputs))
    for k in result
        cv[k] += 1
    end
    make_key(k) = resolve(bn, unpack_output(k, outputs))
    Dict(make_key(k) => c/length(result) for (k,c) in enumerate(cv) if c > 0)
end

end


text:
using Distributions

# function definitions

function attempt_move!(agent::agent_type, destination, g, environments, model::AgentBasedModel)::Bool
  o = agent.pos
  d = destination
  if has_edge(g, o, d)
    move_agent!(agent, d, model)
    return true
    #println("moved between ", environments_2[o],  " and ",  environments_2[d])
  else
    #println("can't move between ", environments_2[o],  " and ",  environments_2[d])
    return false
  end
end

# initialise agents in specified model (note the below is for a GraphSpace)
function initialise_agents!(n_travellers, n_workers, model::AgentBasedModel, environments)
  for i in 1:(n_workers + n_travellers)
    if i <= n_workers
      add_agent!(environments["Hotel"], model)
      model[i].worker = true
      #println(model[i])
    else
      add_agent!(environments["Arrival"], model)
      model[i].traveller = true
      #println(model[i])
    end
  end
end

function initialise_work_schedule!(model::AgentBasedModel, environments, roster)
  days_of_the_week =  1:7;
  for i in keys(model.agents)
    if model[i].worker
      # assign work schedule
      shift_type = sample(rng, roster[1], roster[2])
      days_worked = shuffle(rng, days_of_the_week)
      days_worked[days_worked.> shift_type] .= 0
      days_worked[days_worked .> 0] .= 1
      workdays = days_of_the_week[days_worked .== 1]
      model[i].workdays = workdays
    end
  end
end

# check to make sure hotel is not understaffed:
function check_work_schedule(model::AgentBasedModel, n_min)::Bool
 days_of_the_week =  1:7
 workers_each_day = zeros(length(days_of_the_week))
  for i in keys(model.agents)
    if model[i].worker
      workers_each_day[model[i].workdays] .+= 1
    end
  end
  #println(workers_each_day)
  if minimum(workers_each_day) < n_min
    return false
  else
    return true
  end
end

# assigns uniform household sizes
function assign_households!(model::AgentBasedModel, n_per_hh, households)
  count = 0
  hh_id = 1
  households[hh_id] = household_type(hh_id, [])
  for i in keys(model.agents)
     if model[i].traveller
       model[i].hh_id = hh_id
       count += 1
       push!(households[hh_id].members, model[i].id)
       #println("assigned agent  $(model[i].id) to household $hh_id ")
       if count >= n_per_hh
         hh_id += 1
         households[hh_id] = household_type(hh_id, [])
         count = 0
       end
     end
   end

   # clean up empty households extras may be created due to workers and travellers
   # in teh same list.

   for hh_i in keys(households)
     if length(households[hh_i].members) == 0
       delete!(households, hh_i)
     end
   end

end

function vaccinate_all!(model::AgentBasedModel, pVac_Workers, pVac_Travellers)
  for i in keys(model.agents)
    if model[i].worker
      if rand(rng) < pVac_Workers
        model[i].vaccinated = true
      end
    elseif model[i].traveller
      if rand(rng) < pVac_Travellers
        model[i].vaccinated = true
      end
    end
  end
end

function vaccinate_infected_arrivals!(model::AgentBasedModel)
  for i in keys(model.agents)
    if model[i].traveller
      if environments_2[model[i].pos] == "Arrival"
        if model[i].infected && !model[i].vaccinated
          model[i].vaccinated = true
        end
      end
    end
  end
end

# infect arrivals and initialise infectivity and test sensitivity treajecotires

function infect_arrival!(agent::agent_type, # agent type
                         latent_period,
                         inc_dist, # incubation period distribution
                         r_dist,  # recovery period distribution
                         b_dist, # distribution of infectivity (gamma)
                         c_lims, # range for test sensitivity breakpoint
                         b1_lims, # range for max test sensitivity parameter b1
                         b2_lims, # range for test sensitivity growth parameter b2
                         b3_lims, # range for test sensitivity decay parameter b3
                         p_asymp # probability of becoming symptomatic after incubation
                         )

  agent.infected = true
  agent.index_case = true
  if rand(rng) < p_asymp
    agent.asymptomatic = true
  end
  while agent.incubation_period < latent_period
    agent.incubation_period = rand(rng, inc_dist)
  end
  agent.recovery_period = rand(rng, rec_dist)
  agent.beta_max = rand(rng, b_dist)
  agent.beta_min = agent.beta_max / Vmax

  # note the kinc and krec functions are in the 'disease' file
  agent.k_inc = compute_kinc(agent.incubation_period)
  agent.k_r = compute_krec(agent.recovery_period)

  q = cdf(inc_dist, agent.incubation_period)
  # set test sensitivity breakpoint - it's a function of incubation period
  agent.breakpoint = agent.incubation_period - ( q * (c_lims[2] - c_lims[1]))

  #set test sensitivity growth rate - also a function of incubation period
  agent.b2 = b2_lims[1] + (1.0 - q) * (b2_lims[2] - b2_lims[1])
  # might as well initialise the other test sensitivity terms too
  agent.b1 = b1_lims[1] + rand(rng) * (b1_lims[2] - b1_lims[1])
  agent.b3 = b3_lims[1] + rand(rng) * (b3_lims[2] - b3_lims[1])

  # determine infection status (timing) upon arrival
  # must be pre-symptomatic if not asymptomatic.

  if agent.asymptomatic
    agent.time_infected = rand(rng) * (agent.incubation_period + agent.recovery_period)
  else
    agent.time_infected = rand(rng) * agent.incubation_period
  end

  # determine current state based on time infected
  if agent.time_infected < latent_period
    agent.latent = true
    agent.incubating = true
    agent.time_incubating = agent.time_infected
  elseif agent.time_infected < agent.incubation_period
        agent.incubating = true
        agent.time_incubating = agent.time_infected
  else
         agent.recovering = true
         agent.time_incubating = agent.incubation_period
         agent.time_recovering = agent.time_infected - agent.incubation_period
  end
end

function infect_arrivals!(model::AgentBasedModel, pI_0, pI_Vac)
  n_arrivals_infected = 0
  for i in keys(model.agents)
    if model[i].traveller
      if environments_2[ model[i].pos ] == "Arrival"
        if (model[i].vaccinated && rand(rng) < pI_Vac) ||
           (!model[i].vaccinated && rand(rng) < pI_0)

           n_arrivals_infected += 1
            infect_arrival!(model[i], # agent type
                            latent_period,
                            inc_dist, # incubation period distribution
                            rec_dist,  # recovery period distribution
                            b_dist, # distribution of infectivity (gamma)
                            c_lims, # range for test sensitivity breakpoint
                            b1_lims, # range for max test sensitivity parameter b1
                            b2_lims, # range for test sensitivity growth parameter b2
                            b3_lims, # range for test sensitivity decay parameter b3
                            p_asymp # probability of becoming symptomatic after incubation)
                            )
            #println("arrival infected")
        end
      end
    end
  end

 println("infected $n_arrivals_infected arrivals")

end

function infect_agent!(agent::agent_type)

  agent.infected = true
  agent.time_infected = 0.0
  agent.latent = true
  agent.incubating = true
  agent.recovering = false
  agent.recovered = false
  agent.expressing_symptoms = false
  agent.time_infected = 0.0

  if rand(rng) < p_asymp
    agent.asymptomatic = true
  end
  while agent.incubation_period < latent_period
    agent.incubation_period = rand(rng, inc_dist)
  end
  agent.recovery_period = rand(rng, rec_dist)
  agent.beta_max = rand(rng, b_dist)
  agent.beta_min = agent.beta_max / Vmax

  # note the kinc and krec functions are in the 'disease' file
  agent.k_inc = compute_kinc(agent.incubation_period)
  agent.k_r = compute_krec(agent.recovery_period)

  q = cdf(inc_dist, agent.incubation_period)
  # set test sensitivity breakpoint - it's a function of incubation period
  #agent.breakpoint = c_lims[1] + q * (c_lims[2] - c_lims[1])
  agent.breakpoint = agent.incubation_period - ( q * (c_lims[2] - c_lims[1]))

  #set test sensitivity growth rate - also a function of incubation period
  agent.b2 = b2_lims[1] + (1.0 - q) * (b2_lims[2] - b2_lims[1])
  # might as well initialise the other test sensitivity terms too
  agent.b1 = b1_lims[1] + rand(rng) * (b1_lims[2] - b1_lims[1])
  agent.b3 = b3_lims[1] + rand(rng) * (b3_lims[2] - b3_lims[1])
end

function assign_workforce!(model::AgentBasedModel, day_of_week)::Float64
    n_present = 0.0
    for i in keys(model.agents)
          if model[i].worker
                if day_of_week in model[i].workdays
                #  println("working")
                  model[i].present_in_workplace = true
                  n_present += 1.0
                    if environments_2[model[i].pos] == "Community"
                      attempt_move!(model[i], environments["Hotel"], g, environments, model)
                    end
                else
                #  println("not working")
                  model[i].present_in_workplace = false
                    if environments_2[model[i].pos] == "Hotel"
                      attempt_move!(model[i], environments["Community"], g, environments, model)
                    end
                end
          end
    end

    return n_present

end

function compute_test_sensitivity!(agent::agent_type)
  #println("computing test sensitivity")
    agent.test_sensitivity = 0.0
    if (agent.infected || agent.recovered)

          tau = agent.time_infected - agent.breakpoint
          #println("computing tau: $tau" )

          if tau < 0.0
            agent.test_sensitivity = 1.0 / (1.0 + exp(-1.0 * (agent.b1 + agent.b2 * tau )))
            #println(1.0 / (1.0 + exp(-1.0 * (agent.b1 + agent.b2 * tau ))))

          else
            agent.test_sensitivity = 1.0 / (1.0 + exp(-1.0 * (agent.b1 + agent.b2 * tau + (-1.0 * agent.b2*agent.b3*tau) )))
            #println(1.0 / (1.0 + exp(-1.0 * (agent.b1 + agent.b2 * tau + agent.b2*agent.b3*tau ))))
          end

          #HACK: forcing test sensitivity of 0.5
          #agent.test_sensitivity = 0.5

    end

end

function check_test_sensitivity!(model::AgentBasedModel, t_sens, i_check)
  for i in keys(model.agents)
    if model[i].test_sensitivity > 0 && !(i in i_check)
      push!(t_sens, model[i].test_sensitivity)
      push!(i_check, i)
    end
  end
  if length(t_sens) > 0
   println("average test sensitivity: $(mean(t_sens))")
   println("tests performed: $(length(i_check))")
  end
end

function test_agent!(agent::agent_type, delay)

    compute_test_sensitivity!(agent)

    #println("test sensitivity: $(agent.test_sensitivity)")
      # test sensitivity can only be above 0 if agent is infected or recovered
        if rand(rng) < agent.test_sensitivity
          #println("test is positive")
          agent.test_positive = true
        else
          #println("test is negative")
          agent.test_positive = false
        end

    agent.time_to_test_result = delay
    agent.awaiting_test_result = true;
end

function test_workforce!(model::AgentBasedModel, delay)
    for i in keys(model.agents)
        if model[i].worker
            if model[i].present_in_workplace
               test_agent!(model[i], delay)
            end
        end
    end
end

function test_travellers!(model::AgentBasedModel, delay)
  for i in keys(model.agents)
      if model[i].traveller
        #println("time until traveller test: $(minimum(model[i].time_until_test)) ")
          if minimum(model[i].time_until_test) <= dt
             test_agent!(model[i], delay)
             #println("test taken")
             #println("time until traveller $i test: $((model[i].time_until_test)) ")
             model[i].time_until_test[argmin(model[i].time_until_test)] = Inf
             #println("time until traveller $i test: $((model[i].time_until_test)) ")
          end
      end
  end
end

function assess_symptoms!(model::AgentBasedModel, iso_duration, iso_symptom_extension_flag)
    for i in keys(model.agents)
        if model[i].expressing_symptoms &&
          environments_2[model[i].pos] in ["Hotel",
                                           "Hotel Extension",
                                           "Home",
                                           "Home Extension",
                                           "MediHotel Extension",
                                           "Isolation"]

            if (!model[i].detected)
               model[i].detected = true

            elseif (environments_2[model[i].pos] == "Isolation" &&
                    !model[i].isolation_extended && iso_symptom_extension_flag)
               model[i].time_remaining_in_isolation = iso_duration
               model[i].isolation_extended = true
            end
        end
    end
end

function evaluate_workforce_tests!(model::AgentBasedModel)
  for i in keys(model.agents)
      if model[i].worker
          if (model[i].awaiting_test_result &&
             model[i].test_positive &&
             model[i].time_to_test_result <= dt)
             model[i].detected = true
          end
      end
  end
end

function evaluate_traveller_tests!(model::AgentBasedModel)
  for i in keys(model.agents)
      if model[i].traveller
          if (model[i].awaiting_test_result &&
             model[i].test_positive &&
             model[i].time_to_test_result <= dt)
             model[i].detected = true
          end
      end
  end
end

function reinitialise_worker!(agent::agent_type, pVac_W, p_asymptomatic)
  # work schedule stays the same, id and position stay the same,
  # other parameters are reset:
  agent.worker = true
  agent.traveller = false
  agent.vaccinated = (rand(rng) < pVac_W)
  agent.infected = false
  agent.latent = false
  agent.incubating = false
  agent.recovering = false
  agent.recovered = false
  agent.asymptomatic = (rand(rng) < p_asymptomatic)
  agent.expressing_symptoms = false
  agent.time_infected = 0.0
  agent.time_incubating = 0.0
  agent.time_recovering = 0.0
  agent.time_infectious_in_community = 0.0
  agent.test_sensitivity = 0.0
  agent.b1 = 0.0
  agent.b2 = 0.0
  agent.b3 = 0.0
  agent.breakpoint = 0.0
  agent.beta_t = 0.0
  agent.beta_max = 0.0
  agent.beta_min = 0.0
  agent.k_inc = 0.0
  agent.k_r = 0.0
  agent.incubation_period = 0.0
  agent.recovery_period = 0.0
  agent.test_positive = false
  agent.time_to_test_result = 0.0
  agent.discharged = false
  agent.detected = false
  agent.recorded = false
  agent.FoI_in_community = 0.0
  agent.time_discharged = 0.0
  agent.time_until_test = [0.0]
  agent.awaiting_test_result = false;
end

function record_worker(agent::agent_type)
  linelist_W_entry[:exposure_days] = agent.time_infectious_in_community
  linelist_W_entry[:t_latent] = latent_period
  linelist_W_entry[:t_incubation] = agent.incubation_period
  linelist_W_entry[:t_post_incubation] = agent.recovery_period
  linelist_W_entry[:tested_positive] = convert(Int64, agent.test_positive)
  linelist_W_entry[:expressed_symptoms] = convert(Int64, (!agent.asymptomatic & (agent.time_recovering > 0)))
  linelist_W_entry[:time_discharged] = agent.time_discharged
  linelist_W_entry[:symptomatic] = convert(Int64, !agent.asymptomatic)
  linelist_W_entry[:vaccinated] = convert(Int64, agent.vaccinated)
  linelist_W_entry[:FoI_max] = agent.beta_max
  linelist_W_entry[:FoI_community] = agent.FoI_in_community
  agent.recorded = true
  push!(linelist_W, linelist_W_entry)
end

function discharge_workers!(model::AgentBasedModel, t, pVac_W, p_asymptomatic)
  for i in keys(model.agents)
      if model[i].worker
          if model[i].detected
             model[i].discharged = true
             model[i].time_discharged = t
             if model[i].recovered
               println("recovered worker recorded")
             end
             record_worker(model[i])
             reinitialise_worker!(model[i], pVac_W, p_asymptomatic)
          end
      end
  end
end

function compute_FoI!(agent::agent_type)
    if !agent.infected
        agent.beta_t = 0.0
      elseif agent.incubating && !agent.latent
          t_inc = agent.time_infected
          agent.beta_t = agent.beta_min * ( exp( agent.k_inc * t_inc) / Vmax)
        else
          t_r = agent.time_infected - agent.incubation_period
          agent.beta_t = agent.beta_max * exp(agent.k_r * t_r)
    end
    #plateau implemented as a cutoff.
    if agent.beta_t > agent.beta_max
      agent.beta_t = agent.beta_max
    end
end

function step_infection!(agent::agent_type, time_increment)::Float64
    exposure_days = 0.0
    #update infection step

    infectious_period = agent.incubation_period + agent.recovery_period

    if agent.time_infected > infectious_period

           agent.infected = false
           agent.latent = false
           agent.incubating = false
           agent.recovering = false
           agent.recovered = true
           agent.expressing_symptoms = false

           if agent.worker
             println("worker recovered!")
             agent.detected = true # a hack to make sure
             # recovered workers are swapped out with susceptible ones
             # and recorded in the line list.
           end

    elseif (agent.time_infected > latent_period) &&
           (agent.time_infected < agent.incubation_period)

           agent.latent = false
           agent.incubating = true
           agent.recovering = false
           agent.recovered = false
           agent.expressing_symptoms = false

    elseif agent.time_infected > agent.incubation_period

           agent.latent = false
           agent.incubating = false
           agent.recovering = true
           agent.recovered = false

           if !agent.asymptomatic
              agent.expressing_symptoms = true
           end

    end

    # iterate clocks related to infection
    if agent.infected
      agent.time_infected += time_increment
      if ( (environments_2[agent.pos] == "Community" || agent.worker ) &&  !agent.latent) ||
         ( agent.traveller && !agent.compliant && !agent.latent )
        agent.FoI_in_community += (agent.beta_t * time_increment)
        agent.time_infectious_in_community += time_increment
        exposure_days += time_increment
      end
    end

    if agent.incubating
       agent.time_incubating += time_increment
    elseif agent.recovering
      agent.time_recovering += time_increment
    end

    # compute force of infection for next iteration
    compute_FoI!(agent)

    return exposure_days

end

function step_workers!(model::AgentBasedModel, time_increment::Float64)::Tuple{Float64, Float64, Float64}

    exposure_days = 0.0
    exposure_days_uv = 0.0
    exposure_days_vac = 0.0

    for i in keys(model.agents)
        if model[i].worker
            if model[i].infected
              exposure_days_i = step_infection!(model[i], time_increment)
              exposure_days += exposure_days_i
              if model[i].vaccinated
                exposure_days_vac += exposure_days_i
              else
                exposure_days_uv += exposure_days_i
              end
            end
          # iterate clocks related to testing
            if model[i].awaiting_test_result
               model[i].time_to_test_result -= dt
            end
        end
    end

    return exposure_days, exposure_days_uv, exposure_days_vac

end

function isolate_travellers!(model::AgentBasedModel,
                             iso_duration,
                             test_schedule_ext,
                             medi_hotel_flag,
                             home_ext_compliance_rate)::Tuple{Float64, Float64}
  PCR_detections = 0.0
  clinical_detections = 0.0

  for i in keys(model.agents)
      if model[i].traveller
          if (model[i].detected && environments_2[model[i].pos] in ["Home",
                                                                    "Hotel",
                                                                    "MediHotel Extension",
                                                                    "Hotel Extension",
                                                                    "Home Extension"] )
              attempt_move!(model[i], environments["Isolation"],g,environments, model)

              # NOTE: if the person expressed symptoms right after returning the positive
              # test, it's counted as a clinical detection.
              if model[i].expressing_symptoms
                clinical_detections += 1.0
              else
                 PCR_detections += 1.0
              end

              model[i].detected = false
              model[i].time_remaining_in_isolation = iso_duration
              model[i].time_until_test = ones(size(model[i].time_until_test)) .* Inf
              #println(["isolated agent $i, now in" environments_2[model[i].pos]])
              # extend quarantine for contacts
              # NOTE: if a contact is already detected, they will get moved when
              # their turn comes - if they've already been moved to iso, the
              # attempt_move function will return false.
              hh = model[i].hh_id
              hh_members = households[hh].members
              for j in hh_members

                moved = false

                if medi_hotel_flag
                   moved = attempt_move!(model[j], environments["MediHotel Extension"],g,environments, model)
                     if moved
                       model[j].p_compliance = 1.0
                     end
                  elseif environments_2[model[j].pos] == "Home"
                    moved = attempt_move!(model[j], environments["Home Extension"],g,environments, model)
                      if moved
                        model[j].p_compliance = home_ext_compliance_rate
                      end
                  elseif environments_2[model[j].pos] == "Hotel"
                    moved = attempt_move!(model[j], environments["Hotel Extension"],g,environments, model)
                      if moved
                        model[j].p_compliance = 1.0
                      end
                end

                  if moved
                    model[j].time_until_test = copy(test_schedule_ext)
                    model[j].quarantine_extended = true
                  #else
                    #println("tried to move from $(environments_2[model[j].pos]) to extension")
                  end
              end
          end
      end
  end

  return PCR_detections, clinical_detections

end

function discharge_travellers!(model::AgentBasedModel, t, n_new_hh, n_agents_to_add)::Tuple{Float64, Float64}

    n_discharged_t = 0.0
    n_discharged_infected_t = 0.0

    hh_of_discharged_agents = []

    for i in keys(model.agents)
        if model[i].traveller
            if model[i].discharged && model[i].time_discharged == 0.0
               model[i].time_discharged = t

               tag = environments_2[model[i].pos]

               if tag == "Community"
                 println("trying to discharge twice")
               end

               flag = attempt_move!(model[i], environments["Community"], g, environments, model)
               n_discharged_t += 1.0
               if model[i].infected
                 n_discharged_infected_t += 1.0
               end
               #=if tag == "Isolation"
                  if model[i].infected
                    println(["isolated, infected traveller $i moved to community:  $flag"])
                  elseif model[i].recovered
                    println(["isolated, recovered traveller $i moved to community:  $flag"])
                  else
                    println(["isolated, susceptible traveller $i moved to community:  $flag"])
                  end
               end=#

               #note the below may need to be reinstated.
               #model[i].discharged = false
               if !(model[i].hh_id in hh_of_discharged_agents)
                  push!(hh_of_discharged_agents, model[i].hh_id)
               end

             end
         end
     end

     for hh_i in hh_of_discharged_agents
      # iterate through household members and see if they're all in the community
         n_hh = length(households[hh_i].members)
         n_in_community = 0

         for j in households[hh_i].members
           if environments_2[model[j].pos] == "Community"
             n_in_community += 1
           end
         end

         if n_in_community == n_hh
           n_new_hh .+= 1
           n_agents_to_add .+= n_in_community
         end
     end

 return n_discharged_t, n_discharged_infected_t

end

function initialise_arrivals!(model::AgentBasedModel,
                              pVac_T,
                              pI_Vac,
                              pI_0,
                              n_new_hh,
                              n_new_agents,
                              test_schedule)::Tuple{Float64, Float64, Float64}
    n_arrivals_infected = 0.0
    n_arrivals_infected_uv = 0.0
    n_arrivals_infected_vac = 0.0
    # generate the new agents:
    new_ids = []
    for i in 1:n_new_agents
      new_id = nextid(model)
      push!(new_ids, new_id)
      add_agent!(environments["Arrival"], model)
      model[new_id].traveller = true
    end

    #assign households to new agents:

    n_per_hh = n_new_agents / n_new_hh # should be constant in this version

    if length(households) == 0
      hh_id = 1
        else
        hh_id = maximum(keys(households)) + 1
    end
    count = 0
    households[hh_id] = household_type(hh_id, [])
    for i in new_ids

        if count >= n_per_hh
           hh_id += 1
           households[hh_id] = household_type(hh_id, [])
           count = 0
        end

         model[i].hh_id = hh_id
         count += 1
         push!(households[hh_id].members, model[i].id)
         #println("assigned agent  $(model[i].id) to household $hh_id ")
    end

    # vaccinate, infect, and move new arrivals
    for i in new_ids

        if rand(rng) < pVac_T
           model[i].vaccinated = true
        end

        if (model[i].vaccinated && rand(rng) < pI_Vac) ||
           (!model[i].vaccinated && rand(rng) < pI_0)

            infect_arrival!(model[i], # agent type
                            latent_period,
                            inc_dist, # incubation period distribution
                            rec_dist,  # recovery period distribution
                            b_dist, # distribution of infectivity (gamma)
                            c_lims, # range for test sensitivity breakpoint
                            b1_lims, # range for max test sensitivity parameter b1
                            b2_lims, # range for test sensitivity growth parameter b2
                            b3_lims, # range for test sensitivity decay parameter b3
                            p_asymp # probability of becoming symptomatic after incubation)
                            )
            n_arrivals_infected += 1.0
            if model[i].vaccinated
              n_arrivals_infected_vac += 1.0
            else
              n_arrivals_infected_uv += 1.0
            end
            #println("arrival infected")
        end

        #attempt_move!(model[i], environments["Hotel"], g, environments)
        #model[i].time_until_test = copy(test_schedule)

    end

  #=n_total = length(new_ids)
  if n_total > 0
  println("infected $n_arrivals_infected out of $n_total arrivals ")
  end=#

 return n_arrivals_infected, n_arrivals_infected_uv, n_arrivals_infected_vac

end

function move_arrivals_to_home_quarantine!(model::AgentBasedModel, test_schedule)
    for i in keys(model.agents)
        if environments_2[model[i].pos] == "Arrival"
          attempt_move!(model[i], environments["Home"], g, environments, model)
          model[i].time_until_test = copy(test_schedule)
        end
    end
end

function move_arrivals_to_hotel_quarantine!(model::AgentBasedModel, test_schedule)
    for i in keys(model.agents)
        if environments_2[model[i].pos] == "Arrival"
          attempt_move!(model[i], environments["Hotel"], g, environments, model)
          model[i].time_until_test = copy(test_schedule)
        end
    end
end

function record_and_delete!(model::AgentBasedModel)
   # determine who to kill
   # iterate through households and evaluate removal criteria
   agents_to_kill = []
   households_to_kill = []
   for hh_i in keys(households)
       n_hh = length(households[hh_i].members)
       n_kill = 0
       for i in households[hh_i].members
           if (environments_2[model[i].pos] == "Community" &&
               model[i].infected == false)
               n_kill += 1
           end
       end
       if n_kill == n_hh
           push!(households_to_kill, hh_i )
           agents_to_kill = vcat(agents_to_kill, households[hh_i].members)
       end
   end

   for i in agents_to_kill
      if model[i].infected || model[i].recovered
       #if model[i].time_infectious_in_community > 0.0
         record_traveller(model[i])
       end

       kill_agent!(model[i], model)
   end

   for hh_i in households_to_kill
     delete!(households, hh_i)
   end
end

function record_traveller(agent::agent_type)
  linelist_T_entry[:exposure_days] = agent.time_infectious_in_community
  linelist_T_entry[:days_in_quar] = agent.time_in_quar
  linelist_T_entry[:days_in_extended_quar] = agent.time_in_extended_quar
  linelist_T_entry[:days_in_iso] = agent.time_in_isolation
  linelist_T_entry[:t_latent] = latent_period
  linelist_T_entry[:t_incubation] = agent.incubation_period
  linelist_T_entry[:t_post_incubation] = agent.recovery_period
  linelist_T_entry[:time_discharged] = agent.time_discharged
  linelist_T_entry[:index_case] = convert(Int64, agent.index_case)
  linelist_T_entry[:symptomatic] = convert(Int64, !agent.asymptomatic)
  linelist_T_entry[:vaccinated] = convert(Int64, agent.vaccinated)
  linelist_T_entry[:compliance] = agent.p_compliance
  linelist_T_entry[:FoI_max] = agent.beta_max
  linelist_T_entry[:FoI_community] = agent.FoI_in_community
  agent.recorded = true
  push!(linelist_T, linelist_T_entry)
end

function step_travellers!(model::AgentBasedModel,
                          quar_duration,
                          quar_extension,
                          iso_duration,
                          time_increment)::Tuple{Float64, Float64, Float64}
    exposure_days = 0.0
    exposure_days_uv = 0.0
    exposure_days_vac = 0.0

    for i in keys(model.agents)
        if model[i].traveller
            if model[i].infected
                exposure_days_i = step_infection!(model[i], time_increment)
                exposure_days += exposure_days_i
                if model[i].vaccinated
                  exposure_days_vac += exposure_days_i
                else
                  exposure_days_uv += exposure_days_i
                end
            end
            # iterate clocks related to testing
            if model[i].awaiting_test_result
               model[i].time_to_test_result -= time_increment
            end

            for k in 1:length(model[i].time_until_test)
              model[i].time_until_test[k] -= time_increment
            end

            # remember to update 'discharged' status
            #if environments_2[model[i].pos] in ["Hotel", "Home"]
            if (environments_2[model[i].pos] == "Hotel" || environments_2[model[i].pos] == "Home" )
                model[i].time_in_quar += time_increment
                if model[i].time_in_quar > (quar_duration - time_increment)
                   model[i].discharged = true
                end

            elseif environments_2[model[i].pos] in ["Hotel Extension",
                                                    "MediHotel Extension",
                                                    "Home Extension"]
                  model[i].time_in_extended_quar += time_increment
                  if model[i].time_in_extended_quar > (quar_extension - time_increment)
                    model[i].discharged = true
                  end

            elseif environments_2[model[i].pos] == "Isolation"

                    model[i].time_in_isolation += time_increment
                    model[i].time_remaining_in_isolation -= time_increment
                    #println("$i has been in iso for: $(model[i].time_in_isolation)")
                    #println("$i has : $(model[i].time_remaining_in_isolation) remaining")

                    #if model[i].time_remaining_in_isolation < -1.0
                    #=if ((model[i].time_in_isolation) + (model[i].time_remaining_in_isolation)) > 11
                      println("$i total iso time of:
                      $(model[i].time_in_isolation) + $(model[i].time_remaining_in_isolation) = $((model[i].time_in_isolation) + (model[i].time_remaining_in_isolation))")
                    end=#

                    if model[i].time_remaining_in_isolation <= dt
                      model[i].discharged = true
                      #println("$i has : $(model[i].time_remaining_in_isolation) remaining")
                      #println("$i should be discharged.")
                      #println("discharging from isolation: $(model[i].infected)" )
                    end

            end
          end
    end

    return exposure_days, exposure_days_uv, exposure_days_vac

end

function compute_transmission!(model::AgentBasedModel,
                               VEi,
                               VEs,
                               FoI_fac_Hotel_TT_same,
                               FoI_fac_Hotel_TT_dif,
                               FoI_fac_Hotel_TW,
                               FoI_fac_Hotel_WW,
                               n_workers_present,
                               time_increment)::Float64
 n_transmissions = 0.0
 n_travellers_in_hotel =
 convert(Float64, length(agents_in_position(environments["Hotel"], model))) +
 convert(Float64, length(agents_in_position(environments["Hotel Extension"], model)))
 - n_workers_present

    for i in keys(model.agents)

        if model[i].infected &&
          !model[i].latent &&
          !(environments_2[model[i].pos] in ["Arrival", "Community", "Isolation", "MediHotel Extension"])

            for j in keys(model.agents)
                #if model[i].pos == model[j].pos
                if !model[j].infected && !model[j].recovered

                    env_fac = 0.0
                    pop_fac = 1.0
                    vac_fac = (1.0 - (VEs * convert(Float64, model[i].vaccinated) )  ) *
                              (1.0 - (VEi * convert(Float64, model[j].vaccinated) )  )

                    # check if agents are located in interacting environments
                  #  if (environments_2[model[i].pos] in ["Hotel", "Hotel Extension"] ) &&
                  #     (environments_2[model[j].pos] in ["Hotel", "Hotel Extension"] )

                  if (environments_2[model[i].pos] == "Hotel" || environments_2[model[i].pos] == "Hotel Extension" ) &&
                     (environments_2[model[j].pos] == "Hotel" || environments_2[model[j].pos] == "Hotel Extension" )
                        # transmit to household members
                        if (model[i].traveller && model[j].traveller && model[i].hh_id == model[j].hh_id)

                           n_HH = convert(Float64, length(households[model[i].hh_id].members)) - 1.0
                           pop_fac = 1.0 / n_HH
                           env_fac = FoI_fac_Hotel_TT_same

                                  # transmit between all other agents in hotel
                                  # travellers and workers:

                        elseif (model[i].traveller && model[j].traveller && model[i].hh_id != model[j].hh_id)

                            n_HH = length(households[model[i].hh_id].members)
                            n_hotel = n_travellers_in_hotel - n_HH
                            pop_fac = 1.0 / n_hotel
                            env_fac = FoI_fac_Hotel_TT_dif

                        elseif (model[i].worker && model[j].traveller)

                            n_hotel = n_travellers_in_hotel
                            pop_fac = 1.0 / n_hotel
                            env_fac = FoI_fac_Hotel_TW

                        elseif (model[i].traveller &&
                               (model[j].worker && model[j].present_in_workplace ) )

                            n_hotel = n_workers_present
                            pop_fac = 1.0 / n_hotel
                            env_fac = FoI_fac_Hotel_TW

                        elseif (model[i].worker &&
                               (model[j].worker && model[j].present_in_workplace ) )

                            n_hotel = n_workers_present - 1.0
                            pop_fac = 1.0 / n_hotel
                            env_fac = FoI_fac_Hotel_WW
                        end

                    elseif environments_2[model[i].pos] in ["Home", "Home Extension"] &&
                             environments_2[model[j].pos] in ["Home", "Home Extension"]
                        # transmit between household members only
                        if (model[i].traveller &&
                            model[i].hh_id == model[j].hh_id)

                                  n_HH = convert(Float64, length(households[model[i].hh_id].members)) - 1.0
                                  pop_fac = 1.0 / n_HH
                                  env_fac = FoI_fac_Hotel_TT_same
                        end
                    end

                    beta_ij = model[i].beta_t * time_increment * pop_fac * env_fac * vac_fac

                    p_infect = 1.0 - exp((-1.0 * beta_ij))

                  #=  if model[j].worker
                      println("b infect worker: $p_infect")
                    end=#

                    #=if model[j].traveller
                      println("p infect traveller: $p_infect")
                    end=#

                    if rand(rng) < p_infect
                      infect_agent!(model[j])
                      n_transmissions += 1.0
                        #=if model[j].worker
                          println("worker infected")
                        end=#
                        #=if model[j].traveller
                          println("traveller infected")
                        end=#
                    end
                end
            end
        end
    end

    return n_transmissions

end

function evaluate_compliance!(model)
  for i in keys(model.agents)
    if model[i].traveller &&
      environments_2[model[i].pos] in ["Home", "Home Extension"]

       model[i].compliant = (rand(rng) < model[i].p_compliance)
       #println("agent $i compliant? : $(model[i].compliant)")
       #println("compliance probability: $(model[i].p_compliance)")
     else
       model[i].compliant = true
     end
   end
end

function assign_compliance_rate_to_arrivals!(model::AgentBasedModel, compliance_rate)
  for i in keys(model.agents)
    #model[i].p_compliance = 1.0
    if model[i].traveller &&
       environments_2[model[i].pos] == "Arrival"
       model[i].p_compliance = compliance_rate
    end
   end
end

function check_agents!(model::AgentBasedModel)

  for i in keys(model.agents)

    if model[i].time_in_isolation > 0.1 &&
      environments_2[model[i].pos] in ["Home", "Hotel", "MediHotel Extension", "Home Extension", "Hotel Extension"]
      println("***** $i bad move ******")
    end

    if model[i].time_in_isolation > 0.1 &&
      !(environments_2[model[i].pos] in ["Isolation", "Community"])
      println("***** $i bad move ******")
    end

  end
end

            # if the above conditions are satisfied, transmission is possible under some circumstances


text:
# ---
# title: 1287. Element Appearing More Than 25% In Sorted Array
# id: problem1287
# author: Tian Jun
# date: 2020-10-31
# difficulty: Easy
# categories: Array
# link: <https://leetcode.com/problems/element-appearing-more-than-25-in-sorted-array/description/>
# hidden: true
# ---
#
# Given an integer array  **sorted** in non-decreasing order, there is exactly
# one integer in the array that occurs more than 25% of the time.
#
# Return that integer.
#
#
#
# **Example 1:**
#
#
#
#     Input: arr = [1,2,2,6,6,6,6,7,10]
#     Output: 6
#
#
#
#
# **Constraints:**
#
#   * `1 <= arr.length <= 10^4`
#   * `0 <= arr[i] <= 10^5`
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
isdir("sandpit") && rm("sandpit", recursive = true)
mkdir("sandpit")
cd("sandpit")

@testset "australian_wages" begin
    matte_example("australian_wages", "australian_wages", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(AustralianWages, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "bad_long_running" begin
    matte_example("bad_long_running", "bad_long_running", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(BadLongRunningExample, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "better_long_running" begin
    matte_example("better_long_running", "better_long_running", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(BetterLongRunningExample, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "blank" begin
    new_matte_app("blank", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(NewMatteApp, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "broken_sideeffect" begin
    matte_example("broken_sideeffect", "broken_sideeffect", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(BrokenSideEffect, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "dynamic_select" begin
    matte_example("dynamic_select", "dynamic_select", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(DynamicSelectApp, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "hello_world" begin
    matte_example("hello_world", "hello_world", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(HelloWorldApp, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "iris" begin
    matte_example("iris", "iris", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(IrisApp, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "plot_example" begin
    matte_example("plot_example", "plot_example", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(PlotsExample, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

@testset "server_state" begin
    matte_example("server_state", "server_state", activate = false)
    include(joinpath(pwd(), "app.jl"))
    run_app(ServerStateExample, async = true)
    res = HTTP.request("GET", "http://localhost:8000/")
    @test res.status == 200
    stop_app()
    cd("../")
end

cd("../")
println(pwd())
rm("sandpit", recursive = true)


text:
using JuMP, Gurobi, Ipopt, Distributions, StatsFuns

include("resource_nonlinear_20_30.jl")

const gurobi_env = Gurobi.Env()

# CASES
# number of samples, replicates for scenario approximations
const NumSamples = ceil.(Int64,logspace(1,5,50))
const NumReplicates = 20

# FILENAMES
const objFile = "objectiveValue.txt"
const solnFile = "solution.txt"
const riskFile = "riskLevel.txt"
const solnTimeFile = "solutionTime.txt"
const checkingTimeFile = "checkingTime.txt"
const sortingTimeFile = "sortingTime.txt"
const riskTimeFile = "riskTime.txt"
const callbackFile = "numCallbacks.txt"
const numConstraintsFile = "numConstraintsEnforced.txt"

# compute conservative bound on the probability that
# constraints aren't satisfied
function boundRiskLevel(x::Array{Float64},lambda::Array{Float64},rho::Array{Float64},reliabilityLevel::Float64=1E-06)

	const numSamples = size(lambda,2)
	simpleEst::Bool = false

	numViolated::Int64 = checkScenarioConstraints(x,lambda,rho)

	riskLevel::Float64 = Inf

	if(simpleEst)
		riskLevel = numViolated*1.0/numSamples
		return riskLevel
	else
		if(numViolated == 0)
			riskLevel = -log(reliabilityLevel)/numSamples
			return riskLevel
		end

		 # termination criterion for bisection
		gamma_tolerance::Float64 = 0.1/numSamples

		# use tail bounds on binomial distribution to estimate lower and upper bounds
		gamma_low::Float64 = (numViolated - sqrt(-numSamples*log(reliabilityLevel)/2.0))/numSamples
		if(gamma_low < 0.0)
			gamma_low = 0.0
		end
		gamma_up::Float64 = (numViolated + sqrt(-numSamples*log(reliabilityLevel)/2.0))/numSamples
		if(gamma_up > 1.0)
			gamma_up = 1.0
		end

		gamma::Float64 = 0.0
		func_value::Float64 = 0.0

		# use bisection to solve the nonlinear equation
		while (gamma_up - gamma_low > gamma_tolerance)

			gamma = (gamma_low + gamma_up)/2.0
			func_value = -reliabilityLevel
			for i = 1:numViolated
				tmp_func = i*log(gamma) + (numSamples-i)*log(1-gamma) + lfact(numSamples) - lfact(numSamples-i) - lfact(i)
				func_value += exp(tmp_func)
				if(func_value > 0)
					break
				end
			end
			if(func_value > 0)
				gamma_low = (gamma_low + gamma_up)/2.0
			else
				gamma_up = (gamma_low + gamma_up)/2.0
			end

		end

		riskLevel = gamma_up
		return riskLevel
	end

end

# determines if all constraints are satisfied for a given single scenario
# returns one if scenario constraints are all satisfied, zero otherwise
function checkScenarioConstraints(x::Array{Float64},lambda::Array{Float64},rho::Array{Float64})

	numSamples::Int64 = size(lambda,2)

	numViolated::Int64 = 0

	mod = Model(solver=GurobiSolver(gurobi_env,Presolve=0,OutputFlag=0))

	@variable(mod, y[1:numResources,1:numCustomers] >= 0)

	@objective(mod, Min, 0)
	@constraint(mod, con1[i=1:numResources], sum(y[i,j] for j = 1:numCustomers) <= 0)
	@constraint(mod, con2[j=1:numCustomers], sum(nu[i,j]*y[i,j] for i = 1:numResources) >= 0)

	for iter = 1:numSamples
		for i = 1:numResources
			JuMP.setRHS(con1[i],rho[i,iter]*(x[i])^2)
		end

		for j = 1:numCustomers
			JuMP.setRHS(con2[j],lambda[j,iter])
		end

		status = solve(mod,suppress_warnings=true)

		if(status != Symbol("Optimal"))
			numViolated += 1
		end
	end

	# release memory
	mod = 0

	return numViolated
end

# generate random samples of the demands
function generateRandomSamples(numSamples::Int64)

	lambda = rand(MvNormal(lambda_mean[1,:],lambda_covariance),numSamples)
	rho = Array{Float64}(numResources,numSamples)
	for i = 1:numResources
		rho[i,:] = rand(Normal(rho_mean[i],rho_stdev),numSamples)
		for samp = 1:numSamples
			rho[i,samp] = min(rho[i,samp],rho_max)
		end
	end

	return lambda, rho
end

srand(1234)

# generate samples to estimate actual risk level of solution
const numAnalyticalSamples = 100000
const lambda_analytical, rho_analytical = generateRandomSamples(numAnalyticalSamples)

srand()

# determines if all constraints are satisfied for a given single scenario
# returns one if scenario constraints are all satisfied, zero otherwise
function getScenarioConstraintViolations(x::Array{Float64},lambda::Array{Float64},rho::Array{Float64},pickFirstSetOfConstraints::Bool,maxNumConstraintsPerIteration::Int64)

	const numSamples = size(lambda,2)
	numViolated::Int64 = 0
	constraintViolations = Float64[]
	constraintViolationIndices = Int64[]
	constraintViolationTolerance::Float64 = 1E-06

	mod = Model(solver=GurobiSolver(gurobi_env,Presolve=0,OutputFlag=0))

	@variable(mod, y[1:numResources,1:numCustomers] >= 0)
	@variable(mod, slack)

	@objective(mod, Min, slack)
	@constraint(mod, con1[i=1:numResources], sum(y[i,j] for j = 1:numCustomers) <= 0)
	@constraint(mod, con2[j=1:numCustomers], sum(nu[i,j]*y[i,j] for i = 1:numResources) + slack >= 0)

	for iter = 1:numSamples
		for i = 1:numResources
			JuMP.setRHS(con1[i],rho[i,iter]*(x[i])^2)
		end

		for j = 1:numCustomers
			JuMP.setRHS(con2[j],lambda[j,iter])
		end

		status::Symbol = solve(mod)
		slack_opt::Float64 = getvalue(slack)

		if(slack_opt >= constraintViolationTolerance)
			numViolated += 1
			push!(constraintViolations,slack_opt)
			push!(constraintViolationIndices,iter)
			if(pickFirstSetOfConstraints && numViolated == numConstraintsPerIteration)
				break
			end
		end
	end

	# release memory
	mod = 0

	return numViolated, constraintViolations, constraintViolationIndices
end

# write solution to file
function initializeFiles(details_file::String)

	writeMode::String = "w"

	open(details_file, writeMode) do f
		write(f,"Model: $modelName \n")
		write(f,"numResources: $numResources \n")
		write(f,"numCustomers: $numCustomers \n")
		write(f,"NumSamples: $NumSamples \n")
		write(f,"NumReplicates: $NumReplicates \n")
		write(f,"Method: Scenario approximations \n")
	end

end

# write solution to file
function writeSolutionToFile(dirName::String, status::Symbol, objvar_opt::Float64, x_opt::Array{Float64}, riskLevel::Float64, solutionTime::Float64, checkingTime::Float64, sortingTime::Float64, riskTime::Float64, numCallbacks::Int64, numConstraintsAdded::Int64)

	if(status == Symbol("Optimal"))
		writeMode::String = "a"

		obj_file::String = dirName * objFile
		open(obj_file, writeMode) do f
			write(f,"$objvar_opt \n")
		end

		solution_file::String = dirName * solnFile
		open(solution_file, writeMode) do f
			for i = 1:numResources
				write(f,"$(x_opt[i]) ")
			end
			write(f,"\n")
		end

		risk_file::String = dirName * riskFile
		open(risk_file, writeMode) do f
			write(f,"$riskLevel \n")
		end

		solntime_file::String = dirName * solnTimeFile
		open(solntime_file, writeMode) do f
			write(f,"$solutionTime \n")
		end

		checktime_file::String = dirName * checkingTimeFile
		open(checktime_file, writeMode) do f
			write(f,"$checkingTime \n")
		end

		sorttime_file::String = dirName * sortingTimeFile
		open(sorttime_file, writeMode) do f
			write(f,"$sortingTime \n")
		end

		risktime_file::String = dirName * riskTimeFile
		open(risktime_file, writeMode) do f
			write(f,"$riskTime \n")
		end

		callback_file::String = dirName * callbackFile
		open(callback_file, writeMode) do f
			write(f,"$numCallbacks \n")
		end

		constraints_file::String = dirName * numConstraintsFile
		open(constraints_file, writeMode) do f
			write(f,"$numConstraintsAdded \n")
		end
	end

end

x_initial_guess = Float64[0.0 0.0 0.0 0.0 43.52912917750612 0.0 0.0 0.0 6.345178399087325e-16 0.0 0.0 25.078984684205707 0.0 0.0 0.0 0.0 15.524911271438539 0.0 0.0 0.0]
x_initial_guess = x_initial_guess'

# solve the scenario approximation model
function solveScenarioApproximationModel(numScenarios::Int64,dirName::String)

	tic()

	global x_initial_guess

	# sample the random variables
	lambda, rho = generateRandomSamples(numScenarios)

	maxNumConstraintsPerIteration::Int64 = 5
	numConstraintsAdded::Int64 = 0

	pickFirstSetOfConstraints::Bool = false

	sortingTime::Float64 = 0.0
	checkingTime::Float64 = 0.0
	numCallbacks::Int64 = 0

	objvar_opt::Float64 = Inf
	x_opt = zeros(Float64,numResources)
	status::Symbol = Symbol("Error")

	numViolations::Int64 = numScenarios

	constraintIndices = Int64[]

	while(numViolations > 0)

		numCallbacks += 1
		numViolations = 0

		mod = Model(solver=IpoptSolver(tol=1e-6,print_level=0))

		@variable(mod, objvar)
		@variable(mod, x[i=1:numResources] >= 0,start=x_initial_guess[i])
		@variable(mod, y[1:numResources,1:numCustomers,1:numConstraintsAdded] >= 0)

		@objective(mod, Min, objvar)
		@constraint(mod, sum(costVector[i]*x[i] for i = 1:numResources) <= objvar)
		@constraint(mod, [i=1:numResources, scen=1:numConstraintsAdded], sum(y[i,j,scen] for j = 1:numCustomers) <= rho[i,constraintIndices[scen]]*(x[i])^2)
		@constraint(mod, [j=1:numCustomers, scen=1:numConstraintsAdded], sum(nu[i,j]*y[i,j,scen] for i = 1:numResources) >= lambda[j,constraintIndices[scen]])

		status = solve(mod)
		objvar_opt = getvalue(objvar)
		x_opt = getvalue(x)
		x_initial_guess = deepcopy(x_opt)

		# release memory
		mod = 0

		numViolatedConstraints::Int64 = 0
		constraintViolations = Float64[]
		constraintViolationIndices = Int64[]

		tic()

		numViolatedConstraints, constraintViolations, constraintViolationIndices = getScenarioConstraintViolations(x_opt,lambda,rho,pickFirstSetOfConstraints,maxNumConstraintsPerIteration)

		checkingTime += toq()

		numConstraintsEnforced::Int64 = min(size(constraintViolations,1),maxNumConstraintsPerIteration)

		tic()
		relevantIndices = 1:1:numConstraintsEnforced
		if(!pickFirstSetOfConstraints)
			relevantIndices = sortperm(constraintViolations, rev=true)
		end
		sortingTime += toq()

		for iter = 1:numConstraintsEnforced
			push!(constraintIndices,constraintViolationIndices[relevantIndices[iter]])
		end

		numConstraintsAdded += numConstraintsEnforced

		numViolations += numViolatedConstraints

	end

	tic()

	riskLevel::Float64 = boundRiskLevel(x_opt,lambda_analytical,rho_analytical)

	riskTime = toq()

	solutionTime::Float64 = toq()

	@printf "  Objective: %2.5f,  Risklevel: %.6f,  Time: %4.2f,  NumCallbacks: %d,  NumConstraints: %d \n" objvar_opt riskLevel solutionTime numCallbacks numConstraintsAdded

	writeSolutionToFile(dirName, status, objvar_opt, x_opt, riskLevel, solutionTime, checkingTime, sortingTime, riskTime, numCallbacks, numConstraintsAdded)

	return status, objvar_opt, x_opt, riskLevel, solutionTime, checkingTime, sortingTime, riskTime, numCallbacks, numConstraintsAdded
end

max_stars_repo_name: rohitkannan/SA-for-CCP

max_issues_repo_name: rohitkannan/SA-for-CCP

max_forks_repo_name: rohitkannan/SA-for-CCP


text:
module TraceTranslators

include("../src/Jaynes.jl")
using .Jaynes

# Available on master Gen.
using Gen

polar = @jaynes function p1()
    r ~ InvGamma(1, 1)
    θ ~ Uniform(-π / 2, π / 2)
end

cartesian = @jaynes function p2()
    x ~ Normal(0, 1)
    y ~ Normal(0, 1)
end

@transform f (t1) to (t2) begin
    r = @read(t1[:r], :continuous)
    theta = @read(t1[:theta], :continuous)
    @write(t2[:x], r * cos(theta), :continuous)
    @write(t2[:y], r * sin(theta), :continuous)
end

@transform finv (t2) to (t1) begin
    x = @read(t2[:x], :continuous)
    y = @read(t2[:y], :continuous)
    r = sqrt(x^2 + y^2)
    @write(t1[:r], sqrt(x^2 + y^2), :continuous)
    @write(t1[:theta], atan(y, x), :continuous)
end

pair_bijections!(f, finv)
translator = DeterministicTraceTranslator(cartesian, (), choicemap(), f)
tr = simulate(cartesian, ())
t2, log_weight = translator(tr)

end # module


text:
### Julia OpenStreetMap Package ###
### MIT License                 ###
### Copyright 2014              ###

### Get bounds of mapped region ###
function getBounds(street_map::LightXML.XMLDocument)

    xroot = LightXML.root(street_map)
    bounds = LightXML.get_elements_by_tagname(xroot, "bounds")

    min_lat = float(LightXML.attribute(bounds[1], "minlat"))
    max_lat = float(LightXML.attribute(bounds[1], "maxlat"))
    min_lon = float(LightXML.attribute(bounds[1], "minlon"))
    max_lon = float(LightXML.attribute(bounds[1], "maxlon"))

    return Bounds(min_lat, max_lat, min_lon, max_lon)
end