Multiset Progettare specifica con identificazione delle eventuali astrazioni

  • Slides: 21
Download presentation
Multiset

Multiset

Progettare (specifica con identificazione delle eventuali astrazioni necessarie, incluse eccezioni, e implementazione) del tipo

Progettare (specifica con identificazione delle eventuali astrazioni necessarie, incluse eccezioni, e implementazione) del tipo di dato Multiset, multiinsieme di dati del medesimo tipo. In aggiunta al costruttore si abbiano come operazioni primitive insert, remove, isin. Si progetti poi il tipo di dato Max. Multiset che estende Multiset mantenendo aggiornato il valore che rappresenta la massima molteplicità degli elementi del multiinsieme. Provare che i metodi realizzati soddisfano l'invariante e la loro specifica.

Classe Multiset, Metodo isin public class Multiset { //OVERVIEW: un Multiset e' un insieme

Classe Multiset, Metodo isin public class Multiset { //OVERVIEW: un Multiset e' un insieme di elementi omogenei in //cui ogni elemento puo' occorrere piu' volte, es. {1, 5, 4, 1, 4}. //E' modficabile private vector els; private class type; //metodi public Multiset () { //EFFECTS: inizializza un multiinsieme vuoto els=new vector(); } public boolean isin(Object x) { //EFFECTS: se x e' un elemento di this restituisce true, altrimenti //false if (x==null) return false; for (int i=0; i<els. size(); i++) { Pair p=(Pair)els. get(i); if (x. equals(p. left())) return true; } return false; }

Classe Multiset, Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast.

Classe Multiset, Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception { //EFFECTS: se x e' null solleva Null. Pointer. Exception, se x non e' omogeneo //agli elementi di this solleva Class. Cast. Exception, altrimenti inserisce x in //this //MODIFIES: this if (x==null) throw Null. Pointer. Exception(" "); if (els. size()==0) type=x. getclass(); else { if (!type. isinstance(x)) throw Class. Cast. Exception(" "); } if (!isin(x)) { Pair p=new Pair(x, new Integer(1)); els. add(p); } else { for (int i=0; i<els. size(); i++) { Pair q=(Pair) els. get(i); if (x. equals(q. left())) { int y=(Integer) q. right. int. Value(); y++; Pair p=new Pair(x, new Integer(y)); els. set(i, p); } } }

Classe Multiset, Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x

Classe Multiset, Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this //MODIFIES: this if (!isin(x)) return; for (int i=0; i<els. size(); i++) { Pair p=(Pair) els. get(i); if (x. equals(p. left())) { int y=(Integer) p. right(). intvalue(); y--; if (y>0) els. set(i, new. Pair(x, new Integer(y))); else els. remove(i); } }

Classe Multiset, Iterator elements protected Iterator elements() { //EFFECTS: ritorna gli elementi del multiinsieme

Classe Multiset, Iterator elements protected Iterator elements() { //EFFECTS: ritorna gli elementi del multiinsieme this nella //forma di coppie (elemento, molteplicita') return new Multiset. Gen(this); }

Classe Multiset. Gen private static class Multiset. Gen implements Iterator { //OVERVIEW: restituisce come

Classe Multiset. Gen private static class Multiset. Gen implements Iterator { //OVERVIEW: restituisce come Pair tutti gli elementi di un //multiinsieme che le viene passato private Multiset set; private int current; //metodi public Multiset. Gen(Multiset m) { //EFFECTS: inizializza set a m e current a 0 set=m; current=0; } public boolean hasnext() { //EFFECTS: se ci sono ancora elementi nel multiinsieme da //ritornare ritorna true, altrimenti false return (current<set. els. size()); } public Object next() throws No. Such. Element. Exception { //EFFECTS: restituisce il prossimo elemento del multiinsieme //se ce ne sono, altrimenti solleva un'eccezione if (current=set. els. size()) throw No. Such. Element. Exception; Pair p=(Pair) set. els. get(current); current++; return p; } }

Classe Max. Multiset, metodo maxmul public class Max. Multiset extends Multiset{ //OVERVIEW: un Max.

Classe Max. Multiset, metodo maxmul public class Max. Multiset extends Multiset{ //OVERVIEW: un Max. Multiset e' un Multiset che mantiene traccia //della massima molteplicita' dei suoi elementi private int max; //metodi public Max. Multiset () { //EFFECTS: richiama il costruttore di Multiset e inizializza la //molteplicita' massima a 0 super(); max=0; } public int maxmul() { //EFFECTS: restituisce il valore della molteplicita' massima return max; }

Classe Max. Multiset, metodi insert e remove public void insert (object x) throws Null.

Classe Max. Multiset, metodi insert e remove public void insert (object x) throws Null. Pointer. Exception, Class. Cast. Exception { //EFFECTS: richiama la insert di Multiset ed aggiorna la //molteplicita' massima //MODIFIES: this super. insert(x); max=0; aggiornamax(); } public void remove (object x) { //EFFECTS: richiama la remove di Multiset ed aggiorna la //molteplicita' massima //MODIFIES: this super. remove(x); max=0; aggiornamax(); }

Classe Max. Multiset, metodo aggiornamax private void aggiornamax() { //EFFECTS: aggiorna la molteplicita' massima

Classe Max. Multiset, metodo aggiornamax private void aggiornamax() { //EFFECTS: aggiorna la molteplicita' massima degli elementi //di this //MODIFIES: this Iterator g = elements(); while (g. hasnext()) { Pair p = (Pair)g. next(); if ((Integer) p. right. intvalue()>max) max = (Integer) p. right. intvalue(); } }

Funzione di astrazione e invariante a. Multiset(c) = S : c. els. get(i). left()

Funzione di astrazione e invariante a. Multiset(c) = S : c. els. get(i). left() occorre c. els. get(i). right. intvalue() volte in S i: 0 i<c. els. size IMultiset(c) = c. els null & (c. els. size()>0 c. type null) & i, j 0 i j < c. els. size() ( c. els. get(i). left(). get. Class()=c. type & c. els. get(i). right. intvalue()>0 & c. els. get(i). left() c. els. get(j). left() )

Funzione di astrazione e invariante a. Multiset. Gen(c) = [c. els. get(current). left(). .

Funzione di astrazione e invariante a. Multiset. Gen(c) = [c. els. get(current). left(). . c. els. get(c. set. els. size()-1). left() ] IMultiset. Gen(c) = c. set a. Multiset(c) & 0 c. current < c. set. els. size()

Funzione di astrazione e invariante a. Max. Multiset(c) = a. Multiset(c) IMax. Multiset(c) =

Funzione di astrazione e invariante a. Max. Multiset(c) = a. Multiset(c) IMax. Multiset(c) = c. max 0 & c. max>0 x a. Multiset(c)|x occorre c. max volte & x a. Multiset(c) la molteplicita' di x e' c. max

Costruttore public Multiset () { //EFFECTS: inizializza un multiinsieme vuoto els=new vector(); } Il

Costruttore public Multiset () { //EFFECTS: inizializza un multiinsieme vuoto els=new vector(); } Il costruttore della classe Multiset soddisfa l'invariante e la specifica (banalmente), infatti: IMultiset(c) = c. els null & (c. els. size()>0 c. type null) & i, j 0 i j < c. els. size() ( c. els. get(i). left(). get. Class()=c. type & c. els. get(i). right. intvalue()>0 & c. els. get(i). left() c. els. get(j). left() )

Metodo isin public boolean isin(Object x) { //EFFECTS: se x e' un elemento di

Metodo isin public boolean isin(Object x) { //EFFECTS: se x e' un elemento di this restituisce true, altrimenti //false if (x==null) return false; for (int i=0; i<els. size(); i++) { Pair p=(Pair)els. get(i); if (x. equals(p. left())) return true; } return false; } Il metodo isin soddisfa l'invariante (non modifica nulla) e la specifica: - se x=null x a(this) ed isin ritorna false - se x null e x a(this) allora nel ciclo for viene individuata la coppia (x, n) e isin ritorna true - se x null e x a(this) allora il ciclo for termina la sua esecuzione senza trovare alcuna coppia utile e isin ritorna false

Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception {

Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception { //EFFECTS: se x e' null solleva Null. Pointer. Exception , se x non e' omogeneo //agli elementi di this solleva Class. Cast. Exception , altrimenti inserisce x in //this //MODIFIES: this if (x==null) Il metodo insert soddisfa l'invariante: throw Null. Pointer. Exception(" "); if (els. size()==0) - se x=null solleva un'eccezione ed esce type=x. getclass(); - se x null ma x non e' omogeneo al tipo else { di this, il metodo solleva un'eccezione ed if (!type. isinstance(x)) throw Class. Cast. Exception(" "); } esce if (!isin(x)) { Pair p=new Pair(x, new Integer(1)); els. add(p); } else { Il metodo non effettua nessuna modifica. for (int i=0; i<els. size(); i++) { Assumendo vera l'invariante prima di Pair q=(Pair) els. get(i); if (x. equals(q. left())) { invocare il metodo, l'invariante rimane int y=(Integer) q. right. int. Value(); soddisfatta anche dopo l'esecuzione del y++; metodo. Pair p=new Pair(x, new Integer(y)); els. set(i, p); } } }

Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception {

Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception { //EFFECTS: se x e' null solleva Null. Pointer. Exception , se x non e' omogeneo //agli elementi di this solleva Class. Cast. Exception , altrimenti inserisce x in //this //MODIFIES: this Il metodo insert soddisfa l'invariante: if (x==null) - se x null e this e' vuoto inizializza this alla classe throw Null. Pointer. Exception(" "); if (els. size()==0) di x. c. els. size()>0 c. type null type=x. getclass(); e' soddisfatta, nel momento in cui un elemento e' else { inserito in this (c. els. size()>0) il tipo di this if (!type. isinstance(x)) throw Class. Cast. Exception(" "); } viene inizializzato (c. type null). if (!isin(x)) { Pair p=new Pair(x, new Integer(1)); - se x null e this e' del tipo di x inserisce x in els. add(p); } else { a(this) for (int i=0; i<els. size(); i++) { Pair q=(Pair) els. get(i); if (x. equals(q. left())) { Tutte le condizioni dell'invariante rimangono int y=(Integer) q. right. int. Value(); banalmente soddisfatte anche dopo l'esecuzione del y++; Pair p=new Pair(x, new Integer(y)); metodo. els. set(i, p); } } }

Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception {

Metodo insert public void insert(Object x) throws Null. Pointer. Exception, Class. Cast. Exception { //EFFECTS: se x e' null solleva Null. Pointer. Exception , se x non e' omogeneo //agli elementi di this solleva Class. Cast. Exception , altrimenti inserisce x in //this //MODIFIES: this if (x==null) throw Null. Pointer. Exception(" "); Il metodo insert soddisfa la specifica: if (els. size()==0) type=x. getclass(); - se x=null solleva un'eccezione ed esce else { - se x null e this e' di tipo diverso dal tipo di x if (!type. isinstance(x)) solleva un'eccezione ed esce throw Class. Cast. Exception(" "); } if (!isin(x)) { - se x null e this e' vuoto inizializza this alla classe Pair p=new Pair(x, new Integer(1)); di x. els. add(p); } - se x null e this e' del tipo di x: else { for (int i=0; i<els. size(); i++) { - se x this trova (x, y) e la aggiorna in (x, y+1) Pair q=(Pair) els. get(i); - se x this crea una nuova coppia (x, 1) e la if (x. equals(q. left())) { inserisce nel multiinsieme int y=(Integer) q. right. int. Value(); y++; Pair p=new Pair(x, new Integer(y)); els. set(i, p); } } }

Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this

Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this //MODIFIES: this if (!isin(x)) return; for (int i=0; i<els. size(); i++) { Pair p=(Pair) els. get(i); if (x. equals(p. left())) { int y=(Integer) p. right(). intvalue(); y--; if (y>0) els. set(i, new. Pair(x, new Integer(y))); else els. remove(i); } } Il metodo remove soddisfa l'invariante: - se x a(this) il metodo esegue una return senza fare nulla Assumendo vera l'invariante prima di invocare il metodo, l'invariante rimane soddisfatta anche dopo l'esecuzione del metodo.

Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this

Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this //MODIFIES: this if (!isin(x)) return; for (int i=0; i<els. size(); i++) { Pair p=(Pair) els. get(i); if (x. equals(p. left())) { int y=(Integer) p. right(). intvalue(); y--; if (y>0) els. set(i, new. Pair(x, new Integer(y))); else els. remove(i); } } Il metodo remove soddisfa l'invariante: - se x a(this) il metodo rimuove x da a(this) Tutte le condizioni dell'invariante rimangono banalmente soddisfatte anche dopo l'esecuzione del metodo. Si noti che le condizioni sono soddisfatte anche nel caso in cui x sia l'unico elemento di a(this), il tipo di this resta immutato e verra' cambiato solo ad una nuova chiamata di insert, poiche' this. set. els. size() sara' uguale a 0.

Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this

Metodo remove public void remove(Object x) { //EFFECTS: rimuove un'occorrenza di x da this //MODIFIES: this if (!isin(x)) return; for (int i=0; i<els. size(); i++) { Pair p=(Pair) els. get(i); if (x. equals(p. left())) { int y=(Integer) p. right(). intvalue(); y--; if (y>0) els. set(i, new. Pair(x, new Integer(y))); else els. remove(i); } } Il metodo remove soddisfa la specifica: - se x a(this) il metodo esegue una return senza fare nulla - se x a(this) il metodo cerca la coppia (x, y) e decrementa y - se y-1> 0 aggiorna la coppia (x, y) al valore (x, y-1) - se y-1=0 elimina la coppia (x, y) dal multiinsieme