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); |