| 1815 | | |
| | 1815 | pair<vec,simplex*> choose_simplex() |
| | 1816 | { |
| | 1817 | double rnumber = randu(); |
| | 1818 | |
| | 1819 | // cout << "RND:" << rnumber << endl; |
| | 1820 | |
| | 1821 | // This could be more efficient (log n), but map::upper_bound() doesn't let me dereference returned iterator |
| | 1822 | double prob_sum = 0; |
| | 1823 | toprow* sampled_toprow; |
| | 1824 | for(polyhedron* top_ref = statistic.rows[statistic.size()-1];top_ref!=statistic.row_ends[statistic.size()-1];top_ref=top_ref->next_poly) |
| | 1825 | { |
| | 1826 | // cout << "CDF:"<< (*top_ref).first << endl; |
| | 1827 | |
| | 1828 | toprow* current_toprow = ((toprow*)top_ref); |
| | 1829 | |
| | 1830 | prob_sum += current_toprow->probability; |
| | 1831 | |
| | 1832 | if(prob_sum >= rnumber*normalization_factor) |
| | 1833 | { |
| | 1834 | sampled_toprow = (toprow*)top_ref; |
| | 1835 | break; |
| | 1836 | } |
| | 1837 | } |
| | 1838 | |
| | 1839 | //// cout << "Toprow/Count: " << toprow_count << "/" << ordered_toprows.size() << endl; |
| | 1840 | // cout << &sampled_toprow << ";"; |
| | 1841 | |
| | 1842 | rnumber = randu(); |
| | 1843 | |
| | 1844 | set<simplex*>::iterator s_ref; |
| | 1845 | prob_sum = 0; |
| | 1846 | for(s_ref = sampled_toprow->triangulation.begin();s_ref!=sampled_toprow->triangulation.end();s_ref++) |
| | 1847 | { |
| | 1848 | prob_sum += (*s_ref)->probability; |
| | 1849 | |
| | 1850 | if(prob_sum/sampled_toprow->probability >= rnumber) |
| | 1851 | break; |
| | 1852 | } |
| | 1853 | |
| | 1854 | return pair<vec,simplex*>(sampled_toprow->condition_sum,*s_ref); |
| | 1855 | } |
| | 1856 | |
| | 1857 | pair<double,double> choose_sigma(simplex* sampled_simplex) |
| | 1858 | { |
| | 1859 | double rnumber = randu(); |
| | 1860 | double sigma; |
| | 1861 | |
| | 1862 | double sum_g = 0; |
| | 1863 | for(int i = 0;i<sampled_simplex->positive_gamma_parameters.size();i++) |
| | 1864 | { |
| | 1865 | for(multimap<double,double>::iterator g_ref = sampled_simplex->positive_gamma_parameters[i].begin();g_ref != sampled_simplex->positive_gamma_parameters[i].end();g_ref++) |
| | 1866 | { |
| | 1867 | sum_g += (*g_ref).first/sampled_simplex->positive_gamma_sum; |
| | 1868 | |
| | 1869 | |
| | 1870 | if(sum_g>rnumber) |
| | 1871 | { |
| | 1872 | //itpp::Gamma_RNG* gamma = new itpp::Gamma_RNG(conditions.size()-number_of_parameters,1/(*g_ref).second); |
| | 1873 | //sigma = 1/(*gamma)(); |
| | 1874 | |
| | 1875 | GamRNG.setup(conditions.size()-number_of_parameters,(*g_ref).second); |
| | 1876 | |
| | 1877 | sigma = 1/GamRNG(); |
| | 1878 | |
| | 1879 | // cout << "Sigma mean: " << (*g_ref).second/(conditions.size()-number_of_parameters-1) << endl; |
| | 1880 | break; |
| | 1881 | } |
| | 1882 | } |
| | 1883 | |
| | 1884 | if(sigma!=0) |
| | 1885 | { |
| | 1886 | break; |
| | 1887 | } |
| | 1888 | } |
| | 1889 | |
| | 1890 | rnumber = randu(); |
| | 1891 | |
| | 1892 | double pg_sum = 0; |
| | 1893 | for(vector<multimap<double,double>>::iterator v_ref = sampled_simplex->positive_gamma_parameters.begin();v_ref!=sampled_simplex->positive_gamma_parameters.end();v_ref++) |
| | 1894 | { |
| | 1895 | for(multimap<double,double>::iterator pg_ref = (*v_ref).begin();pg_ref!=(*v_ref).end();pg_ref++) |
| | 1896 | { |
| | 1897 | pg_sum += exp((sampled_simplex->min_beta-(*pg_ref).second)/sigma)*pow((*pg_ref).second/sigma,(int)conditions.size()-number_of_parameters-1)*(*pg_ref).second/fact(conditions.size()-number_of_parameters-1)*(*pg_ref).first; |
| | 1898 | } |
| | 1899 | } |
| | 1900 | |
| | 1901 | double ng_sum = 0; |
| | 1902 | for(vector<multimap<double,double>>::iterator v_ref = sampled_simplex->negative_gamma_parameters.begin();v_ref!=sampled_simplex->negative_gamma_parameters.end();v_ref++) |
| | 1903 | { |
| | 1904 | for(multimap<double,double>::iterator ng_ref = (*v_ref).begin();ng_ref!=(*v_ref).end();ng_ref++) |
| | 1905 | { |
| | 1906 | ng_sum += exp((sampled_simplex->min_beta-(*ng_ref).second)/sigma)*pow((*ng_ref).second/sigma,(int)conditions.size()-number_of_parameters-1)*(*ng_ref).second/fact(conditions.size()-number_of_parameters-1)*(*ng_ref).first; |
| | 1907 | } |
| | 1908 | } |
| | 1909 | |
| | 1910 | return pair<double,double>((pg_sum-ng_sum)/pg_sum,sigma); |
| | 1911 | } |
| | 2223 | } |
| | 2224 | |
| | 2225 | pair<vec,mat> importance_sample(int n) |
| | 2226 | { |
| | 2227 | vec probabilities; |
| | 2228 | mat samples; |
| | 2229 | |
| | 2230 | for(int i = 0;i<n;i++) |
| | 2231 | { |
| | 2232 | pair<vec,simplex*> condition_and_simplex = choose_simplex(); |
| | 2233 | |
| | 2234 | pair<double,double> probability_and_sigma = choose_sigma(condition_and_simplex.second); |
| | 2235 | |
| | 2236 | int dimension = condition_and_simplex.second->vertices.size()-1; |
| | 2237 | |
| | 2238 | mat jacobian(dimension,dimension); |
| | 2239 | vec gradient = condition_and_simplex.first.right(dimension); |
| | 2240 | |
| | 2241 | vertex* base_vert = *condition_and_simplex.second->vertices.begin(); |
| | 2242 | |
| | 2243 | //// cout << "Base vertex coords(should be close to est. param.): " << base_vert->get_coordinates() << endl; |
| | 2244 | |
| | 2245 | int row_count = 0; |
| | 2246 | |
| | 2247 | for(set<vertex*>::iterator vert_ref = ++condition_and_simplex.second->vertices.begin();vert_ref!=condition_and_simplex.second->vertices.end();vert_ref++) |
| | 2248 | { |
| | 2249 | vec current_coords = (*vert_ref)->get_coordinates(); |
| | 2250 | |
| | 2251 | //// cout << "Coords of vertex[" << row_count << "]: " << current_coords << endl; |
| | 2252 | |
| | 2253 | vec relative_coords = current_coords-base_vert->get_coordinates(); |
| | 2254 | |
| | 2255 | jacobian.set_row(row_count,relative_coords); |
| | 2256 | |
| | 2257 | row_count++; |
| | 2258 | } |
| | 2259 | |
| | 2260 | //// cout << "Jacobian: " << jacobian << endl; |
| | 2261 | |
| | 2262 | /// \todo Is this correct? Are the random coordinates really jointly uniform? I don't know. |
| | 2263 | vec sample_coords; |
| | 2264 | double sampling_diff = 1; |
| | 2265 | for(int j = 0;j<number_of_parameters;j++) |
| | 2266 | { |
| | 2267 | double rnumber = randu()*sampling_diff; |
| | 2268 | |
| | 2269 | sample_coords.ins(0,rnumber); |
| | 2270 | |
| | 2271 | sampling_diff -= rnumber; |
| | 2272 | } |
| | 2273 | |
| | 2274 | sample_coords = jacobian.T()*sample_coords+(*base_vert).get_coordinates(); |
| | 2275 | |
| | 2276 | vec extended_coords = sample_coords; |
| | 2277 | extended_coords.ins(0,-1.0); |
| | 2278 | |
| | 2279 | double sample_prob = 1/condition_and_simplex.second->probability/pow(probability_and_sigma.second,(int)conditions.size()-number_of_parameters)*exp(1/probability_and_sigma.second*(extended_coords*condition_and_simplex.first)); |
| | 2280 | sample_prob *= probability_and_sigma.first; |
| | 2281 | |
| | 2282 | sample_coords.ins(0,probability_and_sigma.second); |
| | 2283 | |
| | 2284 | samples.ins_col(0,sample_coords); |
| | 2285 | probabilities.ins(0,sample_prob); |
| | 2286 | } |
| | 2287 | |
| | 2288 | return pair<vec,mat>(probabilities,samples); |