Sunteți pe pagina 1din 17

Universitatea din Bucuresti Facultatea de Matematica - Informatica Specializarea Tehnologia Informatiei

PROIECT

2012

Jerca Vlad Anul I Grupa 152

Universitatea din Bucuresti Facultatea de Matematica - Informatica Specializarea Tehnologia Informatiei

Algoritmul Quine - McCluskey pentru calcularea implicantilor primi (varianta zecimala)

2012

Jerca Vlad Anul I Grupa 152

CUPRINS

1. Algoritmul QMC (varianta zecimala) ..........................................................4 2. Exemple....................................................................................................5 cazul in care avem implicanti primi .....................................................5 cazul in care cubul este complet .........................................................6 3. Implementarea algoritmului ( C++ ) ........................................................... 7 4. Executarea programului ( pentru exemplul a si b ) ................................... 15 5. Bibliografie ............................................................................................. 17

1. Algoritmul QMC (varianta zecimala)


Pasul 1. Se porneste de la forma canonica SOP; se folosesc indicatorii zecimali ai mintermenilor pentru care functia are valoarea 1. Pasul 2. Se scrie echivalentul binar pentru fiecare indicator zecimal. Pasul 3. Se determina greutatea fiecarei combinatii binare. Pasul 4. Se ordoneaza indicatorii zecimali in ordinea crescatoare a greutatii. Pot exista (n+1) grupuri notate S0, S1,..., Sn. Pasul 5 . Se compara fiecare indicator zecimal din gruparea S0 cu toti indicatorii zecimali din grupul S1. Compararea se face prin scadere zecimala a indicatorilor zecimali ai grupurilor S1 si S0 ; doi indicatori zecimali se unesc numai daca diferenta este o putere a lui doi, adica 1,2,4,8,... Pasul 6. Noul termen este format prin enumerarea in ordine crescatoare a indicatorilor zecimali urmata de diferenta zecimala ; (i, j, (j-i)). Acest nou termen este plasat intr-o coloana noua, care se numeste cuplarea 1. Pasul 7. Se marcheaza termenii cuplati. Pasul 8. Dupa ce se realizeaza compararea grupurilor Si si Si+1 se deseneaza o linie in coloana 1. Pasul 9. Se procedeaza similar pana la ultima comparatie intre grupurile Sn-1 si Sn. Pasul 10. Termenii care raman nemarcati sunt extrasi pentru a forma spatiul Z0. Pasul 11. Se compara doua grupuri consecutive din cuplarea 1. Comparatia este permisa numai daca diferenta este aceeasi (valoarea dintre paranteze este aceeasi ); unirea este posibila numai daca diferenta, prima componenta a termenilor este putere a lui 2 (1,4,8, ). Pasul 12. Termenii uniti sunt marcati. Pasul 13. Termenul nou creat este plasat intr-o coloana noua, numita cuplarea 2. Pasul 14. In urma finalizarii procesului de comparare a celor doua grupuri se deseneaza o linie separata in noua coloana. Pasul 15. Procesul continua identic pana cand nu mai exista posibilitatea ca noi termeni sa fie generati (pentru a forma noi cuburi); daca exista doi sau mai multi termeni identici, folosim teorema de idempotenta si oprim numai unul dintre acestia. Pasul 16. Se determina Z ca fiind reuniunea spatiilor Zi, de termeni nemarcati Z = UZi. Pasul 17. Se decodifica spatiul cuburilor prime: a) Se scrie echivalentul binar al primelor numere ale grupului b) Se scriu exponentii puterii lui doi pentru valorile din paranteze. c) Se taie pozitiile corespunzatoare valorilor exponentilor determinati la pasul b d) Se foloseste notatia exponentiala directa pentru pozitiile ramase. 4

2. Exemple
a) cazul in care avem implicanti primi f(abcd) = ( 0, 1, 2, 4, 6, 8, 14, 15 )

CUPLAREA 0: S0: 0

S1: 1 2 4 8 S2: 6 S3: 14 S4: 15

CUPLAREA 1: S0: 0, 1 (1) 0, 2 (2) 0, 4 (4) 0, 8 (8) S1: 2, 6 (4) 4, 6 (2) S2: 6,14 (8) S3: 14,15 (1) -----------------

CUPLAREA 2: S0: 0, 2, 4, 6 (2,4)

S1: -

S2: ---------------------------------

Z(f) = { 0, 1 (1); 0, 8 (8); 6,14 (8); 14,15 (1); 0, 2, 4, 6 (2,4); }

Decodificare: f(abcd) = ~a~b~c + ~b~c~d + bc~d + abc + ~a~d

b) cazul in care cubul este complet f(abc) = ( 0, 1, 2, 3, 4, 5, 6, 7 )

CUPLAREA 0: S0: 0 S1: 1 2 4 S1: S0:

CUPLAREA 1: S0: 0, 1 (1) 0, 2 (2) 0, 4 (4) S1: 1, 3 (2) 1, 5 (4) 2, 3 (1) 2, 6 (4) 4, 5 (1) 4, 6 (2) S2: 3, 7 (4) 5, 7 (2) 6, 7 (1) -----------

