function [growthOnMinimalMedium,essentialExchanges,modelPruned] = predictGrowthRequirements(model)
% Predicts growth requirements for a genome-scale reconstruction.
% The list of predicted essential exchanges as well as a model
% constrained with these exchanges are returned.
%
% INPUT
% model                  COBRA model structure
% biomassReaction        String listing the biomass reaction
%
% OUTPUT
% growthOnMinimalMedium  Bool if growth on defined medium yes or no
% essentialExchanges     Exchanges that need to be open to enable growth
% constrainedModel       Model constrained with predicted essential
%                        exchanges
%
% Almut Heinken, November 2020

tol=1e-6;

% set "unlimited" constraints
model = changeRxnBounds(model, model.rxns(strncmp('EX_', model.rxns, 3)), -1000, 'l');
model = changeRxnBounds(model, model.rxns(strncmp('EX_', model.rxns, 3)), 1000, 'u');

% remove positive values on lower bounds
model.lb(find(model.lb>0))=0;
% 
% % remove compounds that should not be essential for any organism
% unlikelyRequirements={'EX_alaasp(e)';'EX_alagln(e)';'EX_alaglu(e)';'EX_alagly(e)';'EX_alahis(e)';'EX_alaleu(e)';'EX_alathr(e)';'EX_glygln(e)';'EX_glyglu(e)';'EX_glyleu(e)';'EX_glymet(e)';'EX_glyphe(e)';'EX_glypro(e)';'EX_glytyr(e)';'EX_metala(e)';'EX_glyasn(e)';'EX_glyasp(e)';'EX_dpcoa(e)';'EX_coa(e)';'EX_cmp(e)';'EX_dtmp(e)';'EX_ump(e)';'EX_gmp(e)';'EX_dgtp(e)';'EX_nadp(e)';'EX_nad(e)';'EX_thmmp(e)';'EX_malt(e)';'EX_stys(e)';'EX_raffin(e)';'EX_melib(e)';'EX_lcts(e)';'EX_gtp(e)';'EX_datp(e)';'EX_amp(e)';'EX_pppi(e)';'EX_r5p(e)';'EX_g1p(e)';'EX_glu_D(e)';'EX_agm(e)';'EX_glycys(e)';'EX_1hibup_S(e)';'EX_1hibupglu_S(e)';'EX_1hmdgluc(e)';'EX_1ohmdz(e)';'EX_2hatvacid(e)';'EX_2hatvacidgluc(e)';'EX_2hatvlac(e)';'EX_2hatvlacgluc(e)';'EX_2hibup_S(e)';'EX_2hibupglu_S(e)';'EX_2oh_cbz_glc(e)';'EX_2oh_cbz(e)';'EX_2oh_mtz_glc(e)';'EX_2oh_mtz(e)';'EX_34dhphe(e)';'EX_3hibup_S(e)';'EX_3hibupglu_S(e)';'EX_3meacmp(e)';'EX_3oh_cbz_glc(e)';'EX_3oh_cbz(e)';'EX_3oh_dlor_glc(e)';'EX_3oh_dlor(e)';'EX_3oh_mdea_glc(e)';'EX_3oh_mdea(e)';'EX_3oh_mxn_glc(e)';'EX_3oh_mxn(e)';'EX_4dh_tpno_1glc(e)';'EX_4dh_tpno(e)';'EX_4hmdgluc(e)';'EX_4hphac(e)';'EX_4oh_dcf_glc(e)';'EX_4oh_dcf(e)';'EX_4oh_kp_glc(e)';'EX_4oh_kp(e)';'EX_4oh_levole_glc(e)';'EX_4oh_levole(e)';'EX_4oh_meth_glc(e)';'EX_4oh_meth(e)';'EX_4oh_propl_glc(e)';'EX_4oh_propl(e)';'EX_4oh_trz_glc(e)';'EX_4oh_trz(e)';'EX_4oh_vcz_glc(e)';'EX_4oh_vcz(e)';'EX_4ohmdz(e)';'EX_5asa(e)';'EX_5fura(e)';'EX_5oh_sulfp_glc(e)';'EX_5oh_sulfp(e)';'EX_5ohfvs(e)';'EX_5ohfvsglu(e)';'EX_6bhglz(e)';'EX_6bhglzglc(e)';'EX_6ohfvs(e)';'EX_6ohfvsglu(e)';'EX_7a_czp(e)';'EX_7bhglz(e)';'EX_7bhglzglc(e)';'EX_7oh_efv_glc(e)';'EX_7oh_efv(e)';'EX_814dioh_efv_glc(e)';'EX_814dioh_efv(e)';'EX_8oh_efv_glc(e)';'EX_8oh_efv(e)';'EX_abz_ala_b(e)';'EX_ac_amn_b_gly_glc(e)';'EX_ac_amn_b_gly(e)';'EX_ac5asa(e)';'EX_acisnzd(e)';'EX_acmp_glc(e)';'EX_acmp(e)';'EX_acmpglu(e)';'EX_alpz_4oh_glc(e)';'EX_alpz_4oh(e)';'EX_alpz_aoh_glc(e)';'EX_alpz_aoh(e)';'EX_am14_glc(e)';'EX_am14(e)';'EX_am1ccs(e)';'EX_am1cglc(e)';'EX_am5_glc(e)';'EX_am5(e)';'EX_am6_glc(e)';'EX_am6(e)';'EX_amio_c_glc(e)';'EX_amio_c(e)';'EX_amio_glc(e)';'EX_amio(e)';'EX_amn_b_gly_glc(e)';'EX_amn_b_gly(e)';'EX_amntd_m6_glc(e)';'EX_amntd_m6(e)';'EX_anzp(e)';'EX_atvacid(e)';'EX_atvacylgluc(e)';'EX_atvethgluc(e)';'EX_atvlac(e)';'EX_atvlacgluc(e)';'EX_bhpm_glc(e)';'EX_bhpm(e)';'EX_bilr_355(e)';'EX_bilr_M10(e)';'EX_bilr_M12(e)';'EX_bilr_M14(e)';'EX_bilr_M15(e)';'EX_bilr_M16(e)';'EX_bilr_M7(e)';'EX_brv(e)';'EX_bsn_glc(e)';'EX_bsn(e)';'EX_bvu(e)';'EX_bz_glc(e)';'EX_bz(e)';'EX_bzd(e)';'EX_C02528(e)';'EX_caribup_s(e)';'EX_caribupglu_S(e)';'EX_cbz_glc(e)';'EX_cbz(e)';'EX_cd6168_glc(e)';'EX_cd6168(e)';'EX_chlphncl_glc(e)';'EX_chlphncl(e)';'EX_cholate(e)';'EX_clcxb_c_glc(e)';'EX_clcxb_c(e)';'EX_clcxb_glc(e)';'EX_clcxb(e)';'EX_clobi_c(e)';'EX_clobi_glc(e)';'EX_crvsm1(e)';'EX_crvsm23(e)';'EX_cvm1gluc(e)';'EX_cvm23gluc(e)';'EX_czp(e)';'EX_daa_glc(e)';'EX_daa(e)';'EX_dcf_glc(e)';'EX_dcf(e)';'EX_dchac(e)';'EX_ddea_glc(e)';'EX_ddea(e)';'EX_des_astzl_glc(e)';'EX_des_astzl(e)';'EX_dfdcytd(e)';'EX_dfduri(e)';'EX_dgchol(e)';'EX_dh5fura(e)';'EX_digitoxin(e)';'EX_digoxin_glc(e)';'EX_digoxin(e)';'EX_dihydro_digitoxin(e)';'EX_dihydro_digoxin(e)';'EX_dlb_glc(e)';'EX_dlb(e)';'EX_dnpz_5des(e)';'EX_dnpz_6des(e)';'EX_dnpz_m11(e)';'EX_dnpz_m12(e)';'EX_dnpz_m13(e)';'EX_dnpz_m14(e)';'EX_dnpz_m9(e)';'EX_doh_etr_glc(e)';'EX_doh_etr(e)';'EX_doh_vcz_glc(e)';'EX_doh_vcz(e)';'EX_dopa(e)';'EX_dxo_glc(e)';'EX_dxo(e)';'EX_efv_glc(e)';'EX_efv(e)';'EX_eltr_glc(e)';'EX_eltr_m3(e)';'EX_eltr_m4(e)';'EX_eltr(e)';'EX_estradiol(e)';'EX_estradiolglc(e)';'EX_estriol(e)';'EX_estriolglc(e)';'EX_estrone(e)';'EX_estroneglc(e)';'EX_eztmb_glc(e)';'EX_eztmb(e)';'EX_fcsn(e)';'EX_fvs(e)';'EX_fvsgluc(e)';'EX_fvstet(e)';'EX_fvstetglu(e)';'EX_gchola(e)';'EX_glc3meacp(e)';'EX_gltmn_glc(e)';'EX_gltmn(e)';'EX_gmfl_glc(e)';'EX_gmfl_mI_glc(e)';'EX_gmfl_mI(e)';'EX_gmfl_mII_glc(e)';'EX_gmfl_mII(e)';'EX_gmfl_mIII_glc(e)';'EX_gmfl_mIII(e)';'EX_gmfl(e)';'EX_gtacmp(e)';'EX_HC02191(e)';'EX_hst_3_glc(e)';'EX_hst_3_s(e)';'EX_hst_37_diglc(e)';'EX_hst_3glc_7s(e)';'EX_hst_7_glc(e)';'EX_hst_7_s(e)';'EX_hst_7glc_3s(e)';'EX_hst(e)';'EX_ibup_S(e)';'EX_ibupgluc(e)';'EX_imn_glc(e)';'EX_imn(e)';'EX_inv_m1(e)';'EX_inv(e)';'EX_isnzd(e)';'EX_isosorbide_5mn_glc(e)';'EX_isosorbide_5mn(e)';'EX_kprofen_glc(e)';'EX_kprofen(e)';'EX_lactl(e)';'EX_lst4exp(e)';'EX_lstn(e)';'EX_lstn1gluc(e)';'EX_lstnm4(e)';'EX_lstnm7(e)';'EX_mdz_glc(e)';'EX_mdz(e)';'EX_mdzglc(e)';'EX_miso_glc(e)';'EX_miso(e)';'EX_mrphn_3glc(e)';'EX_mrphn_6glc(e)';'EX_mrphn(e)';'EX_mtym(e)';'EX_mtz_glc(e)';'EX_mtz(e)';'EX_N_oh_phtn_glc(e)';'EX_N_oh_phtn(e)';'EX_nchlphncl(e)';'EX_neopront(e)';'EX_nsldp_m5_glc(e)';'EX_nsldp_m5(e)';'EX_nverp_glc(e)';'EX_nverp(e)';'EX_nzp(e)';'EX_odsm_egltmn_glc(e)';'EX_odsm_egltmn(e)';'EX_odsm_gltmn_glc(e)';'EX_odsm_gltmn(e)';'EX_oh_etr_glc(e)';'EX_oh_etr(e)';'EX_oh_pbl_glc(e)';'EX_oh_pbl(e)';'EX_olsa(e)';'EX_pcresol(e)';'EX_phppa_glc(e)';'EX_phppa(e)';'EX_phtn_glc(e)';'EX_prob_glc(e)';'EX_prob(e)';'EX_pront_glc(e)';'EX_pront(e)';'EX_propl_glc(e)';'EX_propl(e)';'EX_prx_mI_glc(e)';'EX_prx_mI(e)';'EX_prx_mII_glc(e)';'EX_prx_mII(e)';'EX_ptvst(e)';'EX_ptvstgluc(e)';'EX_pvs(e)';'EX_pvsgluc(e)';'EX_R_6oh_warf_glc(e)';'EX_R_6oh_warf(e)';'EX_R_7oh_warf_glc(e)';'EX_R_7oh_warf(e)';'EX_R_8oh_warf_glc(e)';'EX_R_8oh_warf(e)';'EX_r406_glc(e)';'EX_r406(e)';'EX_r529_glc(e)';'EX_r529(e)';'EX_r788(e)';'EX_regfnb_glc(e)';'EX_regfnb(e)';'EX_rep_glc(e)';'EX_rep(e)';'EX_rpn_104557_cb_glc(e)';'EX_rpn_104557(e)';'EX_rpn_96990_glc(e)';'EX_rpn_96990(e)';'EX_rpn_oh_glc(e)';'EX_rpn_oh(e)';'EX_rsv(e)';'EX_rsvgluc(e)';'EX_S_4oh_warf_glc(e)';'EX_S_4oh_warf(e)';'EX_S_6oh_warf_glc(e)';'EX_S_6oh_warf(e)';'EX_sanilamide(e)';'EX_sb_611855(e)';'EX_sb_y(e)';'EX_sch_488128(e)';'EX_sch_57871_glc(e)';'EX_sch_57871(e)';'EX_sfnd_1689_glc(e)';'EX_sfnd_1689(e)';'EX_sftz_glc(e)';'EX_sftz(e)';'EX_simvgluc(e)';'EX_smap_glc(e)';'EX_smap(e)';'EX_smvacid(e)';'EX_sn38(e)';'EX_sn38g(e)';'EX_spz_glc(e)';'EX_spz_sfn_glc(e)';'EX_spz_sfn(e)';'EX_spz(e)';'EX_srv(e)';'EX_ssz(e)';'EX_stg_m3(e)';'EX_stg_m4(e)';'EX_stg(e)';'EX_sulfp(e)';'EX_tab(e)';'EX_tat(e)';'EX_taur(e)';'EX_tchola(e)';'EX_tdchola(e)';'EX_tgz_glc(e)';'EX_tgz(e)';'EX_thsacmp(e)';'EX_tlf_a_1a(e)';'EX_tlf_a_1b(e)';'EX_tlf_a_1x(e)';'EX_tlf_a_2(e)';'EX_tlf_a_2a(e)';'EX_tlf_a_3(e)';'EX_tlf_a_4(e)';'EX_tlf_a_m1(e)';'EX_tlf_a_m2(e)';'EX_tlf_a_m3(e)';'EX_tlf_a_m4(e)';'EX_tlf_a_m4a(e)';'EX_tlf_a_m5(e)';'EX_tlf_a_m5a(e)';'EX_tlf_a_m5b(e)';'EX_tlf_a_m6(e)';'EX_tlf_a_m9(e)';'EX_tlf_a(e)';'EX_tlms_glc(e)';'EX_tlms(e)';'EX_tmacmp(e)';'EX_tolcp_ac_glc(e)';'EX_tolcp_ac(e)';'EX_tolcp_am_glc(e)';'EX_tolcp_am(e)';'EX_tolcp_glc(e)';'EX_tolcp(e)';'EX_tpno_1glc_4g(e)';'EX_tpno_4g(e)';'EX_tpno_4glc(e)';'EX_tpnoh(e)';'EX_tsacmgluc(e)';'EX_tym(e)'};
% model=changeRxnBounds(model,unlikelyRequirements,0,'l');

% set objective
biomassReaction=model.rxns{find(strncmp(model.rxns,'bio',3)),1};
model = changeObjective(model, biomassReaction);

[modelMin, modelPruned, essentialExchanges] = generateCompactExchModel(model,tol,biomassReaction,1,1);
modelMin = changeObjective(modelMin, biomassReaction);
FBA=optimizeCbModel(modelMin,'max');
growthOnMinimalMedium=FBA.f;

end