Sunteți pe pagina 1din 48

Universitatea “Al.I.

Cuza”
Facultatea de Informatică

Teză de licenţă

AnaCoS – Comparator de programe

Iolanda Popa

Iaşi, iulie 2008


Cuprins
1. INTRODUCERE...................................................................................................................................................................4

1.1. CE ESTE PLAGIEREA SOFTWARE?.............................................................................................................................................4


1.2. DESPRE ANACOS................................................................................................................................................................7

2. SISTEME SOFTWARE ANTI-PLAGIAT.........................................................................................................................8

2.1. SCURT ISTORIC.................................................................................................................................................................... 8


2.2. PLAGUE....................................................................................................................................................................... 13
2.3. YAP.............................................................................................................................................................................. 14
2.4. JPLAG........................................................................................................................................................................... 16
2.5. SIM................................................................................................................................................................................21
2.6. SIFF............................................................................................................................................................................... 22
2.7. MOSS............................................................................................................................................................................ 24
2.8. DUP............................................................................................................................................................................... 25
2.9. BANDIT........................................................................................................................................................................26
2.10. COGGER.....................................................................................................................................................................27
2.11. CODEMATCH.................................................................................................................................................................. 28
2.12. SID...............................................................................................................................................................................34
2.13. SHERLOCK...................................................................................................................................................................... 36

3. ALGORITMUL FOLOSIT DE ANACOS..................................................................................................................... 38

3.1. GENERALITĂȚI...................................................................................................................................................................38
3.2. COMPARAREA LISTELOR DE TOKENI....................................................................................................................................... 40
3.3. COMPARAREA ARBORILOR SINTACTICI....................................................................................................................................41

4. PREZENTAREA APLICAŢIEI.......................................................................................................................................43

5. EVALUĂRI EMPIRICE PENTRU ANACOS.................................................................................................................45

6. REZUMAT ŞI CONCLUZII ............................................................................................................................................ 46

7. BIBLIOGRAFIE................................................................................................................................................................. 47
Cuvânt înainte

În cadrul cursurilor de informatică studenţii sunt puşi deseori în situaţia de a completa tutoriale
şi exerciţii de laborator cerându-li-se să scrie cod sursă. Cadrele didactice pot cere studenţilor codul
sursă pentru a monitoriza gradul de înţelegere de către studenţi a materiei prezentate în modulul
respectiv, iar codul sursă predat poate fi astfel verificat din punctul de vedere al similarităţilor cu alte
surse, cu scopul identificării cazurilor de plagiat. În exerciţiile individuale, cazurile de plagiat pot să
apară între studenţi prin copierea de la un alt student sau prin copierea din cărţi sau alte surse.
Această lucrare se vrea a fi o cercetare amplă a ideilor celor mai importante de până acum pe
care cercetătorii le-au avut în privința modului cum putem detecta algoritmic acest tip de plagiat și o
contribuție personală prin prezentarea câtorva idei importante implementate în aplicația AnaCoS.

3
1. INTRODUCERE

1.1. Ce este plagierea software?

Pentru cei mai mulţi dintre profesorii care predau programare plagiatul temelor de laborator este
o chestiune serioasă. Internetul, numărul mare de articole şi cărţi sunt surse de inspiraţie utilizate de
studenţi, iar toate acestea facilitează plagierea pentru studenţi. Un articol recent relevă că studenţii
utilizează internetul pentru a convinge programatori cu experienţă să le implementeze secvenţele de
program.

Bull şi Culwin [1] au efectuat sondaje printre cadrele didactice universitare pentru a determina
prevalenţa plagiatului şi au evaluat performanţa softurilor anti-plagiat.

Sondajele au arătat că atât plagierea textelor în limbaj natural cât şi a codului sursă reprezintă
probleme majore în instituţiile universitare şi studiul lui Bull din 2001 indică faptul că jumătate dintre
cadrele didactice universitare participante la sondaj au simţit că în ultimii ani s-a manifestat o creştere a
cazurilor de plagiat.

O analiză a literaturii actuale asupra plagierii codului sursă în activitatea studenţilor, arată că nu
există o descriere general acceptată a ceea ce constituie plagiatul de cod-sursă din perspectiva cadrelor
universitare care predau cursuri de programare a calculatoarelor. Există câteva definiţii ale plagierii
codului sursă, însă acestea par să fie extrem de limitate. De exemplu, în conformitate cu Faidhi şi
Robinson plagiatul se produce atunci când secvenţele program sunt "copiate şi transformate" cu foarte
puţin efort din partea studenţilor, iar Joy Luck defineşte ca fiind plagiat "copierea indezirabila de
documente şi programe." Mai mult, o carte din 2002 scrisă de Decoo despre comportamente academice

4
inadecvate discută diferite aspecte din jurul plagiatului academic. Decoo discută pe scurt despre
plagierea software la nivelul interfeţei-utilizator, conţinutului şi codului sursă.

Sutherland-Smith a efectuat în 2005 un sondaj pentru a afla opiniile a 11 cadre didactice de la


Facultatea de Afaceri şi Drept din cadrul Universităţii South-Coast din Australia. Concluziile relevă
percepţia diferită asupra plagiatului a cadrelor universitare care predau acelaşi subiect şi autorul
sugerează că o "colaborare interdisciplinara de regândire a conceptului de plagiat este necesară."

Georgina Cosma şi Mike Joy [2] reuşesc totuşi să vină cu o serie de informaţii concrete obţinute
de pe urma datelor care au fost adunate printr-un sondaj de opinie realizat în mediile academice din
Marea Britanie. Datele au fost adunate şi analizate pentru a crea o descriere a ceea ce constituie
plagiatul de cod-sursă dintr-o vastă perspectivă academică. În continuare redăm concluziile celor doi.

Plagierea codului sursă în temele de programare poate apărea atunci când un student
reutilizează cod-sursă creat de altcineva prin obţinerea codului cu sau fără permisiunea autorului iniţial
şi fără a recunoaşte, intenţionat sau nu, că a împrumutat cod sursă şi prezentându-l ca propria sa muncă.

Dacă un student refoloseste cod sursă pe care l-a produs ca parte a unei alte activităţi (în care
el/ea a câştigat credite academice), fără a recunoaşte acest fapt, poate constitui auto-plagiat sau o altă
infracţiune academică (conceptul de infracţiune academică depinde de reglementările universitare).

Dacă un student reutilizează cod sursă creat de către altcineva (sau produs de acel student ca
parte a unei alte evaluări) şi recunoaşte acest lucru atunci aceasta poate să constituie o încălcare de
reguli de activitate şi nu plagiat (sau auto-plagiat).

Reutilizarea include următoarele:


● Reproducerea/copierea fără alterări
● Reproducerea/copierea şi adaptarea moderată sau minimală. Adaptarea moderată sau minimală
apare atunci când “munca” oferită de student mai conţine câte ceva din codul sursă original.
● Conversia întreagă sau a unei părţi a unui cod-sursă aparţinând altcuiva într-un alt limbaj de
programare. Dacă acest lucru constituie plagiat sau nu depinde de similitudinea dintre limbaje şi
de efortul depus de către student pentru a face conversia. În cazul în care studentul se inspiră şi
preia idei dintr-un cod-sursă scris într-un alt limbaj de programare şi codul-sursă este în
întregime asumat de către student, nu constituie plagiat.
● Generarea automată de cod-sursă folosind soft generator de cod-sursă poate constitui plagiat

5
dacă utilizarea unui astfel de soft nu este permisă în mod explicit în reglementări.

Procurarea codului sursă cu sau fără permisiunea autorului iniţial include următoarele:
● Un student plăteşte o altă persoană (sau un student din acelaşi modul) să creeze o parte sau
întregul cod-sursă.
● Un student fură codul-sursă al altui student.
● Doi sau mai mulţi studenţi colaborează (muncesc împreună) la scrierea unui program care
solicită activitatea doar a unuia dintre ei iar studenţii prezintă coduri-sursă similare. Acest fapt
poate constitui plagiat (numele infracţiunii academice depinde de regulamentele academice).
● Studenţii din diferite grupe, având de rezolvat aceeaşi problemă, fac schimb de părţi ale codului
sursă cu sau fără consimţământul şefilor lor de grupă.

În lista de mai sus plagiatul de cod-sursă poate să apară în acelaşi timp cu alte infracţiuni academice
în funcţie de regulamentele academice. Aceasta este o listă foarte restrânsă atât timp cât există
numeroase căi prin care studenţii pot obţine cod-sursă scris de alţi autori.

Nerecunoaşterea include:
● Nu se anunţă sursa şi autorul codului sursă în cadrul programului (sub forma unui comentariu)
şi în documentaţia corespunzătoare.
● Utilizarea referinţelor inventate (adică referinţe care au fost scrise de student dar ele nu există)
este o formă de greşeală academică, numită adesea fabricare, şi poate coexista cu plagiatul.
● Utilizarea referinţelor false (adică referinţe care există dar nu conţin codul-sursă care a fost
copiat) este o formă de greşeală academică, numită adesea falsificare, şi poate coexista cu
plagiatul.
● Modificarea ieşirii programului pentru a lăsa impresia că programul funcţionează când de fapt
nu funcţionează este o formă de greşeală academică (falsificare) şi poate coexista cu plagiatul.

6
1.2. Despre AnaCoS

AnaCoS (acronim de la Analizare şi Comparare Surse) este o aplicaţie dezvoltată de autoarea


acestui document care se încadrează în domeniul plagierii software fiind menită să ajute cadrele
academice în depistarea plagiatului.

Concret, din toate cazurile de plagiat prezentate în secţiunea 1.1., AnaCoS se ocupă cu
depistarea programelor copiate fără alterări sau cu adaptări menite să deghizeze plagiatul (alineatele 1
şi 2 de la reutilizare). Astfel, AnaCoS urmăreşte să detecteze situaţiile (stabilite ca fiind plagiat în
secţiunea 1.1.) în care studentul reutilizează cod-sursă creat de altcineva sau pe care l-a produs ca parte
a unei alte activităţi, fără să recunoască. Aceasta este direcţia pe care se înscrie aplicaţia autoarei în
domeniul plagierii software.

Detaliile tehnice, descrierea algoritmului folosit şi performanţele vor fi discutate în capitolele


următoare după o cercetare amplă a altor instrumente anti-plagiat (care se înscriu pe aceeaşi direcţie) şi
evoluţia lor în timp.

7
2. SISTEME SOFTWARE ANTI-PLAGIAT

2.1. Scurt istoric

Literatura de specialitate clasifică soft-urile anti-plagiat în două tipuri: sisteme de numărare a


atributelor şi sisteme bazate pe metrici structurale.