CUPLAREA 2: 0, 1, 2, 3 (1,2) 0, 1, 4, 5 (1,4) 0, 2, 4, 6 (2,4) 1, 3, 5, 7 (2,4) 2, 3, 6, 7 (1,4) 4, 5, 6, 7 (1,2)

CUPLAREA 3: S0: 0, 1, 2, 3, 4, 5, 6, 7 (1,2,4)

------------------

S2: 3 5 6 S3: 7

-----------------------------------

-----------------------------------

CUB COMPLET !

3. Implementarea algoritmului ( C ++ )

#include<iostream> #include<string> #include<vector> #include<algorithm> #include<iomanip> #include<math.h> using namespace std; // afisare implicanti primi Z(f) void afisez(const vector<int> &elem, const int &pas, char c) { int line = int(pow(2.0, pas)); for(unsigned i=0; i<elem.size(); i++) { cout<<setw(2)<<right<<elem[i]; if(!((i+1)%line)) { if(pas>0) { cout<< (; for(int k=1; k<line; k*=2) { cout<<elem[k+i-line+1]-elem[i-line+1]; if(k == line/2) cout<<); else cout<<,; } } if(c == c) cout<<endl; if(c == i) cout<<; ; } else cout<<,; } if(c == c) cout<<endl; }

// afisare mintermeni void afisez(const vector<int> &elem, const int &ordin) { cout<<f(; for(int i=0; i<ordin; i++) cout<<char(a+i); cout<<) = <<char(228)<<( ; if(!elem.empty()) for(unsigned i=0; i<elem.size(); i++) { cout<<setw(2)<<right<<elem[i]; if(i == elem.size()-1) cout<< )<<endl; else cout<<, ; } } // citire mintermeni void citesc(vector<int> &elem, int &ordin) { string min; int sizeBefore, sizeAfter; cout<<Introduceti mintermenii: ; getline(cin, min); while(!min.empty()) { sizeBefore = min.size(); elem.push_back(atoi( min.c_str() )); min.erase(0,min.find( )+1); sizeAfter = min.size(); if(sizeBefore==sizeAfter) min.clear(); } sort(elem.begin(), elem.end()); int max = elem[elem.size()-1]; if(max == 0) ordin = 1; else while(max) { ordin++; max = max>>1; } system(cls); } 8

// nr de valori 1 pe biti int nrUnu(int nr) { int contor = 0; while(nr>0) { if(nr%2 == 1) contor++; nr = nr>>1; } return contor; } // incarcarea Cuplarii 0 void cuplare(vector<int> **&S, vector<int> &minT, const int &ordin) { S = new vector<int>*[ordin+1]; for(int i=0; i<=ordin; i++) S[i] = new vector<int>[ordin+1]; for(unsigned i=0; i<minT.size(); i++) S[0][nrUnu(minT[i])].push_back(minT[i]); minT.clear(); } // incarcarea pentru cuplarile 1...n void cuplare(const vector<int> &elemA, const vector<int> &elemB, vector<int> &cuplare, int pas) { int cresc = int(pow(2.0, pas-1)); for(unsigned i=0; i<elemA.size(); i+=cresc) for(unsigned j=0; j<elemB.size(); j+=cresc) { char seCupl = 0; for(int k=1; k<cresc; k*=2) if(elemA[i+k]-elemA[i] == elemB[k+j]-elemB[j]) seCupl++; if(nrUnu(elemB[j] - elemA[i]) == 1 && seCupl==pas-1) for(unsigned k=i, l=j; k<i+cresc; k++, l++) { cuplare.push_back(elemA[k]); cuplare.push_back(elemB[l]); } } int sortVar = int(pow(2.0, pas))-1; if(!cuplare.empty() && pas>1) for(vector<int>::iterator i=cuplare.begin(), j=cuplare.begin()+sortVar; j<cuplare.end()-sortVar; i+=sortVar+1, j+=sortVar+1) sort(i,j); } 9

// stergem cuburile care se repeta din cuplare void elimin(vector<int> &elemA, const int &pas) { int nrElem = int(pow(2.0, pas)); for(unsigned cub = 0; cub<elemA.size()-nrElem; cub+=nrElem) for(unsigned cubComp = cub + nrElem; cubComp<elemA.size(); ) { int nrEgal=0; for(int i=0; i<nrElem; i++) if(elemA[cub+i] == elemA[cubComp+i]) nrEgal++; if(nrEgal == nrElem) elemA.erase(elemA.begin()+cubComp,elemA.begin()+cubComp+nrElem); else cubComp += nrElem; } } // verific daca cuplarea este vida bool suntCuplari(vector<int> **S, const int &ordin, const int &pas) { char cupl = 0; for(int i=0; i<ordin+1; i++) if(!S[pas][i].empty()) cupl++; if(!cupl) return false; return true; }

10

