Initial commit
This commit is contained in:
892
anproc.c
Normal file
892
anproc.c
Normal file
@@ -0,0 +1,892 @@
|
||||
/** anproc.c **/
|
||||
|
||||
/*
|
||||
* Przetwarzanie struktur stworzonych podczas wczytywania sieci automatow,
|
||||
* tworzenie produktu na podstawie sieci automatow.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include "anproc.h"
|
||||
#include "antypes.h"
|
||||
#include "anmacro.h"
|
||||
#include "macro.h"
|
||||
#include "dbm.h"
|
||||
|
||||
static Aut *aut = NULL;
|
||||
static Aut_idx naut = 0;
|
||||
|
||||
static Clock_idx pclocks_cnt = 0; /* zegary w automacie produktowym */
|
||||
static ProdClock *pclocks_map;
|
||||
static Clock_idx **rpclocks_map;
|
||||
|
||||
static Act *act = NULL;
|
||||
Act_idx nact = 0;
|
||||
|
||||
DBM_idx dbm_size = 0;
|
||||
DBM_elem *zeroDBM = NULL;
|
||||
ProdLoc_set *init_loc_set = NULL;
|
||||
|
||||
Property_set *ppts = NULL;
|
||||
|
||||
/*
|
||||
* Inicjalizacja przetwarzania sieci
|
||||
*
|
||||
* F-cja ustawia wartosci zmiennych globalnych, zeby uniknac przekazywania niektorych argumentow
|
||||
*/
|
||||
void
|
||||
net_init(AutNet *an)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
/* automaty */
|
||||
aut = an->aut;
|
||||
naut = an->naut;
|
||||
|
||||
/* akcje */
|
||||
act = an->act;
|
||||
nact = an->nact;
|
||||
|
||||
ppts = an->ppts;
|
||||
|
||||
/* zliczamy zegary ze wszystkich automatow skladowych */
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
pclocks_cnt += aut[i].nclks;
|
||||
}
|
||||
dbm_size = pclocks_cnt+1;
|
||||
|
||||
zeroDBM = dbm_init_zero(dbm_size);
|
||||
|
||||
prod_clocks_mkmap();
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf("Liczba zegarow w automacie produktowym = %d\n", pclocks_cnt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
prod_clocks_mkmap(void)
|
||||
{
|
||||
Clock_idx i, j, k;
|
||||
|
||||
pclocks_map = smalloc(sizeof(ProdClock)*pclocks_cnt); /* produktowy -> skladowy */
|
||||
rpclocks_map = smalloc(sizeof(Clock_idx *)*naut); /* skladowy -> produktowy */
|
||||
|
||||
k = 0;
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
rpclocks_map[i] = smalloc(sizeof(Clock_idx)*aut[i].nclks);
|
||||
for (j = 0; j < aut[i].nclks; j++)
|
||||
{
|
||||
pclocks_map[k].par_aut = i;
|
||||
pclocks_map[k].par_idx = j+1; /* ze wzgledu na x_0 */
|
||||
rpclocks_map[i][j] = k+1;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
prod_clock_maps_free(void)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
free(pclocks_map);
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
free(rpclocks_map[i]);
|
||||
}
|
||||
free(rpclocks_map);
|
||||
}
|
||||
|
||||
/*
|
||||
* Konwersja indeksu zegara z automatu skladowego
|
||||
* do indeksu zegara z automatu produktoweg
|
||||
*/
|
||||
Clock_idx
|
||||
prod_clock_idx2pidx(Aut_idx ai, Clock_idx ci)
|
||||
{
|
||||
assert(ai < naut);
|
||||
assert(ci-1 < aut[ai].nclks);
|
||||
|
||||
if (ci == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
assert(rpclocks_map[ai][ci-1] < dbm_size);
|
||||
return rpclocks_map[ai][ci-1];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Indeks produktowego zegara -> indeks skladowego
|
||||
*/
|
||||
ProdClock
|
||||
prod_clock_pidx2idx(Clock_idx ci)
|
||||
{
|
||||
if (ci == 0)
|
||||
{
|
||||
ProdClock r;
|
||||
r.par_aut = 0;
|
||||
r.par_idx = 0;
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pclocks_map[ci-1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Okreslanie poczatkowej lokacji produktowej
|
||||
*/
|
||||
Loc_idx *
|
||||
prod_loc_initial(void)
|
||||
{
|
||||
idx_t i;
|
||||
Loc_idx *initial;
|
||||
|
||||
initial = smalloc(sizeof(Loc_idx)*naut);
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
initial[i] = aut[i].init_loc;
|
||||
|
||||
return initial;
|
||||
}
|
||||
|
||||
/*
|
||||
* Kopiowanie okreslonej lokacji produktowej
|
||||
*/
|
||||
Loc_idx *
|
||||
prod_loc_copy(Loc_idx *prod_loc)
|
||||
{
|
||||
Loc_idx *copy;
|
||||
|
||||
copy = smalloc(sizeof(Loc_idx)*naut);
|
||||
(void)memcpy(copy, prod_loc, sizeof(Loc_idx)*naut);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pobieranie listy akcji POTENCJALNIE wykonalnych z lokacji produktowej
|
||||
*/
|
||||
bool *
|
||||
prod_loc_acts(Loc_idx *prod_loc)
|
||||
{
|
||||
idx_t i, j;
|
||||
Trans_set *t;
|
||||
bool *used_acts;
|
||||
|
||||
used_acts = smalloc_zero(sizeof(bool)*nact);
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
for (j = 0; j < aut[i].nloc; j++)
|
||||
{
|
||||
for (t = TRANS(aut[i].trans, aut[i].nloc, prod_loc[i], j);
|
||||
t != NULL;
|
||||
t = t->next)
|
||||
{
|
||||
used_acts[t->act] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return used_acts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wyswietlanie lokacji produktowej
|
||||
*/
|
||||
void
|
||||
prod_loc_show(Loc_idx *prod_loc)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
printf("( ");
|
||||
for (i = 0; i < naut; i++)
|
||||
printf("%s ", get_loc_name(aut[i].loc, prod_loc[i]));
|
||||
printf(")");
|
||||
}
|
||||
|
||||
/*
|
||||
* Dodawanie lokacji produktowej do zbioru
|
||||
*/
|
||||
ProdLoc_set *
|
||||
prod_loc_set_add(Loc_idx *prod_loc, DBM_elem *inv, ProdLoc_set **root, ProdLoc_set **cur)
|
||||
{
|
||||
ProdLoc_set *new;
|
||||
|
||||
new = smalloc(sizeof(ProdLoc_set));
|
||||
new->loc = prod_loc;
|
||||
new->inv = inv;
|
||||
new->src_locs = NULL;
|
||||
new->dst_locs = NULL;
|
||||
new->classes = NULL;
|
||||
new->trans_complete = false;
|
||||
|
||||
prod_loc_set_raw_add(new, root, cur);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dodawanie lokacji produktowej do zbioru w postaci surowej
|
||||
*/
|
||||
void
|
||||
prod_loc_set_raw_add(ProdLoc_set *new, ProdLoc_set **root, ProdLoc_set **cur)
|
||||
{
|
||||
new->next = NULL; /* nie wiadomo co tam bylo, a dodajemy na koncu */
|
||||
|
||||
if (!*root)
|
||||
*root = new;
|
||||
else
|
||||
(*cur)->next = new;
|
||||
*cur = new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sprawdzanie zawierania lokacji produktowej przez zbior
|
||||
*/
|
||||
bool
|
||||
prod_loc_set_is_in(Loc_idx *prod_loc, ProdLoc_set *root)
|
||||
{
|
||||
ProdLoc_set *cur;
|
||||
|
||||
for (cur = root; cur; cur = cur->next)
|
||||
{
|
||||
if (memcmp(cur->loc, prod_loc, sizeof(Loc_idx)*naut) == 0) return true; /* znaleziono */
|
||||
}
|
||||
|
||||
return false; /* nie znaleziono */
|
||||
}
|
||||
|
||||
/*
|
||||
* Sprawdzanie zawierania lokacji produktowej przez zbior
|
||||
*/
|
||||
ProdLoc_set *
|
||||
prod_loc_set_getp(Loc_idx *prod_loc, ProdLoc_set *root)
|
||||
{
|
||||
ProdLoc_set *cur;
|
||||
|
||||
for (cur = root; cur; cur = cur->next)
|
||||
{
|
||||
if (memcmp(cur->loc, prod_loc, sizeof(Loc_idx)*naut) == 0) return cur;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wyciaganie (wybieranie i usuwanie) elementu ze zbioru
|
||||
*/
|
||||
ProdLoc_set *
|
||||
prod_loc_set_raw_pick(ProdLoc_set **root)
|
||||
{
|
||||
ProdLoc_set *picked;
|
||||
|
||||
picked = *root; /* bierzemy korzen */
|
||||
|
||||
/* jesli byl korzen, to mial ustawione pole next, ktore wskazuje na nowy korzen */
|
||||
if (*root)
|
||||
*root = picked->next;
|
||||
|
||||
return picked;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wyswietlanie zbioru lokacji produktowych
|
||||
*/
|
||||
void
|
||||
prod_loc_set_show(ProdLoc_set *root)
|
||||
{
|
||||
ProdLoc_set *cur;
|
||||
|
||||
for (cur = root; cur; cur = cur->next)
|
||||
{
|
||||
prod_loc_show(cur->loc);
|
||||
printf("\ninv:\n");
|
||||
dbm_print(cur->inv, dbm_size);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Pelne zwalnianie pamieci przydzielonej na zbior lokacji produktowych
|
||||
* (pelne - wraz z lokacjami produktowymi).
|
||||
*/
|
||||
void
|
||||
prod_loc_set_free(ProdLoc_set *root)
|
||||
{
|
||||
ProdLoc_set *cur;
|
||||
|
||||
for (cur = root; cur; )
|
||||
{
|
||||
ProdLoc_set *tmp = cur;
|
||||
|
||||
cur = cur->next;
|
||||
free(tmp->loc);
|
||||
dbm_destroy(tmp->inv);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dodawanie przejscia do lokacji
|
||||
*/
|
||||
void
|
||||
trans_add(ProdLoc_set *src_loc, ProdLoc_set *dst_loc, ProdTrLoc_set *prtl)
|
||||
{
|
||||
ProdTrans_set *new_trans;
|
||||
DstLoc_set *cur_dst_loc;
|
||||
DstLoc_set *dst_group = NULL;
|
||||
|
||||
new_trans = smalloc(sizeof(ProdTrans_set));
|
||||
new_trans->act = prtl->act;
|
||||
new_trans->guard = prtl->guard;
|
||||
new_trans->clocks = prtl->clocks;
|
||||
new_trans->next = NULL;
|
||||
|
||||
/*
|
||||
- zgrupowane wszystkie przejscia do jednej lokacji docelowej
|
||||
- dodajac nowe przejscie szukamy grupy do ktorej nalezy okreslone
|
||||
przejscie dodac
|
||||
- jesli nie ma jeszcze takiej grupy, to ja tworzymy
|
||||
- z grupa zwiazany jest wskaznik na lokacje docelowa
|
||||
(dokladnie, element zbioru lokacji ja przetrzymujacy)
|
||||
*/
|
||||
|
||||
/* szukamy grupy przejsc prowadzacych do dst_loc */
|
||||
cur_dst_loc = src_loc->dst_locs;
|
||||
while (cur_dst_loc)
|
||||
{
|
||||
/* sprawdzamy czy znalezlismy cur_dst_loc == dst_loc */
|
||||
if (cur_dst_loc->loc_set == dst_loc)
|
||||
{
|
||||
dst_group = cur_dst_loc;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cur_dst_loc->next)
|
||||
break;
|
||||
else
|
||||
cur_dst_loc = cur_dst_loc->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* jesli dst_group jest nieustawione, to nie ma jeszcze takiej
|
||||
* lokacji docelowej i trzeba ja dodac
|
||||
*/
|
||||
if (!dst_group)
|
||||
{
|
||||
SrcLoc_set *new_src_loc;
|
||||
|
||||
dst_group = smalloc(sizeof(DstLoc_set));
|
||||
dst_group->loc_set = dst_loc;
|
||||
dst_group->trans = NULL;
|
||||
dst_group->last_trans = NULL;
|
||||
dst_group->next = NULL;
|
||||
|
||||
/*
|
||||
* naszym dst_locs_LAST jest cur_dst_loc (gdy dst_group == NULL)
|
||||
*/
|
||||
if (!src_loc->dst_locs)
|
||||
src_loc->dst_locs = dst_group;
|
||||
else
|
||||
{
|
||||
assert(cur_dst_loc != NULL);
|
||||
cur_dst_loc->next = dst_group; /* Segfault! */
|
||||
}
|
||||
|
||||
new_src_loc = smalloc(sizeof(SrcLoc_set));
|
||||
new_src_loc->loc_set = src_loc;
|
||||
new_src_loc->trans = new_trans; /* zapisujemy tylko raz (i tylko pierwszy element) */
|
||||
new_src_loc->next = NULL;
|
||||
|
||||
/*
|
||||
* zakladamy ze jesli nie udalo sie znalezc istniejacej grupy to
|
||||
* w lokacji docelowej tez nie ma informacji o tej lokacji zrodlowej
|
||||
*/
|
||||
if(!dst_loc->src_locs)
|
||||
dst_loc->src_locs = new_src_loc;
|
||||
else
|
||||
dst_loc->last_src_loc->next = new_src_loc;
|
||||
dst_loc->last_src_loc = new_src_loc;
|
||||
|
||||
}
|
||||
|
||||
if (!dst_group->trans)
|
||||
dst_group->trans = new_trans;
|
||||
else
|
||||
dst_group->last_trans->next = new_trans;
|
||||
dst_group->last_trans = new_trans;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pobieranie wskaznika na przejscia z lokacji src do lokacji dst
|
||||
*/
|
||||
ProdTrans_set *
|
||||
trans_get(ProdLoc_set *src, ProdLoc_set *dst)
|
||||
{
|
||||
DstLoc_set *cur_dstloc;
|
||||
|
||||
for (cur_dstloc = src->dst_locs; cur_dstloc; cur_dstloc = cur_dstloc->next)
|
||||
{
|
||||
if (cur_dstloc->loc_set == dst)
|
||||
{
|
||||
return cur_dstloc->trans;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sprawdzanie zawierania elementu zbioru lokacji produktowych
|
||||
* przez zbior lokacji zrodlowych
|
||||
*/
|
||||
bool
|
||||
ploc_in_src_locs(ProdLoc_set *prod_loc, SrcLoc_set *root)
|
||||
{
|
||||
SrcLoc_set *cur;
|
||||
|
||||
for (cur = root; cur; cur = cur->next)
|
||||
{
|
||||
if (cur->loc_set == prod_loc) return true; /* znaleziono */
|
||||
}
|
||||
|
||||
return false; /* nie znaleziono */
|
||||
}
|
||||
|
||||
void
|
||||
trloc_set_free(TrLoc_set **trloc)
|
||||
{
|
||||
idx_t i;
|
||||
TrLoc_set *tmp;
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
for (tmp = trloc[i]; tmp != NULL; tmp = tmp->next)
|
||||
free(tmp);
|
||||
|
||||
free(trloc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sprawdzanie czy lista ograniczen zawiera jakies rzeczywiste ograniczenia
|
||||
*/
|
||||
bool
|
||||
constr_nonempty(Constr *c)
|
||||
{
|
||||
if (c)
|
||||
/* lista jest niepusta */
|
||||
if (CONSTR_IS_TERM(c))
|
||||
/* pierwsze ogr. jest terminujace, czyli nic nie ma */
|
||||
return false;
|
||||
else
|
||||
/* jest przynajmniej jedno ogr. */
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wprowadzanie ograniczen z listy c do DBM-a p
|
||||
*/
|
||||
void
|
||||
constr2dbm(Aut_idx ai, DBM_elem *p, Constr *c)
|
||||
{
|
||||
if (!c) return;
|
||||
|
||||
for (; !CONSTR_IS_TERM(c); c++)
|
||||
{
|
||||
DBM_idx i, j;
|
||||
|
||||
i = prod_clock_idx2pidx(ai, c->l_clk);
|
||||
j = prod_clock_idx2pidx(ai, c->r_clk);
|
||||
|
||||
switch (c->rel)
|
||||
{
|
||||
case CONSTR_LE:
|
||||
dbm_constr_le(p, dbm_size, i, j, c->val);
|
||||
break;
|
||||
|
||||
case CONSTR_LT:
|
||||
dbm_constr_lt(p, dbm_size, i, j, c->val);
|
||||
break;
|
||||
|
||||
default:
|
||||
FERROR("Unknown relation");
|
||||
break;
|
||||
}
|
||||
|
||||
dbm_canon1(p, dbm_size, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Zbieranie z automatow skladowych zegarow z indeksami automatu produktowego
|
||||
*/
|
||||
void
|
||||
clocks_collect(ClockIdx_set **root, ClockIdx_set **cur, Aut_idx ai, Clock_idx *clks, Clock_idx nclks)
|
||||
{
|
||||
idx_t i;
|
||||
|
||||
for (i = 0; i < nclks; i++, clks++)
|
||||
{
|
||||
ClockIdx_set *n = smalloc(sizeof(ClockIdx_set));
|
||||
|
||||
n->idx = prod_clock_idx2pidx(ai, *clks);
|
||||
assert(n->idx > 0);
|
||||
n->next = NULL;
|
||||
|
||||
if (!*root)
|
||||
*root = n;
|
||||
else
|
||||
(*cur)->next = n;
|
||||
*cur = n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Zwalnianie pamieci zaalokowanej przez clocks_collect
|
||||
*/
|
||||
void
|
||||
colclocks_free(ClockIdx_set *elem)
|
||||
{
|
||||
ClockIdx_set *next;
|
||||
|
||||
while (elem)
|
||||
{
|
||||
next = elem->next;
|
||||
free(elem);
|
||||
elem = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pobieranie niezmiennika dla okreslonej lokacji produktowej w post. DBM.
|
||||
*/
|
||||
DBM_elem *
|
||||
prod_loc_inv(Loc_idx *ploc)
|
||||
{
|
||||
DBM_elem *p = NULL;
|
||||
idx_t i;
|
||||
|
||||
p = dbm_init(dbm_size);
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
constr2dbm(i, p, aut[i].loc[ploc[i]].inv);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pobieranie niezmiennika dla okreslonej lokacji produktowej w post. DBM.
|
||||
* Jesli nie ma ograniczen, to DBM == NULL.
|
||||
*/
|
||||
DBM_elem *
|
||||
prod_loc_inv0(Loc_idx *ploc)
|
||||
{
|
||||
DBM_elem *p = NULL;
|
||||
idx_t i;
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
Constr *cinv;
|
||||
|
||||
cinv = aut[i].loc[ploc[i]].inv;
|
||||
|
||||
/* DBM alokowany tylko jak jest co do niego wrzucic */
|
||||
if (!p && constr_nonempty(cinv)) p = dbm_init(dbm_size);
|
||||
|
||||
constr2dbm(i, p, cinv);
|
||||
}
|
||||
|
||||
return p; /* p == NULL jesli nie ma ograniczen */
|
||||
}
|
||||
|
||||
/*
|
||||
* Znajdowanie przejsc z okreslona akcja mozliwych z danej lokacji
|
||||
* produktowej wraz z lokacjami produktowymi do ktorych prowadza.
|
||||
*/
|
||||
ProdTrLoc_set *
|
||||
prod_loc_succ(Loc_idx *src_ploc, Act_idx a)
|
||||
{
|
||||
idx_t i, j;
|
||||
Trans_set *t;
|
||||
|
||||
TrLoc_set **trloc; /* posrednia struktura do ktorej bedziemy zbierac przejscia i lokacje docelowe */
|
||||
idx_t *ntrloc; /* liczniki odnalezionych przejsc w poszczegolnych automatach */
|
||||
|
||||
trloc = smalloc_zero(sizeof(TrLoc_set *)*naut);
|
||||
ntrloc = smalloc_zero(sizeof(idx_t)*naut);
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
if (aut[i].uact[a]) /* jesli akcja jest w zbiorze akcji automatu, to idziemy dalej */
|
||||
{
|
||||
|
||||
for (j = 0; j < aut[i].nloc; j++)
|
||||
{
|
||||
for (t = TRANS(aut[i].trans, aut[i].nloc, src_ploc[i], j);
|
||||
t != NULL; t = t->next)
|
||||
{
|
||||
|
||||
if (t->act == a) /* znalezlismy przejscie z poszukiwana akcja */
|
||||
{
|
||||
TrLoc_set *n;
|
||||
|
||||
ntrloc[i]++; /* znaleziono przejscie */
|
||||
|
||||
n = smalloc(sizeof(TrLoc_set));
|
||||
n->loc = j;
|
||||
n->trans = t;
|
||||
n->next = NULL;
|
||||
|
||||
if (!trloc[i])
|
||||
trloc[i] = n;
|
||||
else
|
||||
{
|
||||
TrLoc_set *last;
|
||||
for (last = trloc[i]; last->next != NULL; last = last->next);
|
||||
last->next = n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!ntrloc[i])
|
||||
{
|
||||
/* akcja jest niewykonalna, poniewaz i-ty automat ma ta akcje
|
||||
* w zbiorze swoich akcji, ale nie jest ona w nim umozliwiona.
|
||||
*/
|
||||
trloc_set_free(trloc);
|
||||
free(ntrloc);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ProdTrLoc_set *r = NULL, *r_cur = NULL;
|
||||
idx_t *idcs = smalloc(sizeof(idx_t)*naut);
|
||||
int k = 0;
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
if (ntrloc[i] > 0) idcs[i] = 1;
|
||||
else idcs[i] = 0;
|
||||
}
|
||||
|
||||
while (k >= 0)
|
||||
{
|
||||
Loc_idx *dst_ploc = prod_loc_copy(src_ploc);
|
||||
ProdTrLoc_set *n = smalloc(sizeof(ProdTrLoc_set));
|
||||
ClockIdx_set *clocks_cur = NULL;
|
||||
|
||||
n->act = a;
|
||||
n->guard = dbm_init(dbm_size);
|
||||
n->clocks = NULL; /* musi byc, bo inaczej clocks_cur bedzie brany pod uwage w clocks_collect */
|
||||
|
||||
for (i = 0; i < naut; i++)
|
||||
{
|
||||
|
||||
int depth = 0;
|
||||
TrLoc_set *trloc_tmp;
|
||||
|
||||
for (trloc_tmp = trloc[i]; trloc_tmp; trloc_tmp = trloc_tmp->next)
|
||||
{
|
||||
/* ten for wykonuje sie tylko jak cos sie zmienilo w i-tym automacie */
|
||||
|
||||
depth++;
|
||||
if (depth == idcs[i])
|
||||
{
|
||||
dst_ploc[i] = trloc_tmp->loc;
|
||||
constr2dbm(i, n->guard, trloc_tmp->trans->guard); /* wystarczy tylko dla trloc[i]? */
|
||||
/* optymalniej byloby dokonac kanonizacji po wniesieniu zmian do DBM z uwzglednieniem
|
||||
* ile zostalo zmodyfikowanych elementow (czasami dbm_canon1 nie oplaca sie), poniewaz
|
||||
* obecnie constr2dbm oblicza za kazdym razem PK co na pewno nie jest oplacalne jesli
|
||||
* modyfikacji jest tyle co dbm_size.
|
||||
*/
|
||||
clocks_collect(&(n->clocks), &clocks_cur, i, trloc_tmp->trans->clocks, trloc_tmp->trans->nclocks);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
n->loc = dst_ploc;
|
||||
n->next = NULL;
|
||||
|
||||
if (!r)
|
||||
r = n;
|
||||
else
|
||||
r_cur->next = n;
|
||||
r_cur = n;
|
||||
|
||||
for (k = naut - 1; k >= 0 && idcs[k] == ntrloc[k]; k--)
|
||||
{
|
||||
if (ntrloc[k] > 0) idcs[k] = 1;
|
||||
}
|
||||
|
||||
if (k >= 0) idcs[k]++;
|
||||
|
||||
}
|
||||
|
||||
free(idcs);
|
||||
trloc_set_free(trloc);
|
||||
free(ntrloc);
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Zwalniamy pamiec prtl i zwracamy kolejny element
|
||||
* (do wykorzystywania w petlach)
|
||||
*
|
||||
*/
|
||||
ProdTrLoc_set *
|
||||
prtl_free_getNext(ProdTrLoc_set *prtl)
|
||||
{
|
||||
ProdTrLoc_set *next;
|
||||
|
||||
next = prtl->next;
|
||||
free(prtl);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generowanie automatu pseudoproduktowego (do testow). Troche nasmiecone. Jesli ma zostac w kodzie, to
|
||||
* trzeba dokonac doglebnego przegladu.
|
||||
*/
|
||||
void
|
||||
prod_show(AutNet *an)
|
||||
{
|
||||
ProdLoc_set *waiting_root = NULL, *waiting_cur = NULL; /* _cur nie musi byc NULL (ale kompilator...) */
|
||||
ProdLoc_set *visited_root = NULL, *visited_cur = NULL;
|
||||
|
||||
Loc_idx *ploc_init;
|
||||
DBM_elem *ploc_init_inv;
|
||||
|
||||
net_init(an);
|
||||
|
||||
ploc_init = prod_loc_initial();
|
||||
ploc_init_inv = prod_loc_inv(ploc_init);
|
||||
|
||||
prod_loc_set_add(ploc_init, ploc_init_inv, &waiting_root, &waiting_cur);
|
||||
|
||||
while (waiting_root)
|
||||
{
|
||||
|
||||
ProdLoc_set *processed;
|
||||
bool *actions;
|
||||
idx_t i;
|
||||
|
||||
processed = prod_loc_set_raw_pick(&waiting_root);
|
||||
prod_loc_set_raw_add(processed, &visited_root, &visited_cur);
|
||||
|
||||
actions = prod_loc_acts(processed->loc);
|
||||
|
||||
printf("-------------------------------------------------------------\n");
|
||||
printf("Przejscia mozliwe z lokacji produktowej ");
|
||||
prod_loc_show(processed->loc); printf("\n");
|
||||
|
||||
for (i = 0; i < nact; i++)
|
||||
{
|
||||
if (actions[i])
|
||||
{
|
||||
ProdTrLoc_set *prtl, *prtl_tmp;
|
||||
prtl = prod_loc_succ(processed->loc, i);
|
||||
|
||||
for (prtl_tmp = prtl; prtl_tmp;)
|
||||
{
|
||||
printf("\n");
|
||||
printf("Akcja %s\n", get_act_name(act, i));
|
||||
printf("Guard:\n");
|
||||
dbm_print(prtl_tmp->guard, dbm_size);
|
||||
printf("Zegary do zresetowania: ");
|
||||
{
|
||||
ClockIdx_set *cur;
|
||||
for (cur = prtl_tmp->clocks; cur; cur = cur->next)
|
||||
{
|
||||
ProdClock pc;
|
||||
pc = prod_clock_pidx2idx(cur->idx);
|
||||
printf("%s(%s,%d) ", aut[pc.par_aut].name, get_clock_name(aut[pc.par_aut].clks, pc.par_idx), cur->idx);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("Do lokacji: ");
|
||||
prod_loc_show(prtl_tmp->loc); printf("\n");
|
||||
|
||||
if (!prod_loc_set_is_in(prtl_tmp->loc, waiting_root) && !prod_loc_set_is_in(prtl_tmp->loc, visited_root))
|
||||
{
|
||||
/* lokacji nie ma jeszcze ani w WAITING ani w VISITED, wiec moze ja dodamy... */
|
||||
DBM_elem *inv_guard;
|
||||
|
||||
inv_guard = dbm_intersection_cf(processed->inv, prtl_tmp->guard, dbm_size);
|
||||
if (!dbm_empty(inv_guard, dbm_size))
|
||||
{
|
||||
ClockIdx_set *cur;
|
||||
DBM_elem *prtl_tmp_locInv;
|
||||
|
||||
for (cur = prtl_tmp->clocks; cur; cur = cur->next)
|
||||
{
|
||||
dbm_reset(inv_guard, dbm_size, cur->idx);
|
||||
}
|
||||
/* przeciecie inv_guard (po resetach) z niezmiennikiem lokacji docelowej */
|
||||
prtl_tmp_locInv = prod_loc_inv(prtl_tmp->loc);
|
||||
dbm_intersection_cf_ip(inv_guard, prtl_tmp_locInv, dbm_size);
|
||||
if (!dbm_empty(inv_guard, dbm_size))
|
||||
{
|
||||
prod_loc_set_add(prtl_tmp->loc, prtl_tmp_locInv, &waiting_root, &waiting_cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbm_destroy(prtl_tmp_locInv);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mamy juz ta lokacje, wiec zwalniamy pamiec */
|
||||
free(prtl_tmp->loc);
|
||||
}
|
||||
|
||||
/* informacje z prod_loc_succ zostaly wykorzystane - zwalniamy pamiec */
|
||||
dbm_destroy(prtl_tmp->guard);
|
||||
colclocks_free(prtl_tmp->clocks);
|
||||
{
|
||||
ProdTrLoc_set *next;
|
||||
|
||||
next = prtl_tmp->next;
|
||||
free(prtl_tmp);
|
||||
prtl_tmp = next;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
free(actions); /* moze lepiej byloby pomyslec nad czyms wielokrotnego uzytku...?
|
||||
albo zastapic jakas lepsza struktura danych? */
|
||||
}
|
||||
|
||||
printf("------\n");
|
||||
prod_loc_set_show(visited_root);
|
||||
prod_loc_set_free(visited_root);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user