Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fix https://framagit.org/simgrid/simgrid/issues/28
[simgrid.git] / src / xbt / automaton / automaton.c
1 /* automaton - representation of büchi automaton */
2
3 /* Copyright (c) 2011-2019. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "xbt/automaton.h"
9 #include <stdio.h> /* printf */
10 #include <xbt/log.h>
11 #include <xbt/sysdep.h>
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_automaton, xbt, "Automaton");
14
15 struct xbt_automaton_propositional_symbol{
16   char* pred;
17   /** Callback used to evaluate the value of the symbol */
18   int (*callback)(void*);
19   /** Additional data for the callback.
20       Alternatively it can be used as a pointer to the data. */
21   void* data;
22   /** Optional callback used to free the data field */
23   void (*free_function)(void*);
24 };
25
26 xbt_automaton_t xbt_automaton_new(void){
27   xbt_automaton_t automaton = xbt_new0(struct xbt_automaton, 1);
28   automaton->states = xbt_dynar_new(sizeof(xbt_automaton_state_t), xbt_automaton_state_free_voidp);
29   automaton->transitions = xbt_dynar_new(sizeof(xbt_automaton_transition_t), xbt_automaton_transition_free_voidp);
30   automaton->propositional_symbols = xbt_dynar_new(sizeof(xbt_automaton_propositional_symbol_t), xbt_automaton_propositional_symbol_free_voidp);
31   return automaton;
32 }
33
34 xbt_automaton_state_t xbt_automaton_state_new(xbt_automaton_t a, int type, char* id){
35   xbt_automaton_state_t state = xbt_new0(struct xbt_automaton_state, 1);
36   state->type = type;
37   state->id = xbt_strdup(id);
38   state->in = xbt_dynar_new(sizeof(xbt_automaton_transition_t), xbt_automaton_transition_free_voidp);
39   state->out = xbt_dynar_new(sizeof(xbt_automaton_transition_t), xbt_automaton_transition_free_voidp);
40   xbt_dynar_push(a->states, &state);
41   return state;
42 }
43
44 xbt_automaton_transition_t xbt_automaton_transition_new(xbt_automaton_t a, xbt_automaton_state_t src, xbt_automaton_state_t dst, xbt_automaton_exp_label_t label){
45   xbt_automaton_transition_t transition = xbt_new0(struct xbt_automaton_transition, 1);
46   if(src != NULL){
47     xbt_dynar_push(src->out, &transition);
48     transition->src = src;
49   }
50   if(dst != NULL){
51     xbt_dynar_push(dst->in, &transition);
52     transition->dst = dst;
53   }
54   transition->label = label;
55   xbt_dynar_push(a->transitions, &transition);
56   return transition;
57 }
58
59 xbt_automaton_exp_label_t xbt_automaton_exp_label_new_or(xbt_automaton_exp_label_t left,
60                                                          xbt_automaton_exp_label_t right)
61 {
62   xbt_automaton_exp_label_t label = xbt_new0(struct xbt_automaton_exp_label, 1);
63   label->type                     = AUT_OR;
64   label->u.or_and.left_exp        = left;
65   label->u.or_and.right_exp       = right;
66   return label;
67 }
68
69 xbt_automaton_exp_label_t xbt_automaton_exp_label_new_and(xbt_automaton_exp_label_t left,
70                                                           xbt_automaton_exp_label_t right)
71 {
72   xbt_automaton_exp_label_t label = xbt_new0(struct xbt_automaton_exp_label, 1);
73   label->type                     = AUT_AND;
74   label->u.or_and.left_exp        = left;
75   label->u.or_and.right_exp       = right;
76   return label;
77 }
78
79 xbt_automaton_exp_label_t xbt_automaton_exp_label_new_not(xbt_automaton_exp_label_t exp_not)
80 {
81   xbt_automaton_exp_label_t label = xbt_new0(struct xbt_automaton_exp_label, 1);
82   label->type                     = AUT_NOT;
83   label->u.exp_not                = exp_not;
84   return label;
85 }
86
87 xbt_automaton_exp_label_t xbt_automaton_exp_label_new_predicat(char* p)
88 {
89   xbt_automaton_exp_label_t label = xbt_new0(struct xbt_automaton_exp_label, 1);
90   label->type                     = AUT_PREDICAT;
91   label->u.predicat               = xbt_strdup(p);
92   return label;
93 }
94
95 xbt_automaton_exp_label_t xbt_automaton_exp_label_new_one(void)
96 {
97   xbt_automaton_exp_label_t label = xbt_new0(struct xbt_automaton_exp_label, 1);
98   label->type                     = AUT_ONE;
99   return label;
100 }
101
102 xbt_dynar_t xbt_automaton_get_states(xbt_automaton_t a){
103   return a->states;
104 }
105
106 xbt_dynar_t xbt_automaton_get_transitions(xbt_automaton_t a){
107   return a->transitions;
108 }
109
110 xbt_automaton_transition_t xbt_automaton_get_transition(XBT_ATTRIB_UNUSED xbt_automaton_t a, xbt_automaton_state_t src,
111                                                         xbt_automaton_state_t dst)
112 {
113   xbt_automaton_transition_t transition;
114   unsigned int cursor;
115   xbt_dynar_foreach(src->out, cursor, transition){
116     if((transition->src == src) && (transition->dst == dst))
117       return transition;
118   }
119   return NULL;
120 }
121
122 xbt_automaton_state_t xbt_automaton_transition_get_source(xbt_automaton_transition_t t){
123   return t->src;
124 }
125
126 xbt_automaton_state_t xbt_automaton_transition_get_destination(xbt_automaton_transition_t t){
127   return t->dst;
128 }
129
130 void xbt_automaton_transition_set_source(xbt_automaton_transition_t t, xbt_automaton_state_t src){
131   t->src = src;
132   xbt_dynar_push(src->out,&t);
133 }
134
135 void xbt_automaton_transition_set_destination(xbt_automaton_transition_t t, xbt_automaton_state_t dst){
136   t->dst = dst;
137   xbt_dynar_push(dst->in,&t);
138 }
139
140 xbt_dynar_t xbt_automaton_state_get_out_transitions(xbt_automaton_state_t s){
141   return s->out;
142 }
143
144 xbt_dynar_t xbt_automaton_state_get_in_transitions(xbt_automaton_state_t s){
145   return s->in;
146 }
147
148 xbt_automaton_state_t xbt_automaton_state_exists(xbt_automaton_t a, char *id){
149   xbt_automaton_state_t state = NULL;
150   unsigned int cursor = 0;
151   xbt_dynar_foreach(a->states, cursor, state){
152    if(strcmp(state->id, id)==0)
153      return state;
154   }
155   return NULL;
156 }
157
158 void xbt_automaton_display(xbt_automaton_t a){
159   unsigned int cursor;
160   xbt_automaton_state_t state = NULL;
161
162   printf("\n\nCurrent state: %s\n", a->current_state->id);
163
164   printf("\nStates' List: %lu\n\n", xbt_dynar_length(a->states));
165
166   xbt_dynar_foreach(a->states, cursor, state)
167     printf("ID: %s, type: %d\n", state->id, state->type);
168
169   xbt_automaton_transition_t transition;
170   printf("\nTransitions: %lu\n\n", xbt_dynar_length(a->transitions));
171
172   xbt_dynar_foreach(a->transitions, cursor, transition){
173     printf("label:");
174     xbt_automaton_exp_label_display(transition->label);
175     printf(", %s -> %s\n", transition->src->id, transition->dst->id);
176   }
177 }
178
179 void xbt_automaton_exp_label_display(xbt_automaton_exp_label_t label){
180   printf("(");
181   switch(label->type){
182     case 0:
183       xbt_automaton_exp_label_display(label->u.or_and.left_exp);
184       printf(" || ");
185       xbt_automaton_exp_label_display(label->u.or_and.right_exp);
186       break;
187     case 1:
188       xbt_automaton_exp_label_display(label->u.or_and.left_exp);
189       printf(" && ");
190       xbt_automaton_exp_label_display(label->u.or_and.right_exp);
191       break;
192     case 2:
193       printf("!");
194       xbt_automaton_exp_label_display(label->u.exp_not);
195       break;
196     case 3:
197       printf("%s", label->u.predicat);
198       break;
199     case 4:
200       printf("1");
201       break;
202     default:
203       break;
204   }
205   printf(")");
206 }
207
208 xbt_automaton_state_t xbt_automaton_get_current_state(xbt_automaton_t a){
209   return a->current_state;
210 }
211
212 static int call_simple_function(void* function)
213 {
214   return ((int (*)(void)) function)();
215 }
216
217 xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new(xbt_automaton_t a, const char* id,
218                                                                             int (*fct)(void))
219 {
220   xbt_automaton_propositional_symbol_t prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
221   prop_symb->pred = xbt_strdup(id);
222   prop_symb->callback                            = &call_simple_function;
223   prop_symb->data = fct;
224   prop_symb->free_function = NULL;
225   xbt_dynar_push(a->propositional_symbols, &prop_symb);
226   return prop_symb;
227 }
228
229 XBT_PUBLIC xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new_pointer(xbt_automaton_t a,
230                                                                                                const char* id,
231                                                                                                int* value)
232 {
233   xbt_automaton_propositional_symbol_t prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
234   prop_symb->pred = xbt_strdup(id);
235   prop_symb->callback = NULL;
236   prop_symb->data = value;
237   prop_symb->free_function = NULL;
238   xbt_dynar_push(a->propositional_symbols, &prop_symb);
239   return prop_symb;
240 }
241
242 XBT_PUBLIC xbt_automaton_propositional_symbol_t xbt_automaton_propositional_symbol_new_callback(
243     xbt_automaton_t a, const char* id, xbt_automaton_propositional_symbol_callback_type callback, void* data,
244     xbt_automaton_propositional_symbol_free_function_type free_function)
245 {
246   xbt_automaton_propositional_symbol_t prop_symb = xbt_new0(struct xbt_automaton_propositional_symbol, 1);
247   prop_symb->pred = xbt_strdup(id);
248   prop_symb->callback = callback;
249   prop_symb->data = data;
250   prop_symb->free_function = free_function;
251   xbt_dynar_push(a->propositional_symbols, &prop_symb);
252   return prop_symb;
253 }
254
255 XBT_PUBLIC int xbt_automaton_propositional_symbol_evaluate(xbt_automaton_propositional_symbol_t symbol)
256 {
257   if (symbol->callback)
258     return (symbol->callback)(symbol->data);
259   else
260     return *(int*) symbol->data;
261 }
262
263 XBT_PUBLIC xbt_automaton_propositional_symbol_callback_type
264 xbt_automaton_propositional_symbol_get_callback(xbt_automaton_propositional_symbol_t symbol)
265 {
266   return symbol->callback;
267 }
268
269 XBT_PUBLIC void* xbt_automaton_propositional_symbol_get_data(xbt_automaton_propositional_symbol_t symbol)
270 {
271   return symbol->data;
272 }
273
274 XBT_PUBLIC const char* xbt_automaton_propositional_symbol_get_name(xbt_automaton_propositional_symbol_t symbol)
275 {
276   return symbol->pred;
277 }
278
279 int xbt_automaton_state_compare(xbt_automaton_state_t s1, xbt_automaton_state_t s2){
280
281   /* single id for each state, id and type sufficient for comparison*/
282
283   if(strcmp(s1->id, s2->id))
284     return 1;
285
286   if(s1->type != s2->type)
287     return 1;
288
289   return 0;
290
291 }
292
293 int xbt_automaton_transition_compare(const void *t1, const void *t2){
294
295   if(xbt_automaton_state_compare(((xbt_automaton_transition_t)t1)->src, ((xbt_automaton_transition_t)t2)->src))
296     return 1;
297
298   if(xbt_automaton_state_compare(((xbt_automaton_transition_t)t1)->dst, ((xbt_automaton_transition_t)t2)->dst))
299     return 1;
300
301   if(xbt_automaton_exp_label_compare(((xbt_automaton_transition_t)t1)->label,((xbt_automaton_transition_t)t2)->label))
302     return 1;
303
304   return 0;
305
306 }
307
308 int xbt_automaton_exp_label_compare(xbt_automaton_exp_label_t l1, xbt_automaton_exp_label_t l2){
309
310   if(l1->type != l2->type)
311     return 1;
312
313   int res;
314   switch(l1->type){
315   case 0 : // OR
316   case 1 : // AND
317     if(xbt_automaton_exp_label_compare(l1->u.or_and.left_exp, l2->u.or_and.left_exp))
318       res = 1;
319     else
320       res = xbt_automaton_exp_label_compare(l1->u.or_and.right_exp, l2->u.or_and.right_exp);
321     break;
322   case 2 : // NOT
323     res = xbt_automaton_exp_label_compare(l1->u.exp_not, l2->u.exp_not);
324     break;
325   case 3 : // predicat
326     res = strcmp(l1->u.predicat, l2->u.predicat);
327     break;
328   case 4 : // 1
329     res = 0;
330     break;
331   default :
332     res = -1;
333     break;
334   }
335   return res;
336 }
337
338 int xbt_automaton_propositional_symbols_compare_value(xbt_dynar_t s1, xbt_dynar_t s2){
339   unsigned int nb_elem = xbt_dynar_length(s1);
340
341   for (unsigned int cursor = 0; cursor < nb_elem; cursor++) {
342     int* iptr1 = xbt_dynar_get_ptr(s1, cursor);
343     int* iptr2 = xbt_dynar_get_ptr(s2, cursor);
344     if(*iptr1 != *iptr2)
345       return 1;
346   }
347
348   return 0;
349 }
350
351 static void xbt_automaton_transition_free(xbt_automaton_transition_t t);
352 static void xbt_automaton_exp_label_free(xbt_automaton_exp_label_t e);
353 static void xbt_automaton_propositional_symbol_free(xbt_automaton_propositional_symbol_t ps);
354
355 void xbt_automaton_state_free(xbt_automaton_state_t s){
356   if (s != NULL) {
357     xbt_free(s->id);
358     xbt_dynar_free(&(s->in));
359     xbt_dynar_free(&(s->out));
360     xbt_free(s);
361   }
362 }
363
364 void xbt_automaton_state_free_voidp(void *s){
365   xbt_automaton_state_free((xbt_automaton_state_t) * (void **) s);
366 }
367
368 static void xbt_automaton_transition_free(xbt_automaton_transition_t t){
369   if(t){
370     xbt_automaton_exp_label_free(t->label);
371     xbt_free(t);
372     t = NULL;
373   }
374 }
375
376 void xbt_automaton_transition_free_voidp(void *t){
377   xbt_automaton_transition_free((xbt_automaton_transition_t) * (void **) t);
378 }
379
380 static void xbt_automaton_exp_label_free(xbt_automaton_exp_label_t e){
381   if(e){
382     switch(e->type){
383     case 0:
384     case 1:
385       xbt_automaton_exp_label_free(e->u.or_and.left_exp);
386       xbt_automaton_exp_label_free(e->u.or_and.right_exp);
387       break;
388     case 2:
389       xbt_automaton_exp_label_free(e->u.exp_not);
390       break;
391     case 3:
392       xbt_free(e->u.predicat);
393       break;
394     default:
395       break;
396     }
397     xbt_free(e);
398     e = NULL;
399   }
400 }
401
402 void xbt_automaton_exp_label_free_voidp(void *e){
403   xbt_automaton_exp_label_free((xbt_automaton_exp_label_t) * (void **) e);
404 }
405
406 static void xbt_automaton_propositional_symbol_free(xbt_automaton_propositional_symbol_t ps){
407   if(ps){
408     xbt_free(ps->pred);
409     xbt_free(ps);
410     ps = NULL;
411   }
412 }
413
414 void xbt_automaton_propositional_symbol_free_voidp(void *ps){
415   xbt_automaton_propositional_symbol_t symbol = (xbt_automaton_propositional_symbol_t) * (void **) ps;
416   if (symbol->free_function)
417     symbol->free_function(symbol->data);
418   xbt_automaton_propositional_symbol_free(symbol);
419 }
420
421 void xbt_automaton_free(xbt_automaton_t a){
422   if(a){
423     xbt_dynar_free(&(a->propositional_symbols));
424     xbt_dynar_free(&(a->transitions));
425     xbt_dynar_free(&(a->states));
426     xbt_automaton_state_free(a->current_state);
427     xbt_free(a);
428     a = NULL;
429   }
430 }