A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Jpf@fe.up.pt www.fe.up.pt/~jpf Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (5ª parte) João Pascoal Faria jpf@fe.up.pt.

Apresentações semelhantes


Apresentação em tema: "Jpf@fe.up.pt www.fe.up.pt/~jpf Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (5ª parte) João Pascoal Faria jpf@fe.up.pt."— Transcrição da apresentação:

1 jpf@fe.up.pt www.fe.up.pt/~jpf
Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (5ª parte) João Pascoal Faria

2 Índice Especificação por pós-condições
Invocação explícita de pré e pós-condições Modelação de máquinas de estados e eventos temporais - exemplo da biblioteca * Modelação de input/output - exemplo da biblioteca Aplicação de VDM++ à descrição de algoritmos * Aplicação de VDM++ à descrição de algoritmos - exemplo da colocação de professores (cont.)

3 Especificação por pós-condições

4 Definição de funções Estilo 1 (baseado no estilo de função explícita de VDM-SL): f: A * B * … * Z -> R1 * R2 * … * Rn f(a,b,…,z) == bodyexpr pre preexpr(a,b,…,z) post postexpr(a,b,…,z,RESULT) ; Estilo 2 (baseado no estilo de função implícita de VDM-SL): f(a:A, b:B, …, z:Z) r1:R1, …, rn:Rn == bodyexpr pre preexpr(a,b,…,z) post postexpr(a,b,…,z,r1,…,rn) ;

5 Definição de funções Tanto a pré-condição (parte “pre …”) com a pós-condição (parte “post …”) são opcionais O corpo também é opcional “bodyexpr” pode ser substituído por “is not yet specified” No estilo 2, pode-se simplesmente omitir a parte “== bodyexpr”

6 Pós-condições de funções
Na maioria dos casos, omitimos a pós-condição, pois é trivialmente semelhante ao corpo, e este tem a vantagem de ser executável Pode-se sempre inferir a pós-condição trivial “RESULT = bodyexpr” Mas, se o corpo é muito mais complexo que a pós-condição, pode ser vantajoso escrever a pós-condição O corpo permite especificar o algoritmo a seguir na cálculo da função (é discutível se o paradigma funcional é o mais apropriado para este efeito …) A pós-condição permite especificar o objectivo da função e verificar o algoritmo Em alguns casos, a pós-condição também pode ser usada para especificar restrições a que deve obedecer o resultado, sem o fixar completamente Em qualquer caso, sempre que há pré-condições aplicáveis, estas devem ser formalizadas na parte “pre”

7 Definição de operações
Estilo 1 (baseado no estilo de operação explícita de VDM-SL): o: A * B * … ==> R o(a,b,…) == bodystmt pre preexpr(a,b,…, instvar1, instvar2, …) post postexpr(a,b,…,RESULT,instvar1, instvar2, …, instvar1~, instvar2~, …) ; Estilo 2 (baseado no estilo de operação implícita de VDM-SL): o(a:A, b:B, …, z:Z) r:R == bodystmt ext rd instvarx, instvary, … wr instvarz, instvarw, … pre preexpr(a,b,…, instvar1, instvar2, …) post postexpr(a,b,…,r,instvar1, instvar2, …, instvar1~, instvar2~, …) ;

8 Definição de operações
Corpo (bodysmt) é uma instrução ou bloco de instruções O corpo é opcional Pode ser substituído por “is not yet specified” ou “is subclass responsibility” No estilo 2, a parte “== bodystmt” pode ser simplesmente omitida A pré-condição (pre) é uma expressão booleana nos valores dos argumentos e das variáveis de instância A pós-condição (post) é uma expressão booleana nos valores dos argumentos, resultado, valores iniciais das variáveis de instância (com sufixo “~”) e valores finais das variáveis de instância (sem “~”) Tanto a pré-condição como a pós-condição são opcionais No estilo 2, quando se indica a pós-condição, é obrigatória indicar a cláusula “ext” (externals), que lista as variáveis de instâncias que são lidas (rd) e actualizadas (wr) no corpo da operação

