9 #include <lib/topology.h> 15 #include <lib/jsmn_helper.h> 19 #include <datatypes/heap.h> 28 unsigned size_checkpoint_costs(
void){
31 sizeof(double) * topology_global.
lp_cnt +
32 sizeof(
unsigned) * 2 * topology_global.
lp_cnt;
35 void *load_topology_file_costs(
c_jsmntok_t *root_token,
const char *json_base){
38 const unsigned lp_cnt = topology_global.
lp_cnt;
39 const unsigned neighbours_cnt = topology_global.
directions;
42 c_jsmntok_t *values_tok = get_value_token_by_key(root_token, json_base, root_token,
"values");
43 if(!values_tok|| values_tok->type != JSMN_ARRAY || children_count_token(root_token, values_tok) != lp_cnt)
44 rootsim_error(
false,
"Invalid or missing json value with key \"values\"");
47 double *ret_data = rsalloc(
sizeof(
double) * neighbours_cnt * lp_cnt);
50 for (i = 0; i < lp_cnt; ++i) {
52 aux_tok = get_at_token(root_token, values_tok, i);
55 if(!aux_tok || parse_double_array(root_token, json_base, aux_tok, neighbours_cnt, &ret_data[i * neighbours_cnt]) < 0)
56 rootsim_error(
false,
"Invalid or missing value in the current array of costs");
63 for (i = 0; i < neighbours_cnt * lp_cnt; ++i) {
66 if(ret_data[i] > -1.0 || ret_data[i] < -1.0)
67 rootsim_error(
true,
"Negative costs are still not supported");
69 ret_data[i] = INFINITY;
76 topology_t *topology_costs_init(
unsigned this_region_id,
void *topology_data){
77 (void) this_region_id;
79 const unsigned lp_cnt = topology_global.
lp_cnt;
80 const unsigned neighbours = topology_global.
directions;
90 memcpy(topology->
data, topology_data,
sizeof(
double) * neighbours * lp_cnt);
92 for(i = 0; i < neighbours * lp_cnt; ++i)
93 topology->
data[i] = 1.0;
95 topology->
dirty =
true;
101 #define __cmp_dijkstra_h(a, b) CmpSumHelpers(a.cost, b.cost) 103 static void dijkstra_costs(
const topology_t *topology,
unsigned int source_cell,
double min_costs[RegionsCount()],
unsigned int previous[RegionsCount()]) {
105 struct _dijkstra_h_t{
110 const unsigned neighbours = topology_global.
directions;
111 const unsigned lp_cnt = topology_global.
lp_cnt;
112 unsigned i, receiver;
114 rootsim_heap(
struct _dijkstra_h_t) heap;
115 const double *costs = topology->
data;
117 struct _dijkstra_h_t current_scan = {{0, 0}, source_cell}, partial_scan = {0};
121 min_costs_h[i].crt = 0;
122 min_costs_h[i].sum = INFINITY;
123 previous[i] = UINT_MAX;
128 min_costs_h[source_cell] = current_scan.cost;
130 heap_insert(heap, current_scan, __cmp_dijkstra_h);
132 while(!heap_empty(heap)) {
134 current_scan = heap_extract(heap, __cmp_dijkstra_h);
136 if(CmpSumHelpers(current_scan.cost, min_costs_h[current_scan.cell]) > 0)
139 for(i = 0; i < neighbours; ++i){
141 receiver = get_raw_receiver(current_scan.cell, i);
142 if(receiver ==
DIRECTION_INVALID || isinf(costs[current_scan.cell * neighbours + i]))
145 partial_scan.cost =
PartialNeumaierSum(current_scan.cost, costs[current_scan.cell * neighbours + i]);
147 if(CmpSumHelpers(partial_scan.cost, min_costs_h[receiver]) < 0){
149 previous[receiver] = current_scan.cell;
151 partial_scan.cell = receiver;
153 min_costs_h[receiver] = partial_scan.cost;
155 heap_insert(heap, partial_scan, __cmp_dijkstra_h);
162 min_costs[i] = ValueSumHelper(min_costs_h[i]);
165 #undef __cmp_dijsktra_h 167 static void refresh_cache_costs(
topology_t *topology){
169 const unsigned lp_cnt = topology_global.
lp_cnt;
174 memset(&topology->
prev_next_cache[lp_cnt], UCHAR_MAX,
sizeof(
unsigned) * lp_cnt);
175 topology->
dirty =
false;
189 void set_value_topology_costs(
unsigned from,
unsigned to,
double value){
193 static_assert(
sizeof(
double) ==
sizeof(uint64_t),
"the bit operation trick on TOPOLOGY_COST updates is wrong");
196 to_send.
upd.val_bits ^= old.val_bits;
202 topology->
data[to_send.loc_i] = value;
204 unsigned i = topology_global.
lp_cnt;
211 topology->
dirty =
true;
214 void update_topology_costs(
void){
220 old_p->val_bits ^= upd_p->
upd.val_bits;
222 topology->
dirty =
true;
225 double get_value_topology_costs(
unsigned from,
unsigned to){
229 bool is_reachable_costs(
unsigned to){
231 return find_receiver_toward_costs(to) != UINT_MAX;
234 unsigned int find_receiver_toward_costs(
unsigned int to){
236 const unsigned lp_cnt = topology_global.
lp_cnt;
239 refresh_cache_costs(topology);
243 if(*ret_p == UINT_MAX){
245 unsigned path[lp_cnt];
256 if(*ret_p == this_lp){
264 double compute_min_tour_costs(
unsigned int source,
unsigned int dest,
unsigned int result[RegionsCount()]) {
266 const unsigned lp_cnt = topology_global.
lp_cnt;
270 refresh_cache_costs(topology);
272 if(!build_path(lp_cnt, result, topology->
prev_next_cache, source, dest)){
280 return topology->
data[topology_global.
directions * lp_cnt + dest];
283 unsigned int previous[lp_cnt];
284 double min_costs[lp_cnt];
286 dijkstra_costs(topology, source, min_costs, previous);
288 if(!build_path(lp_cnt, result, previous, source, dest))
291 return min_costs[dest];
A generic invalid direction.
ROOT-Sim header for model development.
#define UNION_CAST(x, destType)
Macro to "legitimately" pun a type.
struct _sum_helper_t PartialNeumaierSum(struct _sum_helper_t sh, double addendum)
unsigned int to_int
The GID numerical value.
The ROOT-Sim scheduler main module header.
This is the implementation of a dynamic array, used for managing various data structures.
__thread struct lp_struct * current
This is a per-thread variable pointing to the block state of the LP currently scheduled.
this represents a partial Neumaier sum
double data[]
a pointer to the cache used to speedup queries on paths (unused in probabilities topology type) ...
double val
needed by the bitwise XOR
__thread msg_t * current_evt
topology_t * topology
pointer to the topology struct
union _double_bits_trick upd
where to put the new value
GID_t gid
Global ID of the LP.
unsigned * prev_next_cache
#define unlikely(exp)
Optimize the branch as likely not taken.
the customised struct for TOPOLOGY_OBSTACLES representation