// aflam cuburile cu algoritmul QMC void QMC(vector<int> **&S, int &ordin) { vector<int> minT; citesc(minT, ordin); cout<<Ordinul: <<ordin<<endl; afisez(minT, ordin); cout<<\nApasati Enter pentru afisarea cuplarilor...; cin.get(); system(cls); cuplare(S,minT,ordin); for(int pas=1; pas<ordin+1; pas++) // merge stabil pentru toate cuplarile { for(int i=0; i<ordin; i++) // se incarca date in coloana cuplarii zero { if(!S[pas-1][i].empty() && !S[pas-1][i+1].empty()) cuplare(S[pas-1][i], S[pas-1][i+1], S[pas][i], pas); } for(int k=0; k<ordin; k++) if(pas>1 && !S[pas][k].empty()) elimin(S[pas][k], pas); } for(int pas=0; pas<ordin+1; pas++) { if(suntCuplari(S,ordin, pas)) { cout<<CUPLAREA <<pas<<: <<endl<<endl; for(int i=0; i<ordin+1; i++) if(!S[pas][i].empty()) { cout<<S<<i<<: <<endl; afisez(S[pas][i], pas, c); } cout<<Apasati tasta Enter pentru urmatoarea Cuplare...; cin.get(); system(cls); } } cout<<\nS-a calculat QMC - zecimal !\n\nApasati tasta Enter pentru afisarea lui Z(f)...; cin.get(); system(cls); }

11

// traduc din tabel in Z void traduc(const vector<int> &S, vector<int> &Zf) { for(unsigned i=0; i<S.size(); i++) Zf.push_back(S[i]); } // caut si elimin cuburile marcate void IP(vector<int> &sAnt, const vector<int> &sPost, int pas) { int cresc = (int)pow(2.0, pas); for(unsigned i=0; i<sAnt.size(); ) { int eCuplat = 0; for(unsigned caut = i; caut<i+cresc; caut++) for(unsigned j=0; j<sPost.size(); j++) if(sAnt[caut] == sPost[j]) { eCuplat++; caut++; } if(eCuplat >= cresc) sAnt.erase(sAnt.begin()+i, sAnt.begin()+i+cresc); else i+=cresc; } } // incarc Z(f) cu implicantii primi void incarcZ(vector<int> *&Z, vector<int> **&S, const int &ordin) { if(S[ordin][0].empty()) { for(int pas=0; pas<ordin; pas++) for(int i=0; i<ordin; i++) if(!S[pas][i].empty()) traduc(S[pas][i], Z[pas]); } else { cout<< CUB COMPLET !\n; cin.get(); exit (1); } for(unsigned i = ordin; i>1; i--) delete [] S[i-1]; delete [] S; for(int i=0; i<ordin; i++) { if(!Z[i].empty() && !Z[i].empty()) IP(Z[i], Z[i+1], i); } } 12

// returnteaza pozitia marcajului int pozUnu(int nr) { int contor = 0; while(nr>0) { contor++; nr = nr>>1; } return contor-1; } // decodeaza implicantii primi in literali void decodez(const vector<int> &Z, const int &pas, int ordin, bool adunare) { int line = int(pow(2.0, pas)); vector<int> binary; vector<char> literali; for(unsigned i=0; i<Z.size(); i+=line) { char lit = a + ordin-1; int nr = Z[i]; int ordin1 = ordin; int compensez = 0; while(ordin1) { binary.push_back(int(nr%2)); literali.push_back(char(lit)); lit--; nr = nr>>1; ordin1--; } for(int k=1; k<line; k*=2) { binary.erase(binary.begin()+pozUnu(Z[i+k]-Z[i])-compensez, binary.begin()+pozUnu(Z[i+k]-Z[i])+1-compensez); literali.erase(literali.begin()+pozUnu(Z[i+k]-Z[i])-compensez, literali.begin()+pozUnu(Z[i+k]-Z[i])+1-compensez); compensez++; } for(int l=literali.size(); l>0; l--) if(binary[l-1] == 0) cout<<~<<literali[l-1]; else cout<<literali[l-1]; binary.clear(); literali.clear(); if(adunare || i+line < Z.size()) cout<< + ; } } 13

#includefunctions.h int main () { vector<int> **S; int ordin = 0; QMC(S, ordin); vector<int> *Z; Z = new vector<int>[ordin+1]; incarcZ(Z,S, ordin); // s-a eliberat S si s-a incarcat Z cout<<Z(f) = { ; for(int i=0; i<ordin; i++) if(!Z[i].empty()) afisez(Z[i], i, i); cout<< }<<endl; cout<<\nDecodificare:\n\nf(; for(int i=0; i<ordin; i++) cout<<char(a+i); cout<<) = ; for(int i=0; i<ordin; i++) if(!Z[i].empty()) if(!Z[i+1].empty()) decodez(Z[i], i, ordin, true); else decodez(Z[i], i, ordin, false); cout<<\n\nCodat de Jerca Vlad, Anul I, Grupa 152, Specializarea IT .; cin.get(); return 0; }

14

4. Executarea programului
1. exemplul a (pg. 5)

15

2. exemplul b (pg. 6 )

16

BIBLIOGRAFIE

1. Curs BLPC ( sustinut de Dl. Popa Marin ) 2. Wikipedia.com

17