9 Pós-condições de operações
Em muitos casos, omitimos a pós-condição, pois é trivialmente semelhante ao corpo, e este tem a vantagem de ser executável Caso de corpo na forma de uma sequência de atribuições Mas, se o corpo é muito mais complexo que a pós-condição, pode ser vantajoso escrever a pós-condição O corpo permite especificar o algoritmo a seguir na realização da operação A pós-condição permite especificar o objectivo da operação e verificar o algoritmo Em alguns casos, a pós-condição também pode ser usada para especificar restrições a que deve obedecer o resultado, sem existir a intenção de fixar completamente o resultado Em qualquer caso, sempre que há pré-condições aplicáveis, estas devem ser formalizadas na parte “pre”

10 Limitações das pós-condições
Por vezes, não se consegue exprimir devidamente o objectivo / efeito pretendido de uma operação pela pós-condição: Pós-condição permite exprimir retorno de valor e alteração do estado do objecto, mas não outros efeitos laterais (e.g. entrada e saída de dados) No caso de operações com “callbacks” (e.g. invocação de “event listeners” ou “event handlers”), quem escreve a operação não sabe o efeito resultante no estado do sistema. Nestes casos, o efeito pretendido é mais procedimental (exemplo: invocar todos os “event listeners” registados, por ordem de registo) Em VDM++, apenas é possível aceder ao valor inicial de variáveis de instância do próprio objecto, e da mesma classe (não é possível aceder ao estado inicial doutros objectos, nem ao valor inicial de variáveis de instância herdadas) Será sempre possível exprimir algumas restrições ao efeito da operação, mas nem sempre será possível exprimir totalmente o objectivo / efeito pretendido da operação Nesses casos, pode ser preferível exprimir esse efeito de forma mais imperativa no corpo Ver exemplo do alarme na Biblioteca! (projecto VDM\Biblioteca_v2.zip)

11 Invocação explícita de pré e pós-condições

12 Invocação explícita de pré e pós-condições de funções
Suponhamos uma função com assinatura f : T1 * ... * Tn -> Tr Se tiver pré-condição, é automaticamente criada uma função pre_f com assinatura pre f : T1 * ... * Tn +> bool Se tiver a parte de pré-condição, é automaticamente criada uma função post_f com assinatura post f : T1 * ... * Tn * Tr +> bool Estas funções (ou seja, a pré e pós-condição) podem ser invocadas explicitamente Ver exemplo no problema da colocação de professores Infelizmente, não existe algo semelhante para operações

13 Modelação de máquinas de estados e eventos temporais - exemplo da biblioteca

14 Requisitos Passada a data limite de levantamento de uma publicação, no seguimento de um pedido de empréstimo, o sistema deve automaticamente anular o pedido e disponibilizar a publicação para o próximo sócio que a tenha pedido, notificando ambos os sócios O sócio também pode anular o pedido

15 Modelo do ciclo de vida de um empréstimo
Evento temporal

16 Modelação de eventos temporais em VDM++
VDM++ não tem suporte nativo para eventos temporais Eventos temporais podem ser gerados por um relógio com alarme O padrão de desenho “Observer” pode ser usado na comunicação entre o relógio e os seus “clientes” Para efeito de modelação e teste, não é necessário usar a data do sistema, pode ser uma data simulada comandada pelo código de teste Para simplificar, vamos considerar que o relógio funciona de forma síncrona com o resto do sistema Posteriormente, o modelo pode ser refinado para o caso assíncrono, em que se teriam de tratar os problemas de concorrência

17 Modelo de estrutura estática
(notificação de sócios a tratar mais tarde)

18 Modelo de interacção (notificação de sócios a tratar mais tarde)
Também serve como especificação de um cenário de teste!