Transformările care pot fi aduse unui program cu scopul de a deghiza plagierea pot fi de la cele
foarte simple (cum ar fi schimbarea comentariilor din cuprinsul codului sursă sau schimbarea numelui
variabilelor) la cele mai complexe (înlocuirea structurilor de control cu cele echivalente, de ex.
înlocuirea unei bucle for cu o instrucţiune while).

În particular, o sursă utilă de informare în domeniul plagierii de soft este Whale [9] care enumeră
metode potenţiale de deghizare a programelor, printre care:
● Schimbarea comentariilor
● Schimbarea tipurilor de date
● Schimbarea identificatorilor
● Adăugarea de instrucţiuni sau variabile redundante
● Schimbarea structurii instrucţiunilor de selecţie sau iterare
● Combinarea de secvenţe de cod originale şi copiate

Whale continuă cu o discuţie a evaluării sistemelor de detectare a plagiatului şi a diverselor tehnici


de detecţie a similarităţii, inclusiv propriul său utilitar numit Plague (prezentat mai târziu).

O proprietate importantă a oricărui asemenea sistem este depistarea corectă a codului suspicios.
Adică, o distincţie clară între similitudinea întâmplătoare şi similitudinea rezultată prin plagiat. Acest

8
lucru este similar cu detectarea cuvintelor sau bucle for cu o instrucţiune while€). Primele tehnici
utilizate pentru detectarea plagiatului software au fost categorisite ca tehnici de numărare a atributelor.
Primul program a apărut în anii '70 şi a utilizat fie metrica lui Halstead, fie complexitatea ciclomatică a
lui McCabe, fie metrica nivelului de imbricare.

Metrica lui Halstead utilizează următoarele variabile:


n1 = numarul operatorilor unici sau distincţi.
n2 = numarul operanzilor unici sau distincţi.
N1 = totalul utilizărilor tuturor operatorilor.
N2 = totalul utilizărilor tuturor operanzilor.

Apoi Halstead a definit vocabularul n ca


n = n1+ n2
şi lungimea implementării N ca fiind
N = N1 + N2

Una dintre primele măsuri de similaritate care derivă din numărarea acestor elemente a fost
volumul
V:
V = N log2 (n)

Complexitatea ciclomatică a lui McCabe este utilizată pentru a măsura fluxul de control printr-
un program prin calcularea numărului de paşi executaţi. Mărimea, V(G), este derivată din graful de
reprezentare a fluxului programului a€“
nodurile sunt blocuri de instrucţiuni esenţiale şi muchiile sunt căi
de procesare:
V(G) = e - n + 2p,
unde
e = numărul de muchii în graf
n = numărul de noduri în graf
p = numărul de componente în graf (p=1 pentru un modul).

O altă metrică folosită a fost metrica nivelului de imbricare. Aceasta măsoară media adâncimii
imbricarii unui program sau modul prin asignarea fiecărei linii de cod a unui indicator de adâncime.
Suma tuturor instrucţiunilor produce adâncimea imbricarii totale şi o medie poate fi calculată prin
împărţirea măsurilor totale la numărul instrucţiunilor din program/modul.

Primul care a utilizat metrica Halstead pentru detectarea plagiatului a fost Ottenstein de la
Universitatea Purdue care a dezvoltat o aplicaţie pentru detectarea plagiatului în programe Fortran. S-a
constatat că această tehnică este inefectivă pentru programe foarte scurte (nu poate face faţă alterarilor

9
non-triviale ale programelor) şi astfel s-a produs o tranziţie de la tehnicile de numărare a atributelor la
tehnicile structurale.

Robinson şi Soffa au dezvoltat în 1980 un program anti-plagiat care combină noi metrici cu
metrica Halstead în scopul îmbunătăţirii detecţiei plagiatului. Sistemul lor, numit ITPAD, constă în trei
paşi: analiza lexicală, analiza structurii programului pentru determinarea caracteristicilor şi analiza
caracteristicilor.

Sistemul lui Robinson şi Soffa sparge fiecare program în blocuri şi construieşte 2 grafuri pentru
reprezentarea structurii programului fiecărui student. Generează apoi o listă de atribute bazată pe
analiza lexicală şi structurală şi compară perechi de programe prin numărarea acestor caracteristici.

În cele mai multe aplicaţii bazate pe metrici structurale primul stadiu este numit tokenizare. La
acest nivel părţi diferite ale codului se înlocuiesc cu un simbol (token) predefinit şi consistent, de ex.
tipuri diferite de bucle în codul sursă pot fi înlocuite prin acelaşi token indiferent de tipul de buclă
(buclă while, buclă for). Fiecare cod-sursă este apoi reprezentat ca o serie de token-uri. Vezi fig. 1.

(a) (b)

if (x == 5) CONDITIONAL_BEGIN
{
// Loop on j here
for (j = 0; j < Index; j++) LOOP_BEGIN
printf("x = %i", j); DISPLAY
} LOOP_END
else CONDITIONAL_END, CONDITIONAL_BEGIN
while (i < 5) i++; LOOP_BEGIN, ARITHMETIC, LOOP_END
CONDITIONAL_END

Fig. 1: Substituirea cu tokeni. (a) programul original; (b) profilul structurii programului.

Token-urile fiecărui document sunt comparate pentru a determina segmente similare de cod
sursă. Compararea sistemelor software bazate pe numărarea de atribute cu cele bazate pe metrici
structurale arată faptul că metoda numărării atributelor folosită de una singură nu este suficient de
adecvată pentru detectarea plagiatului.

Sistemele cu metrici structurale au fost propuse iniţial de către Donaldson în 1981. Aceste
sisteme utilizează metrici de numărare a atributelor dar compară şi structura programului în scopul
îmbunătăţirii detecţiei plagiatului. Donaldson a identificat tehnici simple pe care studenţii începători în
programare le utilizează pentru mascarea plagiatului: Problema studenţilor rezidând în programele

10
care nu sunt ale lor. Aceste metode sunt: redenumirea variabilelor, reordonarea instrucţiunilor care nu
vor afecta rezultatele programului, schimbarea instrucţiunilor de format şi spargerea instrucţiunilor
cum ar fi declaraţii multiple şi instrucţiuni de ieşire (Donaldson).

Programul dezvoltat de Donaldson scanează fişierele cu cod-sursă şi memorează informaţii


despre anumite tipuri de instrucţiuni. Apoi, tipurilor de instrucţiuni semnificative în descrierea
structurii le sunt atribuite un singur caracter. Fişierul este apoi reprezentat ca un şir de caractere. Dacă
şirurile reprezentărilor sunt identice sau similare, atunci perechea de programe este returnată ca
similară.

Sistemul care utilizează ambele tipuri de metrici pentru a detecta plagiatul (în programele
Fortran), propus de Donaldson, se numeşte ACCUSE (a fost dezvoltat iniţial de către Grier la
Academia Forţelor Aeriene US în Fortran).

Cele mai recente sisteme utilizează metrici de structură şi compară şiruri de reprezentare a
structurii de program. Ele evaluează similaritatea şirurilor de tokeni şi nu cer potriviri exacte. Exemple
de astfel de sisteme sunt: Plague, Sim, YAP.

Un exemplu de algoritm foarte simplu pentru detectarea plagiatului, bazat pe compararea de şiruri
este următorul:
● Înlătură toate comentariile.
● Ignoră toate blancurile şi liniile goale cu excepţia cazurilor când sunt necesare ca delimitatori.
● Execută o comparare de şiruri de caractere între două fişiere utilizând UNIX diff, grep şi wc.
● Administrează un contor de procente ale caracterelor care sunt aceleaşi (numit corelare de
caractere).
● Se execută pentru toate perechile de programe.
● Crează un rezumat al comparărilor conţinând corelarea caracterelor în ordine descrescătoare şi
examinează.

Alte metode care merită menţionate aici sunt:


● Faidhi - Robinson care utilizează 24 de metrici pentru a testa similaritatea. Primele 10 fi
alterate de un plagiator începător, în timp ce celelalte de un plagiator experimentat.
● Rees şi sistemul său STYLE care a fost de asemenea utilizat pentru a acorda scor programelor
bazându-se pe stil.
● Programul CHEAT al lui Rees Robinson.
● Jankowitz care a analizat programe utilizând arborii de execuţie statici obţinuţi prin analiza
gramaticală a corpului programului principal şi a procedurilor.

Verco şi Wise analizează atât sistemul ACCUSE cât şi abordarea Faidhi-Robinson pentru evaluarea

11
performanţei ambelor tehnici. Wise a dezvoltat o serie de utilitare, denumite YAP (Yet another
Plague), care pot fi utilizate pe o gamă largă de limbaje.

O altă zonă de interes este cea judiciară. Se încearcă astfel determinarea autorului unui fragment de
cod cu scopul principal de a determina autorul programelor în cazuri de fraudă pe calculator, de
încălcări de securitate şi de plagiat. O bună introducere face Sallis care continuă de asemenea să
rezume cele mai populare caracteristici care pot permite sau pot îmbunătăţi detectarea plagiatului. Trei
dintre caracteristici le-am văzut deja: metrica lui Halstead, complexitatea ciclomatică a lui McCabe şi
metrica nivelului de imbricare.

Mai departe sunt prezentate câteva dintre cele mai folosite instrumente anti-plagiat, inclusiv unele
dintre cele mai noi. Se sare peste prezentarea unor utilitare mai vechi cum ar fi ACCUSE sau programul
original al lui Ottenstein deoarece tehnicile numărării atributelor aplicate izolat s-au dovedit mai puţin
eficiente decât abordările bazate pe metrici structurale sau o combinaţie a celor două.

12
2.2. PLAGUE

Plague creează mai întâi o secvenţă de tokeni pentru fiecare fişier şi fişiere de structură
conţinând metrici de structură. Apoi profilele structurale sunt comparate şi cele similare sunt
identificate. Caută apoi şi compară secvenţele de tokeni ale fişierelor similare. Wise a dezvoltat un
algoritm de potrivire a şirurilor de tokeni numit Running-Karp-Rabin Greedy-String-Tiling (RKS-
GST) şi l-a utilizat în YAP3. Acest algoritm a fost dezvoltat în principal pentru detectarea spargerii
funcţiilor de cod în funcţii multiple (şi invers) şi de a detecta reordonarea segmentelor de cod
independente.

În esenţă, Plague lucrează în 3 faze:


● Creează o secvenţă de tokeni şi o listă cu metrici structurale pentru a crea un profil al structurii.
Profilul rezumă structurile de control utilizate în program. Profilul structurii se prezintă sub
forma unei expresii regulate generalizate.
2
● O fază de complexitate O(n ) compară profilurile structurale şi determină perechile de vecini
cei mai apropiaţi. Majoritatea intrărilor sunt presupuse nepereche şi orice pereche aleasă acum
trece în următoarea etapă.
● Etapa finală este destinată comparării secvenţelor de tokeni utilizând o variantă a celei mai
lungi subsecvenţe comune pentru verificarea similarităţii.

