Skip to content

Commit 252a8a4

Browse files
feat(GibbsEnergy): refactor energy terms
1 parent 00d4de7 commit 252a8a4

12 files changed

Lines changed: 219 additions & 203 deletions

File tree

include/geode/stochastic/sampling/mcmc/metropolis_hasting_sampler.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ namespace geode
188188
{
189189
const auto new_object = proposal.new_object();
190190
const auto delta_log_energy =
191-
energy_.delta_log_energy_add( state, new_object );
191+
energy_.delta_log_add( state, new_object );
192192
return accept_or_reject( proposal, state, engine, delta_log_energy,
193193
[]( auto& state, auto& proposal ) {
194194
state.add_object(
@@ -203,7 +203,7 @@ namespace geode
203203
{
204204
const auto old_object_id = proposal.old_object_id();
205205
const auto delta_log_energy =
206-
energy_.delta_log_energy_remove( state, old_object_id );
206+
energy_.delta_log_remove( state, old_object_id );
207207
return accept_or_reject( proposal, state, engine, delta_log_energy,
208208
[]( auto& state, auto& proposal ) {
209209
state.remove_object( proposal.old_object_id() );
@@ -216,8 +216,8 @@ namespace geode
216216
{
217217
const auto new_object = proposal.new_object();
218218
const auto old_object_id = proposal.old_object_id();
219-
const auto delta_log_energy = energy_.delta_log_energy_change(
220-
state, old_object_id, new_object );
219+
const auto delta_log_energy =
220+
energy_.delta_log_change( state, old_object_id, new_object );
221221
// should we test that objects are in the same group?
222222
// should be ensured by the dynamic
223223
return accept_or_reject( proposal, state, engine, delta_log_energy,

include/geode/stochastic/sampling/mcmc/models/components/density_term.hpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,10 @@ namespace geode
3333
class DensityTerm : public EnergyTerm< ObjectType >
3434
{
3535
public:
36-
explicit DensityTerm( std::string_view name, double lambda )
37-
: EnergyTerm< ObjectType >( name, lambda )
38-
{
39-
}
40-
41-
explicit DensityTerm(
42-
std::string_view name, double lambda, const uuid& subset_id )
43-
: EnergyTerm< ObjectType >( name, lambda, subset_id )
36+
explicit DensityTerm( std::string_view name,
37+
double lambda,
38+
absl::flat_hash_set< uuid > targeted_subset_ids )
39+
: EnergyTerm< ObjectType >( name, lambda, targeted_subset_ids )
4440
{
4541
}
4642

@@ -79,12 +75,12 @@ namespace geode
7975

8076
double statistic( const ObjectSet< ObjectType >& state ) const override
8177
{
82-
if( this->targeted_subset_id() )
78+
index_t count{ 0 };
79+
for( const auto& subset_uuid : this->targeted_subset_ids() )
8380
{
84-
return static_cast< double >( state.nb_objects_in_subset(
85-
this->targeted_subset_id().value() ) );
81+
count += state.nb_objects_in_subset( subset_uuid );
8682
}
87-
return static_cast< double >( state.nb_objects() );
83+
return static_cast< double >( count );
8884
}
8985
};
9086
} // namespace geode

include/geode/stochastic/sampling/mcmc/models/components/energy_term.hpp

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323
#pragma once
2424

25+
#include <absl/container/flat_hash_set.h>
2526
#include <geode/stochastic/common.hpp>
2627
#include <geode/stochastic/spatial/object_set.hpp>
2728
#include <optional>
@@ -96,17 +97,12 @@ namespace geode
9697
class EnergyTerm
9798
{
9899
public:
99-
explicit EnergyTerm( std::string_view name, double param )
100-
: name_{ name }, energy_scale_{ param }
101-
{
102-
}
103-
104100
explicit EnergyTerm( std::string_view name,
105101
double param,
106-
const uuid& targeted_subset_id )
102+
absl::flat_hash_set< uuid > targeted_subset_ids )
107103
: name_{ name },
108104
energy_scale_{ param },
109-
targeted_subset_id_{ targeted_subset_id }
105+
targeted_subset_ids_{ std::move( targeted_subset_ids ) }
110106
{
111107
}
112108

@@ -127,9 +123,9 @@ namespace geode
127123
return energy_scale_.parameter();
128124
}
129125

130-
std::optional< uuid > targeted_subset_id() const
126+
const absl::flat_hash_set< uuid >& targeted_subset_ids() const
131127
{
132-
return targeted_subset_id_;
128+
return targeted_subset_ids_;
133129
}
134130

135131
/// Energy contribution for a given statistic multiplier
@@ -158,45 +154,42 @@ namespace geode
158154
{
159155
auto message =
160156
absl::StrCat( "Term : ", name(), "; uuid: ", id().string(),
161-
" parameter value: ", energy_scale_.parameter() );
162-
if( targeted_subset_id_ )
157+
" parameter value: ", energy_scale_.parameter(),
158+
" applyied on ", targeted_subset_ids_.size(),
159+
" object subsets -->" );
160+
for( const auto& subset_uuid : targeted_subset_ids_ )
163161
{
164-
absl::StrAppend( &message, " targetted subset: ",
165-
targeted_subset_id_.value().string() );
162+
absl::StrAppend( &message, "\t", subset_uuid.string() );
166163
}
167164
return message;
168165
}
169166

170167
protected:
171168
bool is_targeted_subset( const uuid& subset_id ) const
172169
{
173-
return !targeted_subset_id_ || subset_id == *targeted_subset_id_;
170+
return targeted_subset_ids_.find( subset_id )
171+
!= targeted_subset_ids_.end();
174172
}
175173

176174
template < typename Func >
177175
void for_each_targeted_object(
178176
const ObjectSet< ObjectType >& state, Func&& do_apply ) const
179177
{
180-
if( targeted_subset_id_ )
178+
for( const auto& targeted_subset_id : targeted_subset_ids_ )
181179
{
182180
for( const auto id : geode::Range{
183-
state.nb_objects_in_subset( *targeted_subset_id_ ) } )
181+
state.nb_objects_in_subset( targeted_subset_id ) } )
184182
{
185-
do_apply( { id, *targeted_subset_id_ } );
183+
do_apply( ObjectId{ id, targeted_subset_id } );
186184
}
187-
return;
188-
}
189-
for( const auto& id : state.get_all_object() )
190-
{
191-
do_apply( id );
192185
}
193186
}
194187

195188
private:
196189
std::string name_;
197190
detail::EnergyScale energy_scale_;
198191

199-
std::optional< uuid > targeted_subset_id_{};
192+
absl::flat_hash_set< uuid > targeted_subset_ids_;
200193
uuid energy_term_id_{};
201194
};
202195
} // namespace geode
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#pragma once
2+
3+
#include <absl/container/flat_hash_map.h>
4+
#include <geode/stochastic/sampling/mcmc/models/components/energy_term.hpp>
5+
6+
namespace geode
7+
{
8+
template < typename ObjectType >
9+
class EnergyTermCollection
10+
{
11+
OPENGEODE_DISABLE_COPY( EnergyTermCollection );
12+
13+
public:
14+
EnergyTermCollection() = default;
15+
EnergyTermCollection( EnergyTermCollection&& ) noexcept = default;
16+
~EnergyTermCollection() = default;
17+
18+
uuid add_energy_term( std::unique_ptr< EnergyTerm< ObjectType > > term )
19+
{
20+
const uuid id = term->id();
21+
EnergyTerm< ObjectType >* ptr = term.get();
22+
23+
energy_terms_.emplace( id, std::move( term ) );
24+
25+
for( const uuid& subset_id : ptr->targeted_subset_ids() )
26+
{
27+
subset_to_terms_[subset_id].push_back( ptr );
28+
}
29+
return id;
30+
}
31+
32+
bool remove_energy_term( const uuid& id )
33+
{
34+
auto it = energy_terms_.find( id );
35+
if( it == energy_terms_.end() )
36+
return false;
37+
38+
EnergyTerm< ObjectType >* ptr = it->second.get();
39+
for( const uuid& subset_id : ptr->targeted_subset_ids() )
40+
{
41+
auto& vec = subset_to_terms_[subset_id];
42+
vec.erase(
43+
std::remove( vec.begin(), vec.end(), ptr ), vec.end() );
44+
if( vec.empty() )
45+
subset_to_terms_.erase( subset_id );
46+
}
47+
48+
energy_terms_.erase( it );
49+
return true;
50+
}
51+
52+
void clear()
53+
{
54+
energy_terms_.clear();
55+
subset_to_terms_.clear();
56+
}
57+
58+
[[nodiscard]] index_t size() const
59+
{
60+
return energy_terms_.size();
61+
}
62+
63+
[[nodiscard]] EnergyTerm< ObjectType >* get( const uuid& id ) const
64+
{
65+
auto it = energy_terms_.find( id );
66+
OPENGEODE_EXCEPTION( it != energy_terms_.end(),
67+
absl::StrCat( "[EnergyTermCollection] Unknown energy term: ",
68+
id.string() ) );
69+
return it->second.get();
70+
}
71+
72+
[[nodiscard]] std::vector< EnergyTerm< ObjectType >* > terms_for_subset(
73+
const uuid& subset_id ) const
74+
{
75+
auto it = subset_to_terms_.find( subset_id );
76+
return it != subset_to_terms_.end()
77+
? it->second
78+
: std::vector< EnergyTerm< ObjectType >* >{};
79+
}
80+
81+
[[nodiscard]] std::vector< EnergyTerm< ObjectType >* > all_terms() const
82+
{
83+
std::vector< EnergyTerm< ObjectType >* > result;
84+
result.reserve( energy_terms_.size() );
85+
for( const auto& [id, term] : energy_terms_ )
86+
{
87+
result.push_back( term.get() );
88+
}
89+
return result;
90+
}
91+
92+
std::string string() const
93+
{
94+
auto message = absl::StrCat(
95+
"Gibbs Energy: ", energy_terms_.size(), " terms:" );
96+
// we should find a way to iterate in a ordered way.
97+
for( const auto energy_term : all_terms() )
98+
{
99+
absl::StrAppend( &message, "\n\t --> ", energy_term->string() );
100+
}
101+
return message;
102+
}
103+
104+
private:
105+
absl::flat_hash_map< uuid, std::unique_ptr< EnergyTerm< ObjectType > > >
106+
energy_terms_;
107+
absl::flat_hash_map< uuid, std::vector< EnergyTerm< ObjectType >* > >
108+
subset_to_terms_;
109+
};
110+
} // namespace geode

include/geode/stochastic/sampling/mcmc/models/components/pairwise_term.hpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,9 @@ namespace geode
3737
public:
3838
explicit PairwiseTerm( std::string_view name,
3939
double gamma,
40-
std::unique_ptr< PairwiseInteraction< ObjectType > >&& interaction )
41-
: EnergyTerm< ObjectType >( name, gamma ),
42-
interaction_( std::move( interaction ) )
43-
{
44-
}
45-
46-
explicit PairwiseTerm( std::string_view name,
47-
double gamma,
48-
std::unique_ptr< PairwiseInteraction< ObjectType > >&& interaction,
49-
const uuid& subset_id )
50-
: EnergyTerm< ObjectType >( name, gamma, subset_id ),
40+
absl::flat_hash_set< uuid > targeted_subset_ids,
41+
std::unique_ptr< PairwiseInteraction< ObjectType > > interaction )
42+
: EnergyTerm< ObjectType >( name, gamma, targeted_subset_ids ),
5143
interaction_( std::move( interaction ) )
5244
{
5345
}
@@ -157,6 +149,16 @@ namespace geode
157149
state.get_all_object(); // state.neighbors( obj_id, 1.1 );
158150
for( const auto& neigh_obj_id : neighbors )
159151
{
152+
// if( neigh_obj_id.subset_id < obj_id.subset_id )
153+
//{
154+
// continue;
155+
// }
156+
// if( neigh_obj_id.subset_id == obj_id.subset_id
157+
// && neigh_obj_id.id <= obj_id.id )
158+
//{
159+
// continue;
160+
// }
161+
160162
if( neigh_obj_id == obj_id )
161163
{
162164
continue;

include/geode/stochastic/sampling/mcmc/models/components/single_object_term.hpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,9 @@ namespace geode
3434
public:
3535
explicit SingleObjectTerm( std::string_view name,
3636
double lambda,
37+
absl::flat_hash_set< uuid > targeted_subset_ids,
3738
ObjectContributionFunc contribution_func )
38-
: EnergyTerm< ObjectType >( name, lambda ),
39-
contribution_func_( std::move( contribution_func ) )
40-
{
41-
}
42-
43-
explicit SingleObjectTerm( std::string_view name,
44-
double lambda,
45-
ObjectContributionFunc contribution_func,
46-
std::optional< uuid > subset_id )
47-
: EnergyTerm< ObjectType >( name, lambda, subset_id ),
39+
: EnergyTerm< ObjectType >( name, lambda, targeted_subset_ids ),
4840
contribution_func_( std::move( contribution_func ) )
4941
{
5042
}

0 commit comments

Comments
 (0)