19 Classe “Clock” Modelação do estado (a vermelho tem a ver com alarmes):
class Clock types public Date = DateUtils`Date; instance variables private static curdate : Date := DateUtils`MakeDate(2000,1,1); private static alarms : map Date to seq of AlarmListener := { |-> }; private static changing_curdate : bool := false; -- não podem existir alarmes para datas passadas, nem para a data actual (a não -- ser transitoriamente enquanto se processam os alarmes após mudar a data) inv forall d in set dom alarms & if changing_curdate then d >= curdate else d > curdate; -- não podem existir “listeners” duplicados para a mesma data not SeqUtils`HasDuplicates[AlarmListener](alarms(d));

20 Classe “Clock” Definição de operações sobre a data corrente: …
operations public static GetCurDate() res : Date == return curdate; public static SetCurDate(date : Date) == ( while curdate < date do IncrCurDate() ) pre date >= curdate and not changing_curdate; public static IncrCurDate(n : nat1) == for i = 1 to n do pre not changing_curdate; Para não comprometer o processamento de alarmes!

21 Classe “Clock” Definição de operação auxiliar que incrementa a data corrente e dispara os alarmes, ilustrando a especificação da pós-condição e da cláusula “ext” associada: ... private static IncrCurDate() == ( changing_curdate := true; curdate := DateUtils`NextDate(curdate); while curdate in set dom alarms do ( dcl listener : AlarmListener := hd alarms(curdate); RemoveAlarm(listener, curdate); listener.AlarmFired() ); changing_curdate := false ) ext wr curdate, alarms, changing_curdate pre not changing_curdate post curdate = DateUtils`NextDate(curdate~) and curdate not in set dom alarms and not changing_curdate; -- pós-condição não formalizável: os listeners registados para a nova data (e -- não removidos até chegar a sua vez), têm de ter sido chamados (com a data -- já actualizada) pela ordem por que se registaram

22 Classe “Clock” Definição de operações para registar (adicionar) e remover alarmes (pós-condições omitidas): public static AddAlarm(listener : AlarmListener, date : Date) == ( if date in set dom alarms then alarms(date) := alarms(date) ^ [listener] else alarms := alarms munion { date |-> [listener] } ) pre date > curdate and not ExistsAlarm(listener, date); public static RemoveAlarm(listener : AlarmListener, date : Date) == alarms(date) := SeqUtils`Remove[AlarmListener](listener, alarms(date)); if alarms(date) = [] then alarms := {date} <-: alarms pre ExistsAlarm(listener, date); public static ExistsAlarm(listener : AlarmListener, date : Date) res: bool == return date in set dom alarms and listener in set elems alarms(date); end Clock

23 Classe “AlarmListener”
class AlarmListener operations public AlarmFired() == is subclass responsibility; end AlarmListener

24 Classe “Empréstimo” Modelação de estado (vista parcial):
class Empréstimo is subclass of AlarmListener instance variables -- Datas do empréstimo private dataRequisição : Date; private dataDisponibilização : [Date] := nil; private dataAnulação : [Date] := nil; private dataLimiteLevantamento : [Date] := nil; private dataLevantamento : [Date] := nil; private dataLimiteDevolução : [Date] := nil; private dataDevolução : [Date] := nil; -- Variáveis estáticas para numeração automática e prazos por omissão private static prazoLevantamento : nat1 := 2; private static prazoDevolução : nat1 := 7;

25 Classe “Empréstimo” Invariantes de estado (vista parcial):
-- A requisição não pode ser anterior à aquisição inv dataRequisição >= publicação.GetDataAquisição(); -- Ordem das várias datas (datas que não podem ser anteriores -- nem definidas antes doutras) inv DefinedAfter(dataDisponibilização, dataRequisição); inv DefinedAfter(dataLimiteLevantamento, dataDisponibilização); inv DefinedAfter(dataLevantamento, dataDisponibilização); inv DefinedAfter(dataLimiteDevolução, dataLevantamento); inv DefinedAfter(dataDevolução, dataLevantamento); -- A anulação não pode ser anterior à requisição e só é possível antes -- do levantamento, podendo ocorrer antes ou depois da disponibilização inv dataAnulação <> nil => dataAnulação >= dataRequisição and dataLevantamento = nil and (dataDisponibilização = nil or dataAnulação >= dataDisponibilização);