Există totuşi câteva probleme cu Plague:


● Plague se adaptează greu la noi limbaje; este un foarte mare consumator de timp.
● Rezultatele Plague sunt două liste ordonate care au nevoie de interpretare. Rezultatele nu sunt
imediat evidente.
● Plague suferă din cauza problemelor de eficienţă şi se bazează pe o serie de utilitare UNIX
suplimentare. Aceasta creează probleme de portabilitate.

Rezultatele Plague sunt bune. Din 44 documente Plague a reuşit să identifice corect 22 din 24
cazuri de plagiat.

13
2.3. YAP

Seria de instrumente YAP (vine de la Yet Another Plague) se bazează pe instrumentul de


detectare a plagiatului Plague. Michael Wise a creat versiunea iniţială YAP1 în 1992 şi a urmat curând
o variantă optimizată YAP2. În 1996 Wise produce versiunea finală a YAP (YAP3). Principalul scop al
YAP a fost ca plecând de la Plague, un instrument care s-a dovedit mai victorios decât tehnicile
anterioare de tip numărare-atribute sau bazate pe comparare structurală, să construiască un alt
instrument care să rezolve unele probleme ale acestei tehnici.

Toate variantele de YAP lucrează, în esenţă, în acelaşi mod şi au două faze de funcţionare:
● În prima fază se generează un fişier de tokeni pentru fiecare intrare.
● Cea de-a doua fază compară perechile de fişiere de tokeni.

Toţi identificatorii şi constantele sunt ignorate. O temă de laborator mică are de obicei 100-150
tokeni, în timp ce o temă mai mare poate avea 400-700. Faza de token-izare se face separat pentru
fiecare limbaj, dar toate versiunile au aceeaşi structură:

1. Preprocesarea:
● Eliminarea comentariilor şi a şirurilor de caractere tip constantă,
● Eliminarea literelor care nu au fost găsite în lista identificatorilor legali,
● Transformarea literelor majuscule în minuscule,
● Formarea unei liste de token-uri primitive.
2. Traducerea sinonimelor într-o formă comună, de exemplu, în C_YAP strncmp este mapat la
strcmp. Acest lucru este similar cu maparea cuvintelor la cuvinte mai generice.
3. Identificarea blocurilor de funcție/procedură.
4. Tipărirea blocurilor de funcţie în ordinea apelului. Blocurile repetate sunt expandate doar prima
dată, cele ulterioare fiind înlocuite de un token care reprezintă acea funcţie.
5. Recunoaşterea şi tipărirea de token-uri dintr-un anumit vocabular dat, reprezentând părţi
specifice limbajului.

Apelurile de funcţii sunt mapate la FUN şi alţi identificatori sunt ignoraţi.

În faza de comparaţie, utilitarul UNIX find este folosit pentru a strânge o listă cu fişierele de tokeni
anterior pregătite şi sdiff este utilizat pentru a compara fiecare fişier de tokeni cu toate celelalte. Ieşirea
2
este analizată utilizând un simplu script awk. Această fază este lentă, fiind O(n ), dar a fost accelerată
în YAP2 folosind un program C care implementează algoritmul lui Heckel (22).

14
Rezultatul dat de YAP1 este o valoare de la 0 la 100 pentru fiecare comparaţie, 0 reprezentând nu
se potrivesc şi 100 o copie exactă. O medie şi abatere standard sunt calculate şi apoi orice rezultate
care apar la 3 sau mai multe abateri standard de la medie sunt demne de a fi explorate mai departe.
YAP1 a fost testat vs. Plague pe 167 lucrări Pascal ale studenților. Plague a găsit 640 de perechi peste
pragul 10 şi YAP1 654 perechi cu 1,53 deviaţii standard de la medie. Un rezultat surprinzător a fost că
s-au găsit de către YAP1 391 de potriviri care nu apar în Plague şi 377 de potriviri găsite de către
Plague care nu apar în YAP1. Un număr de 110 potriviri date de YAP1 şi neraportate de Plague s-au
confirmat ca fiind potriviri în care studenţii au tăiat proceduri în bucăţi. Prin expandarea procedurilor în
ordinea apelului similitudinea devine mai evidentă.

Wise, pretinde că Yap este în măsură să facă faţă la:

● Schimbarea comentariilor sau formatării - Yap este imun la aceasta


● Schimbarea identificatorilor - Yap este imun la aceasta.
● Schimbarea ordinii operanzilor - Yap este imun la aceasta.
● Schimbarea tipurilor de date - Yap este imun la aceasta.
● Înlocuirea cu expresii echivalente - Yap este imun la aceasta sau înregistrează doar o mică
diferenţă (1 token).
● Adăugări de construcţii sau variabile redundante - Yap este imun la variabile suplimentare.
Construcţiile suplimentare conduc la mici diferenţe (1 token pe construcţie).
● Schimbarea ordinii secvenţelor independente - de exemplu rearanjarea de clauze Prolog. Yap
are probleme cu aceasta şi poate provoca diferenţe semnificative. Presupunerea pe care Yap o
face, totuşi, este că pentru a putea face acest lucru în mod eficient studentul trebuie să înţeleagă
programul şi cum interacţionează părţile independente.
Dacă definiţiile de proceduri sau de funcţii sunt rearanjate Yap este imun la aceasta.
● Modificarea structurilor de iteraţie - Yap este în mare măsură imun la acest lucru.
● Modificarea structurilor de selecţie - Yap este în mare măsură imun la acest lucru datorită
înlocuirii sinonimelor, de exemplu, case devine elseifTEST ca şi if … then ... else.
● Înlocuirea apelurilor de proceduri cu corpul procedurii - Yap este în mare măsură imun la
acest lucru.
● Introducere de secveţe non-structurale - creează diferenţe de doar 1 token.
● Combinarea de secvenţe de program originale şi copiate - în general, acestea apar ca un
grup de teme de laborator cu potriviri mult peste medie.

Rezultatele au dovedit că Yap a fost capabil să contracareze cele mai multe dintre tehnicile utilizate
de către studenţi (după cum au fost date de Whale) şi Yap este cel puţin la fel de precis ca Plague în
găsirea de asemănări şi la fel de bun în a evita să constate asemănări în cazul în care nu există nici una.

15
2.4. JPLAG

JPlag [6] a fost dezvoltat de membri ai Departamentului de Informatică ai Universităţii din


Karlsruhe, unde Prof. W. Tichy este şeful grupului de cercetare. Utilitarul găseşte asemănări între codul
sursă scris în Java, C, C + + şi Scheme. Acest utilitar compară octeţi de text şi structura de program
făcându-l mai robust împotriva plagiatului deghizat. JPlag poate fi accesat dintr-o pagină Web şi de
îndată ce un cont este obţinut instrumentul poate fi folosit gratuit.

Algoritmul de comparaţie JPlag este un algoritm bazat pe şiruri de tokeni combinat cu


algoritmul RKS-GST ("Greedy String Tiling"), care a fost introdus de către Wise în 1996. Practic,
JPlag analizează fişierele, le transformă în şiruri de tokeni şi apoi aplică GST pentru a găsi asemănări.

JPlag are două faze:

● Toate programele de comparat sunt analizate (sau scanate, în funcţie de limbajul de intrare) şi
convertite în şiruri de tokeni.
● Şirurile de tokeni sunt comparate în pereche pentru determinarea similitudinii fiecăreia. Pe
parcursul comparatiilor, JPlag încearcă să acopere un şir de tokeni cu subsiruri ("tiles") luate de
la celălalt şir, cât mai bine posibil. Procentul de subsiruri de tokeni care pot fi acoperite este
valoarea de similaritate.

Procesul de debut al conversiei programelor în şiruri de tokeni este singurul proces dependent de
limbaj în JPlag. În prezent există 3 versiuni de implementare: cele pentru Java şi Scheme
implementează un analizor complet pentru respectivul limbaj. Versiunea pentru C++ (sau C) constă
doar într-un scanner. Un asemenea analizator are avantajul de a permite ca mai multe informaţii
semantice să fie reprezentate în şirul de tokeni.

De exemplu, în Java, putem crea un token BEGINMETHOD în locul unui token OPEN BRACE.
Ca o regulă, token-urile trebuie să fie alese astfel încât ele să caracterizeze esenţa unui program (care
este dificil de schimbat de către un plagiator) mai degrabă decât aspectele de suprafaţa. De exemplu, în
viziunea autorilor JPlag, spaţiul alb şi comentariile nu ar trebui să producă un token deoarece acestea
sunt cele mai evidente puncte de atac. Unele tipuri de tokeni pot sau nu pot fi considerate utile. De
exemplu, mulţimea prestabilită de tokeni pentru Java ignoră complet expresiile cu excepţia asignarilor
şi a apelurilor de metodă. Vezi fig. 2.

Numărul liniei de la care provine token-ul este stocat în obiectul token-ului, astfel încât este posibil,
mai târziu, să se indice uşor orice asemănări între două fişiere prin referirea la fişierele sursă originale.

16
Reţineţi că fiecare token intern este reprezentat de un singur caracter pentru comparaţie.

Sursa Java Tokenii generaţi


1 public class Count { BEGINCLASS
2 public static void main(String[] args) VARDEF,BEGINMETHOD
3 throws java.io.IOException {
4 int count = 0; VARDEF,ASSIGN
5
6 while (System.in.read() != -1) APPLY,BEGINWHILE
7 count++; ASSIGN,ENDWHILE
8 System.out.println(count+" chars."); APPLY
9 } ENDMETHOD
10 } ENDCLASS
Fig. 2: Exemplu de sursă Java și tokenii corespondenţi

Algoritmul folosit pentru a compara două şiruri de tokeni este în esenţă GST (Greedy String
Tiling) cum a fost prezentat de Michael Wise. Pe parcursul comparării a două şiruri de tokeni A şi B,
scopul este de a găsi un set de subşiruri care sunt la fel şi care îndeplinesc următoarele reguli:
● Orice token din A poate fi comparat doar cu un token din B. Această regulă implică faptul că
este imposibil să se potrivească complet părţi din textul-sursă care au fost duplicate într-un
program plagiat.
● Subşirurile urmează să fie găsite independent de poziţia lor în şir. Aceasta implică faptul că
reordonarea părţilor din codul sursă nu este un atac eficace.
● Potrivirea subşirurilor lungi este preferată celor scurte pentru că ele sunt mai de încredere.
Potrivirile scurte au mai multe şanse de a fi înşelătoare.

