30 aprilie 2010
Heapsort
29 aprilie 2010
28 aprilie 2010
Fapte si reguli in Clips
Socketi "raw"
Socketii "raw", din familia de protocoale PF_PACKET sunt folositi pentru a receptiona sau trimite pachete "raw" direct la nivelul dispozitivului fizic (nivelul OSI 2). Sunt folositi pentru a implementa protocoale direct in user-space fie pentru a le testa fie pentru ca protocolul nu are rost sa fie implementat in kernel. Aceasta familie de protocoale pune la dispozitie doua tipuri de socketi:
- SOCK_RAW - pachetele sunt prezentate utilizatorului asa cum sunt primite de la device driver (i.e. cu tot cu headerul de nivel 2); de asemenea la trimiterea unui pachet printr-un socket de acest tip pachetele sunt trimise nemodificate astfel incat trebuie sa contina si headerul
- SOCK_DGRAM - pachetele sunt prezentate utilizatorului fara headerul de nivel 2; pachetelor trimise pritr-un socket de acest tip li se va adauga headerul de nivel 2; practic utilizatorul vede doar continul pachetului
Socketii "raw" sunt creati la fel ca si socketii normali cu apelul de sistem socket:
packet_socket = socket(PF_PACKET, int socket_type, int protocol);unde socket_type poate fi SOCK_RAW sau SOCK_DGRAM iar protocol una din constantele definite in linux/if_ether.
Aplicatia de mai jos "asculta" toate pachetele care ajung in calculator si printeaza continutul lor, fie ca ii sunt adresate calculatorului sau nu.
#include "netinet/in.h"
#include "stdio.h"
#include "unistd.h"
#include "netpacket/packet.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "net/if.h"
#include "stdlib.h"
#include "sys/ioctl.h"
#include "string.h"
#include "net/if_arp.h"
#include "linux/if_ether.h"
int start(int proto) //eth_p_ip
{
int fd = socket(PF_PACKET, SOCK_DGRAM, htons(proto));
if (fd < 0)
{
perror("can't create protocol socket:");
return -1;
}
return fd;
}
int bind_socket(int fd, int interface, int protocol)
{
struct sockaddr_ll sock_info;
memset(&sock_info, 0, sizeof(sock_info));
sock_info.sll_family = AF_PACKET;
sock_info.sll_protocol = htons(protocol);
sock_info.sll_ifindex = interface;
if (bind(fd, (struct sockaddr *)&sock_info, sizeof(sock_info)))
{
perror("can't bind socket to i/f %m\n");
return -1;
}
return 0;
}
int find_interface(char *name)
{
struct ifreq ifr;
int iindex = 1;
int sock = socket(PF_PACKET, SOCK_RAW, 0);
ifr.ifr_ifindex = iindex;
while (ioctl(sock, SIOCGIFNAME, &ifr) == 0)
{
if (strcmp(ifr.ifr_name, name) == 0)
{
close(sock);
return iindex;
}
ifr.ifr_ifindex = ++iindex;
}
close(sock);
return -1;
}
int set_promisc(int fd, int ifn)
{
struct packet_mreq pack_info;
pack_info.mr_type = PACKET_MR_PROMISC;
pack_info.mr_alen = 0;
pack_info.mr_ifindex = ifn;
if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &pack_info, sizeof(pack_info)))
{
printf("can't set promiscous mode\n");
return -1;
}
return 0;
}
int recv_packet(int sockfd, int *ifn, unsigned char macaddr[], unsigned char *data, int maxlen)
{
struct msghdr msg;
struct iovec iov;
struct sockaddr_ll sock_info;
int len;
memset(&msg, 0, sizeof(msg));
msg.msg_name = &sock_info;
msg.msg_namelen = sizeof(sock_info);
msg.msg_iovlen = 1;
msg.msg_iov = &iov;
iov.iov_len = maxlen;
iov.iov_base = data;
len = recvmsg(sockfd, &msg, 0);
*ifn = sock_info.sll_ifindex;
memcpy(macaddr, sock_info.sll_addr, 6);
return len;
}
int main()
{
int sockfd = start(ETH_P_IP);
int interface = find_interface("eth0");
int b = bind_socket(sockfd, interface, ETH_P_IP);
unsigned char *macaddr=(unsigned char *)malloc(256*sizeof(unsigned char)), *data= (unsigned char *)malloc(256*sizeof(unsigned char));
while (1) {
int promise = set_promisc(sockfd, interface);
int recv = recv_packet(sockfd, &interface, macaddr, data, 256), i;
for(i=0; i < 256;i++)
printf("%c",data[i]);
printf("\n");
}
return 0;
}
Nota
Fisierul va fi executat din pozitie de admin (in Linux: sudo su)
26 aprilie 2010
Makefile pentru C
build:
gcc [nume_fisiere] -o [nume_fis_exe]
clean:
rm [nume_fis_exe]
rm -f *~ core
16 aprilie 2010
Hash tables
Se mai verifica si daca o anumita multime A poate fi acoperita de multimi de un anumit cardinal din Hash table.
#include "stdio.h"
#include "stdlib.h"
typedef struct lista {
int * elem;
int card;
struct lista *leg;
} * Hash;
void insert (int * multime,int card, Hash * L) {
Hash ins = (Hash)malloc(sizeof(struct lista));
ins->elem = multime;
ins->leg = NULL;
ins->card = card;
if (*L == NULL) {
*L = ins; return ; }
else {
Hash aux = *L;
while (aux->leg !=NULL)
aux= aux->leg;
aux->leg = ins; }
}
void printvect (int * v,int n) {
int i;
for(i=0;i < n;i++)
printf( "%d ", v[i]);
printf("\n");
}
void afisare (Hash h, int i) {
Hash aux;
if (h != NULL) {
aux = h;
printf("h[%d] = \n",i);
while (aux != NULL)
{
printvect(aux->elem,aux->card);
aux = aux->leg;
}
}
}
int exista (Hash h, int elem) {
if(h==NULL)
return 0;
Hash aux = h;
int ok =0;
while (aux) {
int c = aux->card, i;
for(i=0; i < c ; i++)
if (aux->elem[i]==elem) ok = 1;
if(ok ==1)
return 1;
aux = aux->leg;
}
return 0;
}
int main() {
Hash *h;
FILE * f = fopen("in", "r");
int n,i;
fscanf(f, "%d", &n);
h = (Hash *)malloc (n*sizeof(struct lista));
for(i=0; i < n ; i++)
h[i]= NULL;
while(!feof(f)) {
int m;
fscanf(f, "%d", &m);
int * v = (int *)malloc(m*sizeof(int));
for(i=0; i < m ;i++)
fscanf(f,"%d", &v[i]);
insert (v,m, &h[m]);
}
for(i=0; i < n ; i++)
afisare(h[i],i);
// multimea A de cardinal k poate fi acoperita de multimi de card. p din Hash table?
printf("\n\n");
FILE * ff = fopen ("in2", "r");
int *A, k,p;
fscanf(ff,"%d", &k);
A = (int *)malloc(k*sizeof(int));
for(i=0; i < k ;i++)
fscanf(ff,"%d", &A[i]);
fscanf(ff,"%d", &p);
int ok = 1;
for(i=0; i < k && ok; i++)
if(!exista(h[p], A[i]))
ok = 0;
if (ok==1) {
printf("da\n");
afisare(h[p],p);
}
else printf("nu\n");
return 0;
}
Functii in Haskell
if a == b && a == c && b == c then True
else False
allDifferent a b c =
if a /= b && a /= c && b /= c then True
else False
howManyEqual a b c
| allEqual a b c = 3
| allDifferent a b c = 0
| otherwise = 2
-- calculeaza sirul fibonacci
fibonacci n
| n == 0 = 1
| n == 1 = 1
| otherwise = fibonacci(n -1) + fibonacci(n - 2)
-- creeaza o pereche ordonata
orderTuple a b
| a > b =(b, a)
| otherwise = (a, b)
-- daca un element apartine listei
member x [] = False
member x (h:t) =
if (h == x) then True
else member x t
-- produs cartezian a doua liste
cartProd a b = [(x,y) | x<-a, y<-b]
-- applies f to every element of list l and returns the new list
functie x = x+2
mapp f [a] = [f a]
mapp f (a:l) =
(f a):(mapp f l)
-- returns a list containing only the elements from list l, satisfying the predicate p
predicat x = x > 2
filterr p (a:l) =
if (p a) then a:(filter p l)
else filter p l
{- reduces a list to a value, going from left to right: applies f to the seed and the first list element,
then applies f to the result and the second element etc -}
f x y= x+y
foldleft f seed [] = seed
foldleft f seed l =
seed + foldleft f (head l) (tail l)
{- computes the sum of list elements, using foldleft -}
sumList l = foldleft f 0 l
{- reduces a list to a value, going from right to left: first computation is (f last_element seed) -}
foldright f elem [] = elem
foldright f seed l =
foldright f (head l) (tail l) + seed
{- returns the number of occurences of val in a, b, c -}
valOccurs val a b c
| a==val = 1+(valOccurs val (1-a) b c)
| b==val = 1+(valOccurs val a (1-b) c)
| c==val = 1+(valOccurs val a b (1-c))
| otherwise = 0
{- returns an ordered triple based on a, b, c -}
orderTriple a b c =
if (a<=b && b<=c) then (a,b,c)
else if (b<=a && a<=c) then (b,a,c)
else if (a<=c && c<=b) then (a,c,b)
else if(b<=c && c<=a) then (b,c,a)
else if (c<=a && a<=b) then (c,a,b)
else (c,b,a)
{- returns the minimum in a list -}
minim a b =
if (a < b) then a
else b
minVal (a:[]) = a
minVal (a:l) =
minim a (minVal l)
{- returns True if all list elements are equal -}
allEq [a] = True
allEq (a:l) =
if (a/= (head l)) then False
else allEq l
{- returns True if list is sorted ascending -}
ascOrd [a] = True
ascOrd (a:l) =
if (a > (head l)) then False
else ascOrd l
{- returns True if list p is a prefix of list l -}
startsWith [] lista = True
startsWith lista [] = False
startsWith p l =
if ((head p) /= (head l)) then False
else startsWith (tail p) (tail l)
{- removes the prefix p from list l -}
del p l =
if (p==[] && l /= []) then l
else del (tail p) (tail l)
{- substitutes all occurences of element old with element new in the list l -}
subst old new [] = []
subst old new (a:l) =
if (a == old) then new:(subst old new l)
else a:(subst old new l)
14 aprilie 2010
Tipuri de date in Haskell
data Natural =
Zero |
Succ Natural
deriving Show
--fct pt predecesor
prede (Succ n) = n
-- egalitate
equal Zero Zero = True
equal (Succ n) Zero = False
equal Zero (Succ n) = False
equal m n =
if equal (prede m) (prede n)== True then True
else False
-- aduna 2 nr naturale
add n Zero = n
add m n =
Succ (add m (prede n))
-- diferenta a doua nr
subs n Zero = n
subs m n =
if (equal m n) then Zero
else prede (subs m ( prede n))
-- a mai mare ca b
gt (Succ n) Zero = True
gt Zero (Succ n) = False
gt m n =
if equal m n then False
else gt m n
-- a mai mic ca b
lt (Succ n) Zero = False
lt Zero (Succ n) = True
lt m n =
if equal m n then False
else lt m n
-- inmultire
mult n Zero = Zero
mult Zero n = Zero
mult (Succ n) (Succ Zero) = (Succ n)
mult (Succ Zero) (Succ n) = (Succ n)
mult m n =
add (mult (prede m) n) n
-- tipul List
data List a =
Empty |
Cons a (List a)
deriving Show
-- lungimea unei liste
lung Empty = 0
lung (Cons x lista) = 1 + lung lista
-- concatenare
conc Empty l = l
conc (Cons x lista) l =
Cons x (conc lista l)
-- tipul Tree, arbore binar de cautare
data Tree a =
Null |
Frunza a |
Nod (Tree a) a (Tree a)
deriving Show
-- inserare intr-un arbore binar
insert t Null = Frunza t
insert t (Frunza a) =
if (t < a) then Nod (Frunza t) a Null
else Nod Null a (Frunza t)
insert x (Nod left t right) =
if (x < t) then Nod (insert x left) t right
else Nod left t (insert x right)
-- construieste un arbore binar de cautare pornind de la o lista
constr Empty = Null
constr (Cons a lista) =
insert a (constr lista)
-- numara elem din arbore
numar Null = 0
numar (Frunza a) = 1
numar (Nod left x right) = 1 + numar left + numar right
-- adancimea arborelui
maxim a b =
if (a < b) then b
else a
adan Null = 0
adan (Frunza x) = 1
adan (Nod left x right) = 1 + maxim (adan left) (adan right)
-- o lista cu elem din arborele parcurs inordine - SRD (lista sortata)
srd (Frunza a) = Cons a Empty
srd Null = Empty
srd (Nod left a right) =
conc (srd left) (Cons a (srd right))
DFS si sortare topologica
Pentru fiecare nod se vor retine: timpul descoperirii, timpul finalizarii, parintele si culoarea.
Algoritmul de explorare DFS nu este nici complet (cautare pe un subarbore infinit) nici optimal (nu gaseste nodul cu adancimea minima).
Dandu-se un graf orientat aciclic, sortarea topologica realizeaza o aranjare liniara nodurilor in functie de muchiile dintre ele. Orientarea muchiilor corespunde unei relatii de ordine de la nodul sursa catre cel destinatie. Astfel, daca (u,v) este una dintre muchiile grafului, u trebuie sa apara inaintea lui v in insiruire. Daca graful ar fi ciclic, nu ar putea exista o astfel de insiruire (nu se poate stabili o ordine intre nodurile care alcatuiesc un ciclu).
Sunt doi algoritmi cunoscuti pentru sortarea topologica: algoritmul bazat pe DFS (parcurgere DFS pentru determinarea timpilor si sortare descrescatoare in functie de timpul de finalizare) un alt algoritm este cel descris de Kahn.
Programul de mai jos realizeaza o parcurgere DFS si o sortare topologica bazata pe aceasta a unui graf citit dintr-un fisier (dat ca liste de adiacenta).
#include "stdio.h"
#include "stdlib.h"
#include "assert.h"
struct Nod
{
int val;
int nrVecini;
int * vecini;
int culoare;
int parinte;
int tDescoperire;
int tFinal;
};
int n;
struct Nod * graf;
/* citeste lista de adiacenta din fisier */
void readData()
{
FILE * f;
int i, j;
f = fopen( "in2.txt","r" );
assert( f );
fscanf( f, "%d", &n );
graf = ( struct Nod * ) malloc ( n * sizeof( struct Nod ) );
for ( i = 0; i < n; ++i ) {
graf[i].val = i;
fscanf( f, "%d", &graf[i].nrVecini );
graf[i].vecini = ( int * ) malloc ( graf[i].nrVecini * sizeof ( int ) );
for ( j = 0; j < graf[i].nrVecini; ++j )
fscanf( f, "%d", &graf[i].vecini[j] );
graf[i].parinte = -1;
graf[i].culoare = 0;
graf[i].tDescoperire = -1;
graf[i].tFinal = -1;
}
fclose( f );
}
/* afisarea timpilor din alg DFS*/
void printTimpi()
{
int i;
printf( "\n" );
for ( i = 0; i < n; ++i )
printf ( "Nod %d: descoperit la t=%d, explorat la t=%d \n", i, graf[i].tDescoperire, graf[i].tFinal );
printf( "\n" );
}
int timp = 0;
/* parcurgere DFS a grafului */
void explorare(int u) {
graf[u].tDescoperire = timp++;
graf[u].culoare = 1;
int j;
for(j = 0 ; j < graf[u].nrVecini ; j++) {
int x = graf[u].vecini[j];
if(graf[x].culoare ==0) {
graf[x].parinte = u;
explorare(x);
}
}
graf[u].culoare = 2;
graf[u].tFinal = timp++;
}
void DFS ()
{
int i;
for (i=0; i < n ; i++)
if(graf[i].culoare == 0)
explorare(i);
}
/* sortare topologica */
void topSort()
{
int ok = 0,i,j;
struct Nod aux;
while (ok == 0) {
ok = 1;
for(i=0; i < n-1;i++)
if(graf[i].tFinal < graf[i+1].tFinal) {
ok = 0; aux = graf[i]; graf[i]=graf[i+1]; graf[i+1]=aux; }
}
}
int main(void){
int i;
//incarca graful din fisier
readData();
//parcurgere BFS
DFS();
//afisarea timpilor
printTimpi();
//sortare topologica
topSort();
printf( "Sortare topologoca: " );
for ( i = 0; i < n; ++i )
printf ( "%d ", graf[i].val );
printf("\n");
for( i = 0; i < graf[i].nrVecini; ++i )
free(graf[i].vecini);
free(graf);
return 0;
}
BFS intr-un graf
BFS depinde de nodul de start. Plecand dintr-un nod se va parcurge doar componenta conexa din care acesta face parte. Pentru grafuri cu mai multe componente conexe se vor obtine mai multi arbori de acoperire.
In urma aplicarii algoritmului BFS asupra fiecarei componente conexe a grafului, se obtine un arbore de acoperire (prin eliminarea muchiilor pe care nu le folosim la parcurgere). Pentru a putea reconstitui acest arbore, se pastreaza pentru fiecare nod dat identitatea parintelui sau. In cazul in care nu exista o functie de cost asociata muchiilor, BFS va determina si drumurile minime de la radacina la oricare
nod.
Pentru implementarea BFS se foloseste o coada. In momentul adaugarii in coada, un nod trebuie colorat gri (a fost descoperit si urmeaza sa fie prelucrat).
Algoritmul de explorare BFS este complet si optimal.
#include "stdio.h"
#include "stdlib.h"
#include "assert.h"
#include "queue.h"
#define START 0
#define FINISH 2
#define INF 10000
struct Nod
{
int nrVecini;
int * vecini;
int culoare;
int parinte;
};
int n;
struct Nod * graf;
/* citeste lista de adiacenta din fisier */
void readData()
{
FILE * f;
int i, j;
f = fopen( "in1.txt","r" );
assert( f );
fscanf( f, "%d", &n );
graf = ( struct Nod * ) malloc ( n * sizeof( struct Nod ) );
for ( i = 0; i < n; ++i ) {
fscanf( f, "%d", &graf[i].nrVecini );
graf[i].vecini = ( int * ) malloc ( graf[i].nrVecini * sizeof ( int ) );
for ( j = 0; j < graf[i].nrVecini; ++j )
fscanf( f, "%d", &graf[i].vecini[j] );
graf[i].parinte = -1;
graf[i].culoare = 0;
}
fclose( f );
}
void printRoad()
{
int aux = FINISH;
printf( "Drumul de la finish la start: " );
while ( aux != START ) {
printf ( "%d ", aux );
if ( graf[aux].parinte>=0 ) {
aux = graf[aux].parinte;
} else {
printf("\nEroare. nu se cunoaste parintele nodului %d\n", aux );
return;
}
}
printf ( "%d\n", aux );
}
/* parcurgere BFS a grafului, plecand din nodul start */
void BFS ( int start )
{
int *dist =(int *)malloc(n*sizeof(int));
int i;
for (i=0; i < n; i++)
dist[i] = INF;
dist[start] = 0;
graf[start].culoare = 1;// gri
Queue Q = NULL;
int j;
enqueue (&Q, &start);
while (size(Q) > 0) {
i = *(int *)Front(Q);
for(j=0; j < graf[i].nrVecini; j++) {
int *x = (int *)malloc(sizeof(int));
*x = graf[i].vecini[j];
if(graf[*x].culoare == 0) { //alb
dist[*x]=dist[i]+1;
graf[*x].parinte = i;
graf[*x].culoare = 1; // gri
enqueue(&Q, x);
free (x);
}
}
graf[i].culoare = 2; //negru
dequeue (&Q);
}
printf("start %d finish %d \n", START, FINISH);
printf("distanta este %d\n", dist[FINISH]);
}
int main(void){
int i;
//incarca graful din fisier
readData();
//parcurgere BFS
BFS( START );
//afisarea nodurilor dintre finish si start
printRoad();
for( i = 0; i < graf[i].nrVecini; ++i )
free(graf[i].vecini);
free(graf);
return 0;
}
Algoritmi de dirijare
Problema dirijarii apare la nivelul retea, si consta in a determina calea pe care o vor parcurge pachetele de la calculatorul sursa la calculatorul destinatie. Software-ul nivelului retea trebuie sa asigure desfasurarea a doua procese distincte:
- retransmitere (forwarding): ceea ce se intampla cand un pachet ajunge la ruter, si acesta trebuie sa stabileasca, prin consultarea unei tabele de rutare, linia de iesire pe care va transmite pachetul mai departe
- dirijare (routing): este procesul de construire si actualizare a tabelei de rutare - adica de stabilire a cailor pe care vor fi transmise pachetele
Referitor la algoritmii ce tin de procesul de dirijare, putem distinge doua categorii de algoritmi: algoritmi neadaptivi (ce realizeaza o dirijare statica - toate rutele sunt determinate initial si nu se tine cont de modificarile ulterioare de trafic si topologie ce apar in retea) si algorimi adaptivi (rutele sunt modificate ca urmare a schimbarilor de topologie si de trafic din retea).
Dintre algoritmii neadaptivi fac parte:
- dirijarea pe calea cea mai scurta (shortest path routing): subreteaua este reprezentata ca un graf, in care ruterele sunt noduri, si se aplica un algoritm (de exemplu Dijkstra) pentru a determina caile cele mai scurte dintre noduri; se pot folosi diverse metrici, cum ar fi numarul de rute intermediare, distanta geografica, intarzierile medii de transmisie
- inundarea (flooding): ruterul trimite fiecare pachet receptionat pe toate liniile de iesire, in afara de cea pe care a venit pachetul; varianta: inundarea selectiva (selective flooding)
Algoritmii adaptivi cel mai des utilizati sunt:
- dirijarea cu vectori distanta (distance vector routing): fiecare ruter mentine o tabela cu calea cea mai buna pentru fiecare destinatie si linia de iesire corespunzatoare acestei cai; tabelele sunt actualizate pe baza informatiilor primite de la celelalte rutere
- dirijarea folosind starea legaturilor (link state routing): fiecare router determina costurile asociate cailor catre vecini, apoi trimite aceste informatii in toata subreteaua; dupa schimburile de informatii, fiecare ruter are informatii complete despre graf si poate determina caile minime
Exemple de protocoale de dirijare:
- RIP (Routing Internet Protocol) - utilizeaza algoritmul distance vector
- OSPF (Open Shortest Path First Protocol) - utilizeaza algoritmul link state
- BGP (Border Gateway Protocol)
Programul de mai jos citeste dintr-un fisier un numar n reprezentand dimensiunea unei matrici de adiacenta a unui graf cu nodurile retelei, precum si aceasta matrice. Initial creeaza o tabela de rutare pentru fiecare nod, care contine informatii despre toate nodurile retelei, sub forma : Destinatar , Cost (=valoarea asociata muchiei dintre acel nod si destinatar), Next_Hop (=nodul urmator de urmat pentru a ajunge la destinatar). Apoi, pentru fiecare nod se vor actualiza informatiile despre celelalte noduri combinand informatiile gasite in fiecare tabela de rutare cercetata.
#include "stdio.h"
#include "stdlib.h"
#define INF 1000
int **a, n;
typedef struct tabela {
int *dest;
int *cost;
int *next_hop;
} Tabela;
void printTabela(Tabela t) {
int i;
for(i=0; i < n; i++)
printf("%d\t%d\t%d \n", t.dest[i], t.cost[i], t.next_hop[i] );
}
int find_dest(Tabela t, int poz) { // prima dest incepand cu poz
int i=poz;
while(t.cost[i] == INF && i<=n-1)
i++;
if (i<=n-1)
return t.dest[i];
return -1; // nu a gasit
}
int main () {
FILE * f = fopen ("in", "r");
fscanf(f, "%d",&n);
int i,j,k;
a = (int **)malloc(n*sizeof(int));
for(i=0; i < n ; i++)
a[i] = (int *)malloc(n*sizeof(int));
for(i=0; i < n ; i++)
for(j=0; j < n ; j++)
fscanf(f, "%d", &a[i][j]);
Tabela * tab = (struct tabela *)malloc(sizeof(struct tabela)*n);
for(i=0; i < n ; i++) {
tab[i].dest = (int *)malloc(n*sizeof(int));
tab[i].cost = (int *)malloc(n*sizeof(int));
tab[i].next_hop = (int *)malloc(n*sizeof(int));
}
// constructia tabelei in forma initiala
for (i=0; i < n ; i++) { // pt fiecare tabela
for(j=0; j < n ; j++)
if (a[i][j]) {
tab[i].dest[j] = j;
if(i!=j)
tab[i].cost[j] = 1;
else
tab[i].cost[j] = 0;
tab[i].next_hop[j] = j;
}
else {
tab[i].dest[j] = j;
tab[i].cost[j] = INF;
tab[i].next_hop[j] = -1;
}
}
printf("Tabela 5 inainte de aplicarea algoritmului:\n");
printTabela(tab[5]); // printam un anumit nod
for(i=0; i < n ; i++) // pt fiecare tabela
for(j=0; j < n ; j++) { // pt fiecare destinatie din tabela
k = find_dest(tab[j],0);
while(k!=-1) {
if (tab[i].cost[k] > tab[j].cost[k] + tab[i].cost[j]) {
tab[i].cost[k] = tab[j].cost[k] + tab[i].cost[j];
tab[i].next_hop[k] = tab[j].dest[j];
}
k = find_dest(tab[j],k+1);
}
}
printf("Tabela finala 5 cu drumuri optime:\n");
printTabela(tab[5]);
return 0;
}
08 aprilie 2010
Purificarea retelelor Petri
In procesul de modelare a protocoalelor folosind RP, pot aparea retele impure. De exemplu, o tranzitie impura t are un loc de intrare l, care este simultan nod de iesire. Pentru o RP pura niciun loc nu este intrare si iesire a aceleiasi tranzitii. Se demonstreaza ca orice RP impura poate fi transformata intr-o RP pura prin reducere. Reducerea ei se face astfel:
- se suprima arcele (l, t) si (t, l)
- se suprima t daca ea devine izolata
Urmatorul program indeplineste urmatoarele functii:
- isi creeaza un exemplu de retea Petri folosind locuri si tranzitii
- verifica daca reteaua contine impuritati;
- aplica reducerea specificata asupra fiecarei tranzitii impure;
- in final printeaza reteaua purificata
#################################
#include"stdio.h"
typedef struct {
int pre[100];
int post[100];
int Npre,Npost;
} tran;
int main() {
tran t[6];
t[1].Npre=2;
t[1].Npost=2;
t[1].post[0]=1;
t[1].post[1]=2;
t[1].pre[0]=1;
t[1].pre[1]=2;
t[2].Npre=3;
t[2].Npost=1;
t[2].post[0]=3;
t[2].pre[2]=3;
t[2].pre[0]=1;
t[2].pre[1]=2;
t[3].Npre=1;
t[3].Npost=1;
t[3].post[0]=1;
t[3].pre[0]=3;
t[4].Npre=1;
t[4].Npost=1;
t[4].post[0]=2;
t[4].pre[0]=3;
t[5].Npre=1;
t[5].Npost=1;
t[5].post[0]=3;
t[5].pre[0]=3;
int n=5,ok=1,i,k,l;
do {
ok=1;
for(i=1;i<=n;i++)
for(k=0;k<=t[i].Npre-1 ; k++)
for(l=0; l<=t[i].Npost-1; l++)
if((t[i].pre[k]==t[i].post[l]) && (t[i].pre[k]!=0)) // daca a gasit tranzitie impura
{
ok=0;
t[i].pre[k]=t[i].post[l]=0; // purifica
break;
}
} while(ok==0);
for(i=1;i<=n;i++) {
printf("\nT%d:\nPre:",i);
for(k=0;k<=t[i].Npre-1;k++)
printf("%d ",t[i].pre[k]);
printf("\nPost:");
for(k=0; k<=t[i].Npost-1 ; k++)
printf("%d ",t[i].post[k]);
}
return 0;
}