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.

Slides:



Advertisements
Apresentações semelhantes
Tratamento de exceções em Java Prof. Gustavo Wagner (Alterações) Prof. Tiago Massoni (Slides Originais) Desenvolvimento de Sistemas FATEC-PB  Centro de.
Advertisements

CLASSES EM JAVA Dilvan Moreira (baseado no livro Big Java)
Disciplina:PROA3V José Henrique Verhalem e Renan Tenório Professor: Alexandre Cassimiro Novembro 2015.
POLINÔMIOS. Polinômio ou função polinomial na variável complexa x é toda função P: ℂ → ℂ definida por P(x) = a n x n + a n–1 x n–1 + a n–2 x n–2 +...
Linguagem de Programação – Aula 03 Prof. Me. Ronnison Reges Vidal.
Tópicos Preliminares Algorítmos I.
RODOLFO SOARES TEIXEIRA OBMEP NA ESCOLA
Análise & Projeto – Especificação de Processos
Complementos de Engenharia de Software A linguagem VDM++ (1ª parte - Estrutura geral duma especificação; importação de.
IX ELAVIO FABIANA SIMÕES E SILVA ORIENTADORA: VITÓRIA PUREZA
Programação em C Aula 8.
Complementos de Engenharia de Software A linguagem VDM++ (2ª parte - Operadores e expressões; definição de invariantes,
MEI / LEIC Engenharia de Requisitos de Sistemas de Software Estudo de Casos - Caso da Colocação de Professores João Pascoal Faria Novembro de 2004.
Métodos Formais em Engenharia de Software 3c
Métodos Formais em Engenharia de Software Utilização da Ferramenta VDMTools Lite João Pascoal Faria
Estruturas de Repetição
Teste e Qualidade de Software Teste baseado em modelos – exemplo da biblioteca João Pascoal Faria
Complementos de Engenharia de Software A linguagem VDM++ (4ª parte – Funções avançadas) João Pascoal Faria
TQS - Teste e Qualidade de Software (Software Testing and Quality) Teste Envolvendo Acesso a Bases de Dados João Pascoal.
TQS - Teste e Qualidade de Software (Software Testing and Quality) Caso de estudo: Problema da procura duma string num.
Módulo I Capítulo 3: Fluxo de Código e Operador Condicional
Sistemas Prof. Luis S. B. Marques MINISTÉRIO DA EDUCAÇÃO
Prof. Wellington Franco
IP – Condicionais e controle de fluxo
O Problema dos Leitores e Escritores
EGP, CPC, 2004/05 Problema e Algoritmos de Colocação de Professores
ALGEBRA LINEAR AUTOVALORES E AUTOVETORES Prof. Ademilson
Algoritmos e Fluxogramas
FUNDAMENTO DE PROGRAMAÇÃO PROF. BRUNO DE CASTRO H. SILVA
LIMITE DE UMA FUNÇÃO Aula 01 – Matemática I – Engenharia de Aquicultura Prof. Danilene Donin Berticelli.
FUNDAMENTO DE PROGRAMAÇÃO
IP – Repetições Prof. Eduardo Falcão.
Introdução à Programação
Programação Orientada a Objetos
Dilvan Moreira (baseado no livro Big Java e T. Munzner)
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS
Complementos de Engenharia de Software A linguagem VDM++ (3ª parte – instruções; aplicação à descrição de algoritmos e.
BANCO DE DADOS II.
Programação Orientada a Objetos
Diagramas de Sequência
Estrutura de Repetição
Cálculo do clique maximal de um grafo
TQS - Teste e Qualidade de Software (Software Testing and Quality) Teste baseado em modelos (visuais e formais): exemplo.
Programação.
A decisão de Concessão de Crédito
Análise Sintática Botton Up Diomara M. R. Barros
Aula 02 – Produtos Notáveis
14/08/2012 Professor Leomir J. Borba- –
Emparelhamento em Grafos
O que você deve saber sobre
Sistemas Operacionais
Complexidade de Algoritmos
Serviço de Psicologia e Orientação
FUNDAMENTOS DA GESTÃO DE PROCESSOS Business Process Modeling Notation
Arranjo Físico Industrial
Arquitetura e padrões de software
Filas.
ALGORITMOS.
ALGORITMOS.
Modelo de Análise.
Geometria Computacional
TOP 10 - DINÂMICO matemátICA MÓDULO 1
Circuitos Sequenciais
Python: Comandos Básicos
Introdução a progrmação Comandos condicionais: if e switch
RESULUÇÃO DOS EXERCÍCIOS E
Arquitetura e padrões de software
Aula 7 Professores: Conteúdo: Dante Corbucci Filho
Sistemas de Informação
Aula 3 Professores: Conteúdo: Dante Corbucci Filho
Transcrição da apresentação:

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 www.fe.up.pt/~jpf

Í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.)

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

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) ;

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”

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”

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~, …) ;

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

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”

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)

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

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

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

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

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

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

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

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!

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));

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!

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 …

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

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

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;

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);

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>;

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!

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));

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>;

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

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

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

Modelo de estrutura estática

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; …

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

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

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;

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)

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

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

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

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: 2.3.1. Procura-se o professor já colocado de melhor ranking que pode beneficiar dessa vaga 2.3.2. Se não se encontrar nenhum professor nessas condições, a recuperação da vaga fica concluída 2.3.3. 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

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)

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

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

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.

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.

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

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)

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

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

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: 1-85233-881-4. Springer Verlag, New York. 2005. Specification of Software Systems, V.S. Alagar and K. Periyasamy, ISBN: 0-387-98430-5, 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)