Aplicarea secvenţială a celei de-a treia reguli la fiecare pas de verificare a potrivirii conduce la un
algoritm greedy care constă din două faze:
● Faza 1: Se caută în cele două şiruri de tokeni cea mai lungă potrivire contiguă. Aceasta se face
cu 3 bucle imbricate: prima iterează peste toate token-urile din şirul A, cea de-a doua compară
acest token cu fiecare token din B. În cazul în care acestea sunt identice, bucla cea mai din
interior încearcă să extindă potrivirea cât mai mult posibil. Aceste bucle imbricate colectează
mulțimea tuturor subsecvenţelor comune cele mai lungi.
● Faza 2: se marchează toate potrivirile de lungime maximă găsite în faza 1. Aceasta înseamnă că
toate token-urile sunt marcate şi, astfel, nu pot fi utilizate pentru alte comparări din faza 1 a unei
iteraţii ulterioare. Aceasta garantează că fiecare token va fi folosit numai într-o singură
comparaţie şi, astfel, satisface prima regula de mai sus. În plus, unele dintre potriviri se pot
suprapune. În acest caz, prima potrivire găsită este aleasă şi celelalte sunt ignorate.

17
Aceste două etape sunt repetate până când nu mai sunt găsite potriviri. Deoarece lungimea potrivirii
maxime scade cu cel puţin 1 la fiecare pas, se garantează că algoritmul se termină.
Dacă s-ar permite potriviri de orice lungime pot apărea potriviri scurte, întâmplătoare de tokeni. Prin
urmare, pentru evitarea falselor potriviri, se defineşte o limită inferioară pentru lungimea unei potriviri
numită “Lungimea minimă de potrivire”.

Fig. 3 arată pseudocodul algoritmului. Operatorul + din linia 12 adaugă o potrivire unei mulţimi de
potriviri dacă şi numai dacă aceasta nu se suprapune cu una dintre potrivirile aflate deja în mulţime.
Tripleta (a, b, I) indică o asociere între subşirurile din A şi B de lungime I care încep la poziţiile A a şi
Bb respectiv.

0 Greedy-String-Tiling(String A, String B) {
1 tiles = {};
2 do {
3 maxmatch = MinimumMatchLength;
4 matches = {};
5 Forall unmarked tokens Aa in A {
6 Forall unmarked tokens Bb in B {
7 j= 0;
8 while (Aa+j == Bb+j &&
9 unmarked(Aa+j ) && unmarked(Bb+j ))
10 j++;
11 if (j == maxmatch)
12 matches = matches + match(a, b, j);
13 else if (j > maxmatch) {
14 matches = {match(a, b, j)};
15 maxmatch = j;
16 }
17 }
18 }
19 Forall match(a, b, maxmatch) ∈ matches {
20 For j = 0 ... (maxmatch - 1) {
21 mark(Aa+j );
22 mark(Bb+j );
23 }
24 tiles = tiles + match(a, b, maxmatch);
25 }
26 } while (maxmatch > MinimumMatchLength);
27 return tiles;
28 }
Fig. 3: Algoritmul GST (Greedy String Tiling)

18
Pentru fiecare token Aa nemarcat din A, faza 1 începe prin căutarea unui token identic Bb din B
(liniile 5-8). Apoi, tokenii corespondenţi imediat următori sunt comparaţi cu scopul de a extinde
potrivirea cât mai mult (liniile 7-10). Nici unul dintre aceşti tokeni nu trebuie să fie marcaţi anterior. De
îndată ce cele două simboluri Aa + j şi Bb + j diferă sau unul dintre ei este marcat, a fost găsită o potrivire
maximă de lungime j (linia 11). Acum programul verifică dacă această potrivire este cel puţin la fel de
lungă ca cea mai lungă găsită până atunci, a cărei lungime este stocată în maxmatch. Daca j este egal cu
maxmatch, s-a găsit o nouă potrivire maximă care este adăugată la mulţimea matches (linia 12). Daca j
este mai mare decât maxmatch, mulţimea matches este reiniţializată doar cu noua potrivire (linia 14) şi
apoi noua lungime maximă j este stocată în maxmatch (linia 15).

După această etapă matches conţine toate potrivirile maximale. Setul este gol dacă nu s-au găsit
potriviri de lungime cel puţin MinimumMatchLength.

Cea de-a doua fază începe de la linia 19. Mulţimea matches este traversată şi fiecare potrivire
este marcată (liniile 20-23) şi adăugată la mulţimea tiles.

Apoi algoritmul iterează prin cele două etape până când nu se mai găseşte nici o potrivire mai
lungă de MinimumMatchLength şi algoritmul se termină cu mulţimea tiles rezultată. Potrivirile din
această mulţime satisfac regulile date la începutul acestei secţiuni. Fiecare potrivire poate fi acum
analizată pentru a localiza liniile corespunzătoare din codul sursă.

Intuitiv, măsura de similitudine ar trebui să reflecte raportul de token-uri din programele


originale care sunt acoperite de potriviri. Există două variante posibile: Dacă dorim ca o similitudine de
100% să semnifice că cele două şiruri de tokeni sunt echivalente, trebuie să se ia în considerare la
calcul ambele şiruri de tokeni. Dacă, pe de altă parte, am prefera ca fiecare program care a fost copiat
complet (şi apoi extins eventual) să rezulte într-un grad de similitudine de 100%, trebuie să se ia în
considerare doar şirul mai scurt. A fost aleasă prima variantă, care dă următoarea măsură de similaritate
sim:
sim(A, B) = 2∗acoperire /∣A∣∣B∣

acoperire =
∑ lungime
match a ,b , lungime∈tiles

În continuare, sunt date câteva detalii despre interfaţa JPlag. Vezi fig. 4 şi 5.

Rezultatele JPlag sunt prezentate în format HTML sub forma unei histograme a valorilor de
similitudine pentru toate perechile de programe. Perechile de fişiere similare şi măsura lor de
asemănare sunt afişate şi pot fi selectate pentru vizualizare – fig. 5.

19
Fig. 4: Procesarea fişierelor în JPLAG

Fig. 5: JPlag – Rezultate

20
1
2.5. SIM

SIM (Software SIMilarity Tester) – dezvoltat de Dick Grune la Universitatea Vrije - testează
similaritatea programelor măsurând similitudinea lexicală a surselor/textelor scrise în C, Java, Pascal,
Modula-2, Miranda şi limbaj natural.

Dick Grune, afirmă despre SIM că este în măsură să:


● Detecteze plagiatul în proiecte software.
● Detecteze potenţialele fragmente de cod duplicate din proiecte software mari.

Rezultatele obţinute pot fi prelucrate folosind script-uri shell pentru a produce histograme sau o
listă de suspiciuni. Algoritmul de bază este:
● Citeşte fişierele sursă (pasul 1) - fiecare fişier este citit folosind un scaner generat de lex
adecvat pentru tipul de intrare şi tokenii de un octet sunt stocaţi într-un array.
● Pregăteşte o tabelă de referinţă înainte - fiecare subşir de dimensiune minimă este comparat
cu fiecare alt subşir la dreapta de el. Rezultatul este un tabel referinţă în care indicele
următorului subşir a cărui hash trimite spre aceeaşi locaţie este stocat. Dacă nici un subşir
similar nu este găsit, indicele are valoarea 0.
● Determină setul de run-uri interesante – algoritmul caută prin fişiere pentru a testa şi
determina cea mai bună potrivire de subşir (numită run).
● Determină numerele de linie ale run-urilor interesante (pasul 2) - această fază găseşte linia
de început şi de sfârşit pentru fiecare subşir interesant cunoscut doar prin poziţia token-ului de
început.
● Listează conţinutul run-urilor în ordine (pasul 3) – run-urile memorate sunt apoi prezentate
în ordinea importanţei folosind numerele de linie şi formatare pentru o analiză mai uşoară .
Rezultatele testărilor nu sunt raportate în documentaţia care însoţeşte software-ul.

1. http://www.few.vu.nl/~scula/sim.html şi codul sursă (versiunea 2.12) e disponibil la:


ftp://ftp.cs.vu.nl/pub/dick/similarity_tester/

21
2
2.6. SIFF

Scopul iniţial pentru acest instrument a fost de a găsi fişierele similare într-un sistem mare de
fişiere şi a fost numit SIF. Mai recent, tehnica a fost utilizată împreună cu alte metode pentru a măsura
similaritatea fişierelor Java. Programul a fost redenumit Siff.

Siff a fost conceput iniţial pentru a compara un număr mare de fişiere text şi de a găsi
similitudinile dintre ele. Diff este un instrument UNIX care poate compara două fişiere text, dar
presupunând o secundă pe comparaţie, pentru 5000 de fişiere ar necesita mai mult de 12 de milioane de
comparaţii rezultând aproximativ 5 luni de rulare pentru CPU. Acest lucru este imposibil şi, prin
urmare, algoritmul Siff a fost creat pentru a reduce acest timp. Siff creează o reprezentare compactă a
unui fişier numită amprentă aproximativă (fingerprint). Această amprentă constă într-o ancoră - un
şir de caractere (de exemplu, acte) - şi 50 de caractere de aici (poate include cuvinte cum ar fi
caracter). O sumă de control este calculată, pornind de la cele 50 de caractere, pentru a fi folosită în
compararea fişierelor. Deci, pentru ca ancorele alese să fie în mod rezonabil reprezentative pentru text,
se recurge şi la nişte metode de selectare aleatoare.

Această amprentă poate fi comparată rapid dar permite diferenţe destul de mari între fişiere (până
la 25% similaritate). Dacă două fişiere au între 5-10 amprente comune, acestea sunt clasificate ca fiind
similare (depinde şi de dimensiunea fişierului). Avantajul acestei metode este că amprenta, pentru două
fişiere similare, va fi în mare măsură comună celor două fişiere, iar pentru două fişiere diferite ea va
avea o mică intersecţie, cu mare probabilitate. În mod normal, probabilitatea de a găsi acelaşi şir de 50
octeţi în două fişiere diferite este foarte scăzută, dar metoda este susceptibilă la amprente proaste. De
exemplu, formatarea textului în documente poate găsi multe asemănări între fişiere, mai ales în cazul în
care documentul este mic. Acest lucru ar putea cauza ca două fişiere fără legătură să fie grupate ca fiind
similare. Această problemă ar putea fi totuşi rezolvată extrăgând doar textul din documente.
Metoda prezentată este complet sintactică şi nici o menţiune de limitare a dimensiunii fişierelor nu este
dată. Siff poate fi utilizat la:

● Compararea diferitelor versiuni de program pentru plagiat,