26 Classe “Empréstimo” Definição de operações (vista parcial):
-- Chamado internamente aquando da devolução ou anulação doutro empréstimo private Disponibilizar() == ( let d = Clock`GetCurDate() in dataDisponibilização := d; dataLimiteLevantamento := DateUtils`DateAdd(d, prazoLevantamento) ); Clock`AddAlarm(self, DateUtils`NextDate(dataLimiteLevantamento)) ) ext rd prazoLevantamento wr dataDisponibilização, dataLimiteLevantamento pre GetEstado() = <EsperaDisponibilidade> and self = publicação.GetPróximoPedido() post let d1 = Clock`GetCurDate(), d2 = DateUtils`DateAdd(d1, prazoLevantamento) in dataDisponibilização = d1 and dataLimiteLevantamento = d2 and Clock`ExistsAlarm(self, DateUtils`NextDate(d2)) and GetEstado() = <EsperaLevantamento>;

27 Classe “Empréstimo” -- (chamado de DateUtils quando o alarme dispara)
-- (nota: como herda de "public", tem de manter "public") public AlarmFired() == Anular() pre GetEstado() = <EsperaLevantamento> and Clock`GetCurDate() > dataLimiteLevantamento; -- Anular pedido de empréstimo (automaticamente pelo sistema, uma -- vez ultrapassada a data limite de levantamento, ou a pedido do sócio) public Anular() == ( dataAnulação := Clock`GetCurDate(); if GetEstado() = <EsperaLevantamento> then ( if Clock`ExistsAlarm(self, DateUtils`NextDate(dataLimiteLevantamento)) then Clock`RemoveAlarm(self, DateUtils`NextDate(dataLimiteLevantamento)); def e2 = publicação.GetPróximoPedido() in if e2 <> nil then e2.Disponibilizar() ) ext wr dataAnulação, dataLimiteLevantamento pre GetEstado() in set {<EsperaDisponibilidade>, <EsperaLevantamento>} post dataAnulação = Clock`GetCurDate() and GetEstado() = <Anulado> and not Clock`ExistsAlarm(self, DateUtils`NextDate(dataLimiteLevantamento)); -- e disponibilizou para o próximo!

28 Classe “Empréstimo” -- Levantar publicação cujo empréstimo tinha sido pedido (e o pedido não foi anulado) public Levantar() == ( dcl d : Date := Clock`GetCurDate(); Clock`RemoveAlarm(self, DateUtils`NextDate(dataLimiteLevantamento)); dataLevantamento := d; dataLimiteDevolução := DateUtils`DateAdd(d, prazoDevolução) ) ext wr dataLevantamento, dataLimiteDevolução, dataLimiteLevantamento rd prazoDevolução pre GetEstado() = <EsperaLevantamento> and sócio.GetEstado() = <Activo> and not sócio.TemDevoluçõesAtrasadas() post let d = Clock`GetCurDate() in dataLevantamento = d and dataLimiteDevolução = DateUtils`DateAdd(d, prazoDevolução) and GetEstado() = <EmCurso> and not Clock`ExistsAlarm(self, DateUtils`NextDate(dataLimiteLevantamento));

29 Classe “Empréstimo” -- Devolver publicação que tinha sido emprestada
public Devolver() == ( dataDevolução := Clock`GetCurDate(); def e2 = publicação.GetPróximoPedido() in if e2 <> nil then e2.Disponibilizar() ) ext wr dataDevolução pre GetEstado() = <EmCurso> post dataDevolução = Clock`GetCurDate() and GetEstado() = <Concluído>; -- e disponibilizou para o próximo! De que forma é que as pré-condições e pós-condições estão relacionadas com o diagrama de estados de um empréstimo? public GetEstado() res : EstadoEmpréstimo == return if dataAnulação = nil then <Anulado> else if dataDisponibilização = nil then <EsperaDisponibilidade> else if dataLevantamento = nil then <EsperaLevantamento> else if dataDevolução = nil then <EmCurso> else <Concluído>;

30 * Modelação de input / output – exemplo da biblioteca

31 Problema no exemplo da Biblioteca
Requisito: Sócio deve ser notificado nas seguintes situações: Publicação pedida já pode ser levantada Expirou prazo de levantamento, pelo que o pedido de empréstimo foi anulado Expirou prazo de devolução

32 Modelação e teste Para efeito de modelação e teste, as notificações podem ser simuladas Em vez de enviar as notificações, mantém-se um registo das notificações Nas pós-condições, pode-se consultar o registo de notificações Caso se pretenda uma solução reutilizável, podem-se definir duas classes genéricas: Notifiable – classe abstracta que representa um destinatário de notificações, e que tem definidas operações Notify (para realizar a notificação) e GetNotifications (para consultar historial de notificações) Notification – classe concreta que representa uma notificação genérica, com data e mensagem, e que pode ser especializada em subclasses

33 Modelo de estrutura estática

34 Geração e verificação de notificações
Exemplo de geração de notificação (no corpo) e verificação de notificação (na pós-condição) para um dos tipos de notificação: class Empréstimo … private Disponibilizar() == ( … sócio.Notify(new NotificaçãoBiblioteca(<PodeLevantar>, self)) ) … post exists x in set elems sócio.GetNotifications() & x.GetTipo() = <PodeLevantar> and x.GetEmpréstimo() = self;

35 Aplicação de VDM++ à descrição de algoritmos

36 Ordenação de uma sequência
-- Função de ordenação de uma sequência pelo algoritmo quick sort quicksort: seq of nat -> seq of nat quicksort(s) == cases s: [] > [], [x] > [x], [x, y] > if x < y then [x, y] else [y, x], - ^ [x] ^ - -> quicksort ([y | y in set elems s & y < x]) ^ [x] ^ quicksort ([y | y in set elems s & y > x]) end pre no_dups(s) post sorted(res) and same_elems(s, res); sorted(s: seq of nat) res : bool == forall i, j in set inds s & i < j => s(i) <= s(j); same_elems(s: seq of nat, t: seq of nat) res : bool == elems s = elems t; no_dups(s: seq of nat) res: bool == forall i, j in set inds s & i <> j => s(i) <> s(j); Fim aula de 16/Set/2005

37 Divisão inteira -- Operação de cálculo da divisão inteira à custa da multiplicação, -- adição e subtracção Divisao : nat * nat1 ==> nat * nat -- dá quociente e resto Divisao(dividendo, divisor) == ( dcl quociente: nat := 0; dcl resto: nat; while (quociente + 1) * divisor <= dividendo do quociente := quociente + 1; resto := dividendo – divisor * quociente; return mk_(quociente, resto) ) post let mk_(quociente, resto) = RESULT in resto >= 0 and resto < divisor and quociente * divisor + resto = dividendo;

38 Ordenação topológica de um grafo
-- Operação de ordenação topológica de grafo dirigido representado por mapeamento que dá -- os sucessores de cada vértice, segundo algoritmo descrito em Donald E. Knuth, -- The Art of Computing Programming, Volume 1: Fundamental Algorithms. TopologicalSort : map Vertex to set of Vertex ==> seq of Vertex TopologicalSort(Succ) == ( dcl indegree: map Vertex to nat; -- nº de antecessores por ordenar de cada vértice dcl S : set of Vertex; -- vértices por ordenar com indegree = 0 dcl R : seq of Vertex := []; -- resultado indegree := {v |-> 0 | v in set dom Succ}; for all v in set dom Succ do for all w in set Succ(v) do indegree(w) := indegree(w) + 1; S := {v | v in set dom Succ & indegree(v) = 0}; while S <> {} do let v in set S in ( S := S \ {v}; R := R ^ [v]; for all w in set Succ(v) do ( indegree(w) := indegree(w) – 1; if indegree(w) = 0 then S := S union {w} ) ); return R pre (forall v in set dom Succ & Succ(v) subset dom Succ) and IsAcyclic(Succ) post (len RESULT = card dom Succ) and forall i, j in set inds RESULT & i < j => RESULT(i) not in set Succ(RESULT(j)); Pode ser implementado (como?) em tempo O(nº de vértices + nº de arestas). Na presença de ciclos (violando a 2ª pós-condição), o algoritmo dá como resultado uma sequência parcial (violando a 1ª pós-condição)

39 * Aplicação de VDM++ à descrição de algoritmos - exemplo da colocação de professores (cont.)

40 Exemplo com várias soluções admissíveis
professor posição (ou vaga) preferência Situação inicial: V1 V2 Soluções possíveis válidas (obedecendo às restrições): P1 P2 V1 V2 solução melhor pior algoritmo pessimista só consegue encontrar algoritmo optimista consegue encontrar

41 Exemplo de aplicação do critério de optimalidade
Ao melhorar a posição de alguns professores mantendo a posição dos restantes, pode-se violar a restrição de justiça relativa entre dois candidatos à mesma vaga! Por isso é que o critério de optimalidade refere soluções admissíveis, e não soluções em geral não é colocação admissível P1 P1 professor com melhor ranking, mas sem posição inicial P2 P3 P3 P2 colocação inicial é colocação final admissível melhorar situação de P2 e P3, mantendo situação de P1

42 Algoritmo de colocação pessimista
1. Consideram-se inicialmente ocupadas as posições iniciais dos professores que pretendem mudar de posição 2. Colocam-se os professores pela ordem do ranking: 2.1. Coloca-se o professor na sua melhor preferência que está ainda livre 2.2. Se o professor estava inicialmente colocado e é colocado agora numa nova posição, gera uma vaga que tem de ser recuperada: Procura-se o professor já colocado de melhor ranking que pode beneficiar dessa vaga Se não se encontrar nenhum professor nessas condições, a recuperação da vaga fica concluída Se se encontrar um professor nessas condições, muda-se a colocação desse professor (melhorando-a), o que origina uma nova vaga que tem de ser recuperada da mesma forma

43 Análise do algoritmo de colocação pessimista
Uma vez que a recuperação de uma vaga corresponde à melhoria de posição de um professor, o nº máximo de movimentos de recuperação de vagas ao longo de toda a execução do algoritmo é o nº total de preferências indicadas pelos professores Isto também garante que o algoritmo termina sempre É fácil (?!) de ver que as pós-condições são satisfeitas No entanto, não garante optimalidade (ver 1º exemplo)

44 Algoritmo de colocação optimista (*)
1) Consideram-se inicialmente livres as posições iniciais dos professores que pretendem mudar de posição 2) Colocam-se os professores pela ordem do ranking, na melhor preferência ainda livre de cada professor (alguns professores podem ficar por colocar) 3) Se os professores que estavam inicialmente colocados ficaram todos colocados, o processo termina. 4) Senão, 4.1) Os professores que estavam inicialmente colocados e ficaram por colocar são colocados definitivamente nas suas posições iniciais, que deixam de estar livres 4.2) Repete-se a colocação com menos estes lugares livres (*) Desenvolvido pela

45 Análise do algoritmo optimista
O nº máximo de iterações externas é limitado pelo número de professores que estavam inicialmente colocados Isto garante que o algoritmo termina sempre Corre em tempo polinomial (demorou cerca de 30 minutos com os dados de 2004) Ver demonstração da correcção do algoritmo nas referências (a ATX demonstrou que encontra uma solução admissível, mas não que encontra a solução óptima) Segundo Ana Paula Tomás (ver referências), o algoritmo optimista determina a solução óptima

46 Relação com problema de casamentos estáveis
Problema de casamentos estáveis (StableMarriage), versão clássica: Supondo que cada elemento dum grupo de n homens e n mulheres ordenou todos os de sexo oposto por ordem de preferência estrita, pretende-se determinar um emparelhamento estável. Sendo H = {h1, , hn} e M = {m1, ,mn} os conjuntos de homens e mulheres, um emparelhamento E é uma qualquer função injectiva de H em M. Informalmente, um emparelhamento é, neste caso, um conjunto de n casais (monogâmicos e heterossexuais). Um emparelhamento E diz-se instável se e só se existir um par (h,m)  E tal que h prefere m à sua parceira em E e m também prefere h ao seu parceiro em E. Caso contrário, diz-se estável.

47 Relação com problema de casamentos estáveis
Problema de casamentos estáveis com listas de preferências incompletas (StableMarriageWithIncompleteLists) Surgiu na colocação de internos em hospitais O critério de estabilidade das soluções é reformulado do modo seguinte: Um emparelhamento é instável se e só se existir um candidato r e um hospital h tais que h é aceitável para r e r é aceitável para h, o candidato r não ficou colocado ou prefere h ao seu actual hospital e h ficou com vagas por preencher ou h prefere r a pelo menos um dos candidatos com que ficou. Caso contrário, diz-se estável.

48 Relação com problema de casamentos estáveis
(1962)

49 Relação com problema de casamentos estáveis
Propriedades do algoritmo de Gale-Shapley (1962): O emparelhamento obtido por este algoritmo é óptimo para os internos e péssimo para os hospitais: qualquer interno fica com o melhor hospital que pode ter em qualquer emparelhamento estável e cada hospital fica com os piores internos. Tempo de execução é de ordem quadrática (nº de internos * nº de hospitais)

50 Relação com problema de casamentos estáveis
No problema da colocação de professores, o conceito de emparelhamento é o mesmo, se se considerar que a atribuição é de candidatos a vagas Internos correspondem aos professores Hospitais correspondem às vagas (ou escolas?) Cada vaga prefere 1º o professor que aí estava colocado anteriormente, e depois todos os outros pela ordem do ranking

51 Formalização e teste em VDM++
VDM++ permite formalizar restrições do problema por pré e pós-condições VDM++ permite descrever algoritmos a um nível de abstracção elevado, através do corpo de funções ou operações Ver projecto VDM\ColocaProfs.zip Exercício: refazer com operações em vez de funções

52 Referências Manual de VDM++ (langmanpp_a4.pdf)
Modelling Systems: Practical Tools and Techniques in Software Development, John Fitzgerald and Peter Gorm Larsen, Cambridge University Press, 1998.  (existe na biblioteca da FEUP) Validated Designs for Object-oriented Systems. John Fitzgerald, Peter Gorm Larsen, Paul Mukherjee, Nico Plat and Marcel Verhoef. ISBN: Springer Verlag, New York Specification of Software Systems, V.S. Alagar and K. Periyasamy, ISBN: , Springer, 1998. Algoritmo de colocação de professores (ATX Software) Emparelhamentos, Casamentos Estáveis e Algoritmos de Colocação de Professores (Ana Paula Tomás, FC, UP)


Carregar ppt "Jpf@fe.up.pt www.fe.up.pt/~jpf Métodos Formais em Engenharia de Software Especificação Baseada em Modelos em VDM++ (5ª parte) João Pascoal Faria jpf@fe.up.pt."

Apresentações semelhantes


Anúncios Google