● Găsirea fişierelor duplicate dintr-o structură mare de date,
● Găsirea de fişiere similare de pe Internet pentru a îmbunătăţi căutarea şi pentru a reduce
vizitarea fişierelor din directoare (ex ftp directoare) în care ar putea exista fişiere similare cu
cele deja vizitate,
● Pentru editori pentru a detecta plagiatul,
● Pentru cadre universitare care doresc să detecteze plagiatul în temele studenţilor,

2. Mai multe informaţii pot fi obţinute de la: http://glimpse.arizona.edu/javadup.html

22
● Pentru gruparea fişierelor similare înainte de a fi comprimate,
● Compararea reviziilor de fişiere de pe calculatoarele de acasă, de la muncă sau portabile.

Îmbunătăţiri viitoare ce ar putea fi aduse sunt selectarea, într-un mod mai "inteligent", de ancore
reprezentative pentru conţinutul fişierului (de exemplu, utilizând cuvinte "importante" din document),
precum şi compararea numai a textului nu şi a modului de formatare. De asemenea, ar fi benefice mai
multe studii empirice pentru a determina dimensiunea ferestrei sumei de control.

23
2.7. MOSS

Moss (Measure of Software Similarity) a fost dezvoltat în 1994 de Alex Aiken la Berkeley ca
un sistem de măsurare a similitudinii dintre coduri sursă scrise în C, C++, Java, Pascal, Ada, ML, Lisp
sau Scheme. Scopul principal a fost detectarea plagiatului la orele de programare. Acest instrument este
furnizat ca un serviciu Internet şi fiind dată o listă cu fişierele sursă, întoarce o pagină HTML cu o listă
de perechi de programe similare.

Codul furnizat de profesor şi bibliotecile pot fi eliminate din testele de similitudine pentru a
elimina "pozitivele false" - adică linii de cod despre care se crede că sunt plagiate atunci când, de fapt,
nu sunt.

Algoritmul [7] poate fi descris de aceste faze:

● Înlocuieşte toate spaţiile şi semnele de punctuaţie din fiecare fişier cod-sursă şi converteşte
toate literele în minuscule.

● Divide caracterele diferite de spaţiu rămase din fiecare fişier în k-grame, care sunt subşiruri
contigue de lungime k, prin baleierea unei ferestre de dimensiune k prin fişier. În acest fel, cel
de-al doilea caracter din prima k-gramă, este primul caracter al celui de-al doilea k-gram, şi aşa
mai departe.

● Se calculează o valoare hash pentru fiecare k-gram şi se selectează un subset al tuturor k-


gramelor pentru a fi amprentele digitale ale documentului. Amprenta digitală include informaţii
despre poziţia în document a fiecărui k-gram selectat.

● Compară fişierul de amprente digitale pentru a găsi fişiere similare.

24
2.8. DUP

DUP este o tehnică dezvoltată de Brenda Baker care găseşte lungi secţiuni de cod sursă care
aproape se potrivesc. Tehnica foloseşte ideea unei potriviri parametrizate (sau p-match), care va
potrivi două segmente de cod dacă textual sunt aceleaşi, dar conţin simple modificări a numelor de
variabilă. Utilizatorul specifică o lungime prag până la care DUP rapoartează toate p-match-urile între
fişiere. Rezultatul este procentul de duplicare dintre cele două fişiere împreună cu un profil al
potrivirilor din fiecare linie de intrare şi locul unde apar.

P-match-urile sunt calculate folosind arbori de sufix parametrizaţi (p-suffix tree), care
reprezintă de fapt codificarea sufixelor şirului de tokeni sub forma unui trie compactat. Un trie este
pur şi simplu o structură de arbore unde fiecare nod reprezintă un caracter şi rădăcina reprezintă şirul
vid. Avantajul acestei reprezentări este că timpul de căutare a unui şir de caractere este liniar şi
procesul de a construi şi de a adăuga mai multe elemente arborescente este foarte uşor.

DUP este capabil să identifice p-match-urile prin înlocuirea token-urilor reali, cum ar fi
identificatorii, cu offset-ele lor. Aceasta elimină identitatea, dar păstrează diferenţierea la diferiţi
identificatori. Prima apariţie a unui identificator se înlocuieşte cu 0, apoi apariţiile se înlocuiesc cu
numărul de tokeni până la cel precedent. De exemplu, date fiind două segmente de cod: u(x,y) =
(x>y)?x:y şi v(w,z) = (w>z)?w:z, ambele ar fi codificate ca 0(0,0) = (6>6)?5:5, deoarece u şi v apar în
aceleaşi poziţii, la fel ca şi perechile (w,x) si (y,z).

Alte utilizări ale arborilor de sufixe sunt:


● Depistarea tuturor apariţiilor lui q ca subşir al lui S
● Găsirea celui mai lung subşir comun al unei mulţimi de şiruri S1 .. Sk
● Găsirea celui mai lung palindrom în S
● Găsirea celui mai lung şir repetat într-un text.

De asemenea, DUP a fost folosit la întreţinere software în găsirea de secţiuni de cod identice (cu
excepţia modificării sistematice de parametri) şi detectare de plagiat.

25
3
2.9. BANDIT

Acest instrument a fost dezvoltat de Malcolm Shute, Koshor Mistry, Haydn Robinson şi Adrian
Vest în cadrul laboratorului de programare denumit ARCADE, la Universitatea Victoria din
Manchester. Instrumentul colectează lucrările studenţilor şi caută cod sursă copiat între lucrările
curente şi anterioare ale studenților.

Codul, de cel puţin câteva zeci sau sute de linii, este defalcat într-un flux de tokeni lexicali,
independent de comentarii şi nume de variabile. Similitudinea dintre fişierele sursă este apoi detectată
prin compararea fluxurilor de tokeni şi căutarea de secvenţe de token-uri similare. Căutarea secvenţelor
similare se face folosind o tehnică Dotplot unde fluxul de tokeni al unuia dintre programe este desenat
pe axa Ox şi fluxul de tokeni pentru celălalt program este desenat pe axa Oy. O cruce este plasată în
locul în care doi tokeni se potrivesc. Detectorul caută diagonale neîntrerupte care indică secvenţe de
tokeni comuni. Metoda este rezistentă la reaşezarea token-urilor deoarece diagonalele întrerupte
corespund inserării, ştergerii sau reaşezării de tokeni şi pot fi uşor observate. Acest instrument este
dependent de limbaj doar în ce priveşte tokenizarea, restul analizei fiind relativ generic.

Bandit întoarce o listă de secvenţe de potrivire descrise prin lungimea şi poziţia în cadrul
surselor. Cu cât lungimea e mai mare, cu atât acest lucru este mai semnificativ. În general, cazurile cele
mai suspecte sunt trase către vârf. Bandit scoate un grafic al programelor vs. scorul de similitudine ce
poate fi folosit pentru a identifica rapid potenţialele programe suspecte.

Bandit dispune, de asemenea, de o interfaţă grafică în care programele pot fi cercetate cu


uşurinţă pentru detectarea plagiatului.

Autorii pretind că singura modalitate de a păcăli Bandit este de a rearanja toţi tokenii din program
astfel încât să nu mai rămână nici o corespondenţă structurală suspectă, acţiune care ar necesita o
profundă înţelegere a codului sursă (ceea ce este oricum de dorit de la o temă de programare). În cei
patru ani de test la Manchester, detectorul a prins un număr de studenţi care au efectuat plagiat.

Un alt rezultat scontat a fost evidenţierea studenţilor care se zbat cu cursul dar nu cer ajutor,
întrucât aceste persoane copiază, în general, ca nişte amatori şi sunt, prin urmare, mai uşor de prins.

3. Mai multe informații la: http://wwwipd.ira.uka.de:2222/ și http://socrates.cs.man.ac.uk/~ajw/pd.html

26
2.10. COGGER

Cogger (un slang anglo-irlandez desemnând cuvântul temă sau alte exerciţii) vine cu o abordare
neobişnuită în detectarea plagiatului în temele de programare, folosind o abordare Case Based
Reasoning (CBR). Problema găsirii similarităţilor în programe devine analoagă cu problema regăsirii
de cazuri în CBR.

În CBR obiectivul este de a căuta similaritatea dintre cazuri pentru a permite refolosirea de
soluţii vechi în situaţii noi. Similaritatea dintre cazuri se poate baza pe caracteristici de suprafaţă sau
caracteristici mai abstracte şi structurale. Aceste caracteristici sunt utilizate pentru a crea un profil care
poate fi folosit pentru comparaţie.

O metodă numită Filtrarea de bază este utilizată pentru a selecta un mic grup de candidaţi din
cazul de bază care sunt similari cu cazul avut ca obiectiv. Aceasta devine o problemă de clasificare şi
tehnici cum ar fi cel mai apropiat vecin sau arbori de decizie pot fi folosiţi. Principala diferenţă între
tehnici este dacă toate cazurile de bază trebuie sa fie cercetate. Cogger foloseşte un tip de arbore de
decizie.

În ceea ce priveşte detectarea plagiatului, Cogger reprezintă programele ca un şir de caractere şi


încearcă să găsească subşiruri comune. Caracteristicile superficiale utilizate au fost pur şi simplu
frecvenţa identificatorilor în cadrul programelor. Această abordare s-a dovedit ineficientă, astfel că,
apoi s-au folosit doar frecvenţele cuvintelor rezervate. Deşi e o ameliorare, tot nu e suficient de eficace
pentru multe cazuri de plagiat. Reprezentarea finală pentru profil a fost folosirea a cât mai puţinor
cuvinte cheie previzibile.

Rezultatele testelor sunt foarte vagi şi nu sunt date rate de succes.

27
2.11. CodeMatch

Plague, Yap şi JPlag pot fi descrişi în termeni generali ca folosind următorul algoritm în trei faze.
Fiecare program utilizează metode diferite pentru fiecare fază, dar în esenţă, paşii sunt aceiaşi:

● Eliminarea comentariilor, numele identificatorilor, precum şi spaţiile.

● Înlocuirea codului cu o secvenţă de tokeni.

● Compararea secvenţelor de tokeni pentru a găsi similitudinile.

În prima fază, toate comentariile sunt eliminate. De asemenea, numele identificatorilor cum ar fi
numele de variabile şi de funcţii sunt aruncate. Spaţiile sunt eliminate. În cea de-a doua fază,
construcţiile specifice limbajului de programare se înlocuiesc cu tokeni generici care descriu
funcţionalitatea de bază a programului. În cea de-a treia etapă, secvenţele de tokeni sunt comparate
pentru a găsi potriviri.

Există o serie de probleme în acest tip de abordare:

● Aceste programe sunt dificil de adaptat la noile limbaje de programare, deoarece sunt atât de
dependente de cunoştinţe expert despre limbajul de programare în care a fost scris codul sursă.

● Ele sunt vulnerabile la schimbarea ordinii liniilor de cod în codul sursă.

● Ele renunță la informaţii utile atunci când înlătură comentarii, nume de variabile, nume de
funcţii şi alți identificatori.

Al doilea punct este o problemă particulară, deoarece secţiuni întregi de cod pot fi rearanjate şi linii
individuale pot fi reordonate pentru a păcăli aceste programe să dea scoruri mai mici.

Cel de-al treilea punct este o problemă deoarece comentariile, numele de variabile, numele de
funcţii şi alţi identificatori pot fi utili în detectarea plagiatului. Aceşti identificatori pot fi folosiţi pentru
a repera imediat codul copiat. Chiar şi în multe cazuri de copiere intenţionată, comentariile sunt lăsate
din greşeală în codul copiat şi pot fi folosite pentru a găsi potriviri. Greşeli ortografice comune sau
folosirea de cuvinte particulare pe parcursul programului în două coduri sursă pot ajuta la identificarea
lor, ca având acelaşi autor, chiar dacă structura codului în sine nu se potriveşte. În cazul Cadence vs.
Avant!, în care Avant! a fost găsit vinovat de furt de cod de la Cadence Design Systems, codul de la
programele ArcCell şi Aquarius includea în comentarii cuvinte greşit ortografiate în acelaşi mod ca şi
comentariile din codul programului Symbad de la Cadence. Se pare că secţiuni din cod au fost rescrise

28
dar multe comentarii au rămas. A fost dovedit astfel faptul că Avant! nu a început dezvoltarea de cod
de la zero, ci a avut o bază de plecare prin însuşirea de cod sursă străin în mod ilegal. ("'Smoking gun'
presented at Avant! restitution hearing," EE Times, 27 iunie 2001) Ignorarea comentariilor şi numele
identificatorilor este o problemă comună instrumentelor anti-plagiat.

CodeMatch [10], un program scris de Bob Zeidman, are o abordare complet diferită în detecţia pla-
giatului faţă programele descrise anterior. În primul rând, CodeMatch compară caracteristici din fiecare
pereche de fişiere sursă prin analizarea lor completă, nu doar prin compararea unui număr mic de
mostre de cod hash-uite. Aceasta poate cere programului să ruleze ore întregi sau în unele cazuri chiar
zile pentru a găsi cazurile de plagiat în seturi consistente de fişiere mari. Având în vedere miza în multe
cazuri de furt de proprietate intelectuală, timpul de procesare poate rămâne totuşi o a doua prioritate.
Însă este cu siguranţă mai puţin costisitor decât angajarea unor experţi care să studieze codul manual.

În al doilea rând, CodeMatch face apel la cunoştinţe despre limbajele de programare şi la structura
programelor pentru a îmbunătăţi rezultatele. Există o cantitate mică de informaţii necesare, sub forma
unei liste de construcţii specifice a limbajului de programare pe care CodeMatch trebuie să le re-
cunoască. Această listă este specifică limbajului de programare examinat. În plus, CodeMatch are
nevoie de informaţii cu privire la caracterele care sunt folosite pentru a identifica comentarii şi carac-
terele folosite ca separatori.

CodeMatch foloseşte o combinaţie de cinci algoritmi pentru a detecta plagiatul: potrivire linii de
cod, potrivire linii de comentariu, potrivire cuvinte, potrivire parţială de cuvinte şi potrivire secvenţă
semantică. Fiecare algoritm este util în găsirea diferitor indicii de plagiat, indicii ce pot scăpa celorlalţi
algoritmi. Prin utilizarea tuturor celor cinci algoritmi, şansele de a nu identifica codul plagiat sunt
diminuate semnificativ. Înainte de aplicarea oricărui algoritm, se fac nişte preprocesari pentru a crea
nişte şiruri de string-uri. Fiecare fişier este reprezentat de trei şiruri a€“
un şir de linii de cod care constă
în liniile de cod din sursa funcţională şi nu include comentarii; un şir de linii de comentariu care nu
include cod funcţional; şi un şir de identificatori găsiţi în codul sursă. Identificatorii includ nume de
variabile, constante, funcţii, precum şi orice alte cuvinte care nu sunt cuvinte-cheie ale limbajului de
programare.

Potrivire cuvinte

Pentru fiecare pereche de fişiere, algoritmul CodeMatch - Potrivire cuvinte contorizează


numărul de potriviri de cuvinte care nu sunt cuvinte cheie ale limbajului de programare. Pentru a
determina dacă un cuvânt este un cuvinte cheie al limbajului, se face comparaţia cu o listă deja
existentă de cuvinte cheie. De exemplu, cuvântul while dintr-un fişier sursă C ar fi ignorat ca şi cuvânt
cheie după acest algoritm. În unele limbaje de programare cum ar fi C şi Java, se face distincţia între
majuscule şi minuscule. CodeMatch are un parametru care-i indică dacă trebuie sau nu să facă această

29
distincţie în funcţie de limbajul examinat. Deci, pentru un limbaj ca C, cuvântul While nu va fi
considerat cuvânt cheie şi deci nu va fi ignorat. Într-un limbaj cum e Basic, însă, cuvântul While va fi
considerat cuvânt cheie şi va fi ignorat. În orice caz, compararea cuvintelor neignorate de algoritm nu
ţine seama de diferenţa dintre majuscule şi minuscule. Acest lucru se face pentru a preveni simple
tentative de fraudă prin modificări ale literelor din majusculă în minusculă sau invers.

Potrivire parţială de cuvinte

Algoritmul CodeMatch - Potrivire parţială de cuvinte analizează fiecare cuvânt dintr-unul din
fişiere care nu este cuvânt cheie şi găseşte dacă există măcar un cuvânt din celălalt fişier care conţine
primul cuvânt ca sub-cuvânt. Ca şi algoritmul Potrivire cuvinte, nu se face distincţia între majuscule şi
minuscule. Figura 6 arată rezultatele acestui algoritm pe un exemplu.

(a)

Word1[0] = "abc" Word2[0] = "Aabc"


Word1[1] = "abc1" Word2[1] = "aBc"
Word1[2] = "abc123" Word2[2] = "abc1111111"
Word1[3] = "abcdef" Word2[3] = "abcXXXyz"
Word1[4] = "pdq" Word2[4] = "i"
Word1[5] = "xxx" Word2[5] = "j"
Word1[6] = "xyz" Word2[6] = "pdq"
Word1[7] = "yyy" Word2[7] = "X"

(b)

PartialWord[0] = "abc"
PartialWord[1] = "abc1"
PartialWord[2] = "xxx"
PartialWord[3] = "xyz"

Fig. 6: Potrivire partială de cuvinte (a) Cuvintele cu excepţia cuvintelor-cheie din fişierele 1 şi 2; (b)
cuvintele care s-au potrivit parţial.

În figura 6(a) sunt afişate toate cuvintele din cele două fişiere cu excepţia cuvintelor cheie. În
figura 6(b), este listat fiecare cuvânt dintr-un fişier care poate fi găsit ca sub-cuvânt al unui cuvânt din
celelălt fişier. Deci, cuvântul abc în fişierul 1 poate fi găsit în cuvintele aabc, abc1111111, şi abcxxxyz
din fişierul 2. A se reţine că cuvântul pdq nu este listat deoarece se potriveşte cu un cuvânt complet şi a
fost deja luat în considerare în algoritmul Potrivire cuvinte. De asemenea, a se reţine că x nu este listat
deoarece cuvintele de lungime 1 sunt ignorate, fiind prea comune.

30
Potrivire linii de cod

Algoritmul CodeMatch - Potrivire linii de cod compară fiecare linie de cod din ambele fişiere,
ignorând diferenţa dintre majuscule şi minuscule. Se iau în considerare doar liniile de cod funcţionale,
liniile de comentariu se exclud. De asemenea, secventele de spaţii albe sunt transformate într-un singur
spaţiu astfel ca structura sintactică a liniei să se păstreze. Notaţi că o linie de cod sursă poate avea un
comentariu la sfârşit. Comentariul este eliminat pentru această comparaţie. Liniile de cod care conţin
doar cuvinte-cheie ale limbajului de programare se ignoră. Pentru ca să se considere că două linii de
cod se potrivesc ele trebuie să conţină cel puţin un cuvânt care nu e cuvânt-cheie cum ar fi un nume de
variabilă sau funcţie. Altfel, liniile care conţin operaţii de bază va fi raportat ca se potrivesc. Figura 7
arată două fişiere împreună cu liniile considerate de către algoritm că se potrivesc.

(a)

File 1 File 2
1 /* ---- begin routine ---- */ 1 /* find the file extension */
2 void fdiv( 2 void file_divide(
3 char *fname, // file name 3 char *fname,
4 char *path) /* path */ 4 char *path)
5 { 5 {
6 int Index1, j; 6 int i, j;
7 7 while (1) // loop here
8 while (1) 8 j = strlen(fname);
9 j = strlen(fname); 9
10 // find the file extension 10

(b)

File 1 File 2
3 char *fname, // file name 3 char *fname,
4 char *path) /* path */ 4 char *path)
9 j = strlen(fname); 8 j = strlen(fname);

Fig. 7: Potrivire linii de cod. (a) 2 fişiere; (b) liniile care se potrivesc

Potrivire linii de comentariu


Algoritmul CodeMatch - Potrivire linii de comentariu compară fiecare linie de comentariu din
ambele fişiere, ignorând din nou dacă e vorba de literă mică sau mare. Ca şi mai înainte, secventele de
spaţii albe sunt transformate într-un singur spaţiu astfel ca structura sintactică a liniei să se păstreze.
Notaţi că o linie de cod sursă poate avea un comentariu la sfârşit. Bucata de cod funcţional este

31
eliminată pentru această comparaţie. Se compară întregul comentariu, indiferent dacă există cuvinte
cheie în comentariu sau nu. Figura 8 arată două fişiere împreună cu liniile de comentariu considerate de
algoritm că se potrivesc.

(a)

File 1 File 2
1 /* begin routine */ 1 /* find the file extension */
2 void fdiv( 2 void file_divide(
3 char *fname, // file name 3 char *fname,
4 char *path) /* path */ 4 char *path) // path
5 { 5 {
6 int Index1, j; 6 int i, j; /* begin routine */
7 7 while (1) // loop here
8 while (1) 8 j = strlen(fname);
9 j = strlen(fname); 9
10 // find the file extension 10 switch (x)
11 if (x == 5) { 11 {

(b)

File 1 File 2
1 /* begin routine */ 6 int i, j; /* begin routine */
4 char *path) /* path */ 4 char *path) // path
10 // find the file extension 1 /* find the file extension */

Fig. 8: Potrivire linii de comentariu. (a) 2 fişiere; (b) liniile de comentariu care se potrivesc
Potrivire secvenţă semantică

Algoritmul CodeMatch - Potrivire secvenţă semantică compară primul cuvânt de pe fiecare


linie din cele două fişiere, ignorând liniile goale şi liniile de comentariu. Acest algoritm găseşte
secvenţe de cod care par să execute aceleaşi funcţii în ciuda unor comentarii şi identificatori schimbaţi.
Algoritmul găseşte cea mai lungă secvenţă semantică comună din cele două fişiere. A se urmări
exemplul din figura 9.

File 1 File 2
1 if (x == 5) 1 if (xyz < 2)

32
2 { 2 for (jjj = 0; jjj < i; jjj++)
3 // Loop on j here 3 {
4 for (j = 0; j < Index; j++) 4 printf("Hello world\n");
5 printf("x = %i", j); 5 }
6 } 6 else
7 else 7 while (i > 3) i--;
8 while (i < 5) i++; 8

Fig. 9: Potrivire secvenţă semantică

Secvenţa de linii din cele două fişiere se potriveşte deoarece primul cuvânt este identic după ce
se scot liniile goale, spaţiile albe şi semnele de punctuaţie. Acest algoritm produce un scor care
reprezintă numărul de linii din cea mai lungă secvenţă semantică comună.

Scorul final

În final, un singur scor este dat pentru asemănarea perechilor de fişiere. Dacă o pereche de
fişiere are un scor mai mare înseamnă că aceste fişiere sunt mai similare şi pot fi copiate una de la alta
sau de la un al treilea fişier. Scorurile date de fiecare din cei cinci algoritmi individuali sunt ponderate
şi apoi adunate pentru a obţine scorul final. Aceste ponderi pot fi ajustate pentru a da rezultate optime.

Cu timpul, aceste ponderi au fost modificate prin compararea rezultatelor pentru fişiere în care
codul a fost copiat şi mascat. Cu toate acestea, spre deosebire de alţi algoritmi, CodeMatch nu
intenţionează să ofere un anumit scor prag pentru similitudine. CodeMatch produce un raport HTML
cu lista de perechi de fişiere ordonate după scorul lor total. Utilizatorii pot face clic pe un hyperlink al
perechii de fişiere pentru a ajunge la un raport HTML detaliat care arată potrivirile exacte dintre
fişierele selectate. În acest fel, experţii sunt direcţionaţi către similarităţi suspecte pentru a putea lua
propriile hotărâri. CodeMatch nu este un instrument care să identifice exact codul plagiat, ci mai
degrabă un instrument care să asiste un expert în găsirea codului copiat. CodeMatch reduce efortul
necesar, permiţând expertului să se concentreze, nu pe sute de mii de linii de cod în sute de fişiere ci pe
zeci de linii de cod în zeci de fişiere.

33
2.12. SID

SID provine de la Shared Information Distance sau Software Integrity Detection. Detectează
similitudinea dintre programe calculând cantitatea de informaţie partajată dintre ele. A fost iniţial un
algoritm dezvoltat pentru a compara cât de similari sau diferiţi sunt genomii. S-a constatat mai târziu că
acest algoritm ar putea fi extins la multe alte aplicaţii, inclusiv către uneltele anti-plagiat. Grupul de
bioinformatică de la Universitatea din California, Santa Barbara şi grupul de bioinfomatica de la
Universitatea Waterloo l-au aplicat în detecţia de plagiat de cod sursă. În prezent suportă cod sursă scris
în Java şi C++.

Pentru compararea a două programe, algoritmul din spatele aplicaţiei SID calculează cantitatea
de informaţie partajată dintre cele două programe. Pentru a realiza acest lucru, se face uz de conceptul
de complexitate Kolmogorov [5].

n
Complexitatea Kolmogorov C(s) a unui şir binar oarecare s ∈ {0, 1} este lungimea celui mai
scurt program care produce acest şir pe o maşină Turing universală (MTU) şi apoi se opreşte. Cu alte
cuvinte, pe o MTU, C(s) biţi de informaţie sunt necesari pentru codarea lui s. Maşina Turing nu este un
calculator real, ci o maşină imaginară de referinţă. Detaliile specifice ale MTU sunt irelevante. Cum
orice maşină Turing poate să fie implementată pe oricare alta, lungimea minimă a unui program pe o
maşină va adăuga doar o constantă la lungimea minimă a programului pe orice altă maşină. Această
constantă este lungimea implementării primei maşini pe cealaltă maşină şi este independentă de şirul în
cauză. Aceasta s-a observat prima data în 1964 de către Ray Solomonoff.

Experienţa a arătat că fiecare încercare de a construi un model teoretic de calcul mult mai
puternic decât maşina Turing a ajuns la ceva care este cel mult la fel de puternic ca maşina Turing.
Acest lucru a fost afirmat în 1936 de către Alonzo Church în teza lui Church: clasa de funcţii numerice
calculabile algoritmic coincide cu clasa de funcţii parţial recursive. Tot ce se poate calcula putem
calcula cu o maşină Turing şi ce nu putem calcula cu o maşină Turing nu putem calcula deloc. Aceasta
fiind spusă, se poate folosi complexitatea Kolmogorov ca măsură universală care va atribui aceeaşi
valoare pentru orice secvenţă de biţi, indiferent de modelul de calcul, în cadrul limitelor unei constante
aditive.

Complexitatea Kolmogorov condiţională K(s | a) este definită ca fiind lungimea celui mai scurt
program care produce la ieşire pe o MTU sirul s atunci cand şirul a este dat pe o bandă auxiliară. K(s)
este cazul special K(s | ε) cand banda auxiliară este goală.

Deci, SID defineşte distanta informaţiei partajate dintre două programe X şi Y astfel:

34
K(X) - K(X|Y)
D(X,Y) =
K(XY)
unde K(X|Y) este complexitatea Kolmogorov a lui X fiind dat Y. Când Y este vid, aceasta devine
K(X). K(X)-K(X|Y) este informaţia mutuală dintre X şi Y --- adică măsoară cantitatea de informaţie pe
care Y o "cunoaşte" despre X. Este bine cunoscut faptul că informaţia mutuală este simetrică. Cu toate
acestea ea nu satisface inegalitatea triunghiului şi nu este o distanţă. Însă, D(X,Y) este o distanţă bine
definită şi este demonstrabil că este, de asemenea, universală.

35
4
2.13. Sherlock

Sherlock a fost dezvoltat la Universitatea din Warwick, Departamentul de Informatică.


Programul a fost pe deplin integrat în sistemul software online BOSS în 2002 devenind apoi open-
source. Detectează plagiatul în coduri-sursă şi în lucrări scrise în limbaj natural.

Fig. 10 – Sherlock: preprocesarea (spaţii albe, comentarii, normalizare, token-izare)

4. Pagina web a BOSS: www.boss.org.uk

36
Fig. 11 – Sherlock: rezultatele comparaţiei

37
3. ALGORITMUL FOLOSIT DE ANACOS

3.1. Generalități

AnaCoS se înscrie în categoria sistemelor ca Plague, YAP, JPLag întrucât se bazează, în


principal, tot pe ideea de token-izare. Include, totuși, înainte de token-izare, o scurtă etapă menită să
ajute la comparație.

Fazele algoritmului sunt:


● Selectarea comentariilor și a numelor de identificatori în eventualitatea găsirii de potriviri.
● Token-izarea, însă spre deosebire de celelalte aplicații, în AnaCoS, această fază va genera două
fișiere: un fișier cu lista de tokeni și un fișier xml care va descrie structura sintactică
arborescentă a programului (arborele sintactic) în care nodurile vor fi etichetate tot cu tokeni.
● Procesarea listei de tokeni a fiecărui program prin expandarea fiecărei definiții de funcții doar la
primul apel, celelalte apeluri fiind înlocuite cu un token. Ideea este asemănătoare cu ideea
expandării funcţiilor din YAP. Această etapă este vitală pentru detectarea atacurilor de genul
spargerii funcţiilor în bucăți.
● Compararea listelor de tokeni care se face prin două metrici ce necesită timp O(n) și metrica
2
ușor modificată a celui mai lung subșir comun care necesită timp O(n ). Aceste metrici sunt
explicate în secțiunea 3.2.
● Compararea arborilor sintactici prezentată în secțiunea 3.3.
● Prima etapă precum și penultimele două, pentru fiecare algoritm aplicat, vor returna un scor
parțial al similarităţii programelor. Fiecare scor parțial este ponderat în funcție de algoritmul
care l-a obținut, iar scorul final de similaritate este obținut prin însumarea scorurilor parțiale.

Lista de tokeni predefinită conține un set minimal de tokeni foarte reprezentativi pentru

38
structura unui program. De asemenea, construcțiile sintactice pentru bucle vor mapa către un singur
token reprezentativ pentru loop-uri, la fel ca și construcţiile pentru condiții către un singur token pentru
instrucțiuni condiționale (de ex., if și case vor mapa amândouă către același token). Se preîntâmpină
astfel atacurile în care se înlocuiesc anumite construcții sintactice cu altele care fac același lucru.
De asemenea, algoritmul folosit de AnaCoS ia în calcul și situaţiile din cadrul laboratoarelor de
informatică în care profesorul distribuie la început studenţilor cod-sursă ce urmează să fie completat și
modificat de către studenți în cadrul unui exercițiu. În acest caz nu e de mirare că sursele studenţilor
vor părea foarte asemănătoare, soft-ul anti-plagiat putându-se păcăli ușor.

Pentru a preaîntâmpina această situație AnaCoS poate să treacă, la cerere, prin următoarele
etape:
● Generarea listei de tokeni și a arborelui sintactic pentru fișierul sursă ce a fost distribuit de către
profesor
● Găsirea celei mai lungi secvențe comune dintre lista de tokeni a codului distribuit și cea a
studentului și eliminarea acesteia din lista studentului, pentru fiecare cod-sursă ce trebuie
2
verificat. Timpul O(n ) pentru determinarea celei mai lungi secvențe comune este un timp bun
în acest caz deoarece nu se iau toate perechile de fișiere ci doar fișierele.
● Găsirea celui mai mare arbore comun dintre arborele sintactic al codului distribuit și cel al
studentului și eliminarea acestuia din arborele studentului. În cazul obținerii unei păduri de
arbori se adaugă o rădăcină fictivă de care să fie legată toți arborii orfani. Problema găsirii celui
mai mare arbore comun este cunoscută în literatura de specialitate ca problema calculării
distanței de editare dintre doi arbori (sau este într-o foarte strânsă legătură cu aceasta). AnaCoS
3
implementează un algoritm în O(n ) care rezolvă această problemă, iar detalii despre algoritm
sunt prezentate în secțiunea 3.3.

Încă un lucru ce trebuie menţionat este acela că utilizatorul poate să aleagă care dintre
algoritmii de comparare vor fi folosiți pentru calcularea scorului final în funcție de importanța situaţiei
de plagiat și de timpul avut la dispoziție. Acest lucru se întâmplă deoarece unii dintre algoritmii folosiți
pot fi destul de costisitori ca timp pentru date de intrare mai consistente.

În următoarele două secțiuni sunt date mai multe detalii despre algoritmii de comparare a
listelor de tokeni precum și a arborilor sintactici.

39
3.2. Compararea listelor de tokeni

Pentru compararea listelor de tokeni s-a recurs la două metrici implementabile în timp liniar și
la un algoritm pătratic, care deși e destul de costisitor ca timp, poate da rezultate foarte bune.

Cei trei algoritmi sunt:

● Se calculează pentru fiecare tip de token de câte ori apare într-un program. Această valoare se
scade din numărul ce reprezintă de câte ori apare token-ul în celălalt program. Toate aceste
rezultate obținute de la fiecare token sunt însumate iar valoarea obținută se scade din numărul
total de tokeni. Astfel, cu cât rezultatul obținut e mai mare cu atat e mai probabil ca cele doua
programe să se asemene. Practic, această metrică calculează în ce măsură cele două programe
folosesc același număr de tokeni din fiecare tip.

● Se calculează gradul de decalare al token-urilor de același tip. Astfel, pentru fiecare tip de token
se ia prima poziție pe care apare într-un program și se scade din valoarea primei poziții pe care
apare în celălalt program. La fel pentru a doua poziție, a treia poziție etc. până când una din liste
se termină. Toate aceste valori sunt adunate iar pentru tokenii rămași nepereche se adună un
anumit cost. Acest rezultat, la fel, se scade dintr-o constantă mare obținându-se scorul acestui
algoritm.

● Se calculează cea mai lungă secvență comună a celor două liste de tokeni. Această secvență este
eliminată din cele două liste și algoritmul se poate reaplica pe listele care au rezultat din
eliminarea secvenței comune. Reaplicarea se face de un număr de ori dat de utilizator sau
implicit de 5 ori. Cu cât lungimea listelor obținute în final e mai mică sau cu cât mai repede s-a
obținut o listă vidă cu atât programele sunt mai suspicioase din punctul de vedere al plagierii.
Posibilitatea de a reaplica algoritmul urmărește să demaște atacurile în care porțiuni de cod
independente între ele au fost rearanjate.

40
3.3. Compararea arborilor sintactici

În afară de o referință vagă la Jankowitz care a încercat să aplice ideea comparării arborilor
sintactici, nu s-au mai găsit informații despre alte tentative de acest tip, deși această idee a comparării
arborilor merită exploatată.

Comparând arborii ne putem face o imagine mult mai exactă asupra distanței dintre cele două
programe, pe când în cazul listei de tokeni asemănările trag după ele un grad mai mare de probabilitate
a similarităţii programelor originale. Iar autoarea acestei lucrări a identificat încă un avantaj al acestei
soluții: poate fi folosită împotriva atacurilor în care se rearanjează bucăți de cod indepdendete pentru că
este foarte probabil ca aceste bucăți de cod să aparțină unor noduri frați din arborele sintactic. Așadar,
rearanjarea lor ar însemna schimbarea ordinii unor noduri frați din arbore și nu o modificare prea
profundă a structurii arborelui.

Algoritmii de comparare implementați sunt de două tipuri: un algoritm care vede arborele
sintactic ca un arbore neetichetat și neordonat și ceilalți doi care îl văd ca un arbore etichetat și ordonat.
Cei trei algoritmi sunt:

● Primul algoritm, aparținând autoarei lucrării de față, are o complexitate bună, anume O(n log n)
și vede arborele sintactic ca un arbore neetichetat și neordonat. Prin verificarea, în acest mod, a
asemănării arborilor atacurile mai sus menționate sunt imediat depistate. Ideea de bază este că
pentru fiecare nod se sortează subarborii-fii ai lui în funcție de numărul de noduri din
subarbore, în caz de egalitate, în funcție de adâcime etc. După aceasta, structura arborilor poate
fi comparată printr-o simplă parcurgere.

3
● Al doilea algoritm, de complexitate O(n ), vede arborele sintactic ca un arbore etichetat și
ordonat și aparține lui Erik D. Demaine, Shay Mozes, Benjamin Rossman, and Oren Weiman
[4]. Acesta, de fapt, calculează distanța de editare dintre doi arbori.

Distanța de editare dintre doi arbori ordonați, cu rădăcină și cu noduri etichetate este costul
minim de a transforma un arbore în celălalt printr-o serie de operații elementare constând în
ștergerea și reetichetarea de noduri precum și inserarea de noduri noi. A se urmări figurile 12,
13 și 14.

Deși algoritmul este costisitor ca timp, reprezintă cel mai bun indicator pentru gradul de
asemănare dintre programele inițiale ale studenților.

41
Fig. 12: Reetichetarea

Fig. 13: Ștergerea

Fig. 14: Inserarea

3
● Al treilea algoritm, de complexitate O(n·k ), vede arborele sintactic tot ca un arbore etichetat și
ordonat și aparține lui Hélène Touzet [8]. Este un algoritm liniar pentru compararea de arbori
similari. Întoarce ca rezultat o mapare a nodurilor din cei doi arbori cu mai puțin de k erori,
dacă o astfel de mapare există. AnaCoS aplică acest algoritm pentru k = 3 implicit sau în funcție
de parametrul utilizatorului. Avantajul este că acest algoritm poate stabili rapid dacă cele două
programe sunt foarte asemănătoare.

42
4. PREZENTAREA APLICAŢIEI

AnaCoS este o aplicație bazată web, scrisă in limbaj PHP, sub Linux, care implementează
algoritmii prezentați mai sus. Cerințele tehnice sunt minimale. Aplicația permite utilizatorului
următoarele:

● Gestionarea unui director din care vor fi luate sursele pentru a fi comparate

● Selectarea unui fișier sursă care se presupune că a fost distribuit înainte studenților, dacă este
cazul

● Selectarea prin bifare a metricilor și algoritmilor care vor contribui la scorul final al comparării,
în funcție de timpul avut la dispoziție

● Compararea tuturor perechilor de surse din fișier

● Compararea unui singur fișier sursă cu toate sursele din director

● Vizualizarea unui tabel ordonat descrescător în funcție de scorul final în care sunt listate
perechile de surse ce au intervenit în comparare împreună cu scorul obținut pentru fiecare
metrică

● Vizualizarea unei perechi de surse ce a intervenit în comparare pentru identificarea elementelor


găsite ca fiind similare

43
Intern, pentru generarea token-urilor și a fișierului xml care dă arborele sintactic, AnaCoS
comunică cu parser-ul Elsa. Elsa este un parser de C/C++ și se bazează pe generatorul de parsere
Elkhound.

44
5. EVALUĂRI EMPIRICE PENTRU ANACOS

Vor fi incluse în fişierul PowerPoint care va însoţi prezentarea acestui document.

45
6. REZUMAT ŞI CONCLUZII

În această lucrare am vorbit despre:

● ce înseamnă plagierea software


● direcția pe care se înscrie aplicația AnaCoS în domeniul plagierii software
● un mic istoric al ideilor de soft anti-plagiat pentru surse școlare: evoluția de la sistemele bazate
pe numărare de atribute la sistemele bazate pe metrici structurale și care sunt aceste sisteme
● cele mai importante soft-uri anti-plagiat dezvoltate până acum împreună cu modul de utilizare și
mai important, algoritmii folosiți de ele pentru detectarea plagiatului
● algoritmul folosit de AnaCoS, aplicația dezvoltată de autoarea acestei lucrări, în toate detaliile
lui, cu avantaje și dezavantaje
● o scurtă descriere a aplicației propriu-zise

Trecând în revistă atâtea idei frumoase și încercări de a construi un sistem anti-plagiat puternic
putem constata că acest domeniu abia așteaptă să fie exploatat. Această lucrare se vrea a fi o cercetare
amplă a ideilor celor mai importante de până acum pe care cercetătorii le-au avut în această direcție și o
contribuție personală prin prezentarea câtorva idei importante implementate în aplicația AnaCoS.
Domeniul luptei virtuale împotriva plagierii software este un domeniu deopotrivă interesant și
tentant dar încă insuficient exploatat și sperăm că lucrarea de față constituie un mic pas înainte și o
încurajare spre o cercetare mai intensă a domeniului.

46
7. BIBLIOGRAFIE

[1] Bull, J. . Technical review of plagiarism detection software report. CAA, 2001
centre. Universitatea Luton. http://www.jisc.ac.uk/uploaded_documents/luton.pdf

[2] Cosma Georgina and Joy Mike, Source-code plagiarism: A UK academic perspective, Raport
Nr. 422, Departamentul de Informatică, Universitatea Warwick, 2006.
http://www.dcs.warwick.ac.uk/reports/422.htm

[3] Clough, Paul. "Plagiarism in Natural and Programming Languages: An Overview of Current
Tools and Technologies," Research Memoranda, CS-00-05, Departamentul de Informatică,
Universitatea Sheffield, UK, 2000

[4] Demaine, Erik D.; Mozes, Shay; Rossman, Benjamin; Weimann, Oren. An Optimal
Decomposition Algorithm for Tree Edit Distance, 2006

[5] Nannen,Volker. A Short Introduction to Kolmogorov Complexity, 2003,


http://volker.nannen.com/pdf/short_introduction_to_kolmogorov_complexity.pdf

[6] Prechelt, Lutz; Malpohl, Guido; Phlippsen, Michael. JPlag: Finding plagiarisms among a set of
programs, Raport Tehnic2000-1, Facultatea de Informatică, Universitatea Karlsruhe, 2000

[7] Schleimer, Saul; Wilkerson, Daniel S.; Aiken, Alex. Winnowing: Local Algorithms for
Document Fingerprinting, 2003, http://theory.stanford.edu/~aiken/publications/papers/sigmod03.pdf

[8] Touzet, Hélène. A linear tree edit distance algorithm for similar ordered trees, 2005

47
[9] Whale, Geoff. "Identification of Program Similarity in Large Populations," The Computer
Journal, Vol. 33, Number 2, 1990

[10] Zeidman, Bob. Tools and algorithms for finding plagiarism in source code, 2004,
http://www.ddj.com/architect/184405734

48

S-ar putea să vă placă și