Métodos Formais de Programação II --- Trabalho Prático

J.N. Oliveira

Ano lectivo de 1996/97

Sumário

O presente texto descreve a proposta de trabalho laboratorial (opcional) da disciplina Métodos Formais de Programação II (obrigatória da Licenciatura em Matemática e Ciências da Computação e opcional da Licenciatura em Engenharia de Sistemas e Informática ), na sua edição de 1996/97. Esta proposta é partilhada pela disciplina Desenvolvimento de Sistemas de Informação (obrigatória da Licenciatura em Engenharia de Sistemas e Informática e opcional da Licenciatura em Matemática e Ciências da Computação ).

O que se pretende neste trabalho é que os alunos adquiram prática laboratorial em ``prototipagem rápida'' e ``cálculo de programas'', as áreas dos métodos formais de especificação e desenvolvimento de aplicações de que a disciplina se ocupa.

Contents

Introdução

O tema do presente projecto laboratorial combina e estende dois problemas que foram abordados nas aulas práticas da disciplina Métodos Formais de Programação I , edição de 96/97: Ex. 2.47 sobre o modelo de dados Orc e Ex. 2.54 sobre o modelo de dados Actplan.

Destes exercícios recorda-se o seguinte:

Objectivo

O que se pretende neste trabalho é especificar e implementar um sistema que combine, estenda e generalize os dois modelos dados. O resultado final deverá ser uma aplicação capaz de fazer gestão integrada de projectos, nas suas componentes de planeamento, escalonamento, previsão de custos e orçamentação.

Material Disponível

Para o efeito foi desenvolvido um pequeno protótipo CAMILA , que faz parte do material disponível para a realização do projecto (Ver Anexo). Este protótipo, que deve ser encarado como um mero ponto de partida, é completamente aberto à extensão ou modificação e consta das partes seguintes:

Requisitos

Recordando o ``ciclo de vida'' para as aplicações, adoptado nesta disciplina,

são os seguintes os requisitos deste trabalho:

  1. Primeiramente, o grupo deverá embeber o protótipo dado ('kit') em C (ver manuais disponíveis na documentação CAMILA ) e construir-lhe um 'browser' numa tecnologia à sua escolha, e.g. DELPHI em WINDOWS 95 , Tcl/Tk em Linux, Java , etc. Deverão ser procurados na tecnologia escolhida objectos para visualização tipo histogramas, gráficos de barras etc.

    Deste exercício saltará a necessidade de melhorar significativamente tal protótipo, incluindo o aumento de funcionalidade e a identificação de invariantes. (Uma actividade interessante a especificar poderá dizer respeito à procura, fixado o tempo de execução de um projecto, de um escalonamento que minimize a flutuação relativa dos recursos envolvidos.)

  2. De seguida há que calcular (em SETS ) uma implementação relacional de toda ou parte da aplicação prototipada, a correr em mSQL (Mini SQL) , integrando-se o correspondente código calculado em lugar do CAMILA correspondente (refinamento ``horizontal''). A camada interactiva deverá permanecer a mesma, apenas se redefinindo a API, ao nível do C, onde chamadas a CAMILA passam a ser substituídas por chamadas a mSQL (Mini SQL) .

De tudo isto deve ser realizado um breve relatório e uma demonstração final.

Prazo de Entrega

Os grupos devem combinar com o monitor da disciplina a data de entrega do relatório do projecto, e correspondente demo, por forma a que esta se realize até duas semanas antes do lançamento das notas no livro de termos, ie. 16 de Julho de 1997 (época normal) ou 4 de Setembro de 1997 (época de recurso).

Não serão aceites trabalhos em Setembro para melhoria.

Anexo - Protótipo de um ``Kit'' para o Projecto

;=====================================================================
;    `Kit' para trabalho laboratorial M.F.P.II - 96/97
;---------------------------------------------------------------------
;    Equipa docente: {jno,lsb,fln}@di.uminho.pt
;=====================================================================
;    0. Auxiliary Functions
;---------------------------------------------------------------------

FUNC f870(f:A->(B->C)):AxB->C 
RETURN
     PLUS({ let (g=f[a]) in [ < a, b>  -> g[b] | b <- dom(g) ] | a <- dom(f) });

FUNC f822(p:AxB):BxA
RETURN <p2(p),p1(p)>;

FUNC f87x(f:AxB->C):A->(B->C)
RETURN let (X=dom(f),
            Y=p1-set(X))
        in [ a -> [ p2(p) -> f[p] | p <- X : p1(p)==a ] | a <- Y ];

FUNC mcup(m:A->NAT,n:A->NAT):A->NAT
RETURN monff(m,n,add);

FUNC MCUP(l:(A->NAT)-seq):A->NAT
RETURN mcup-orio([],l);

FUNC monff(m:A->B,n:A->B,o:BxB -> B):A->B
RETURN m + n + [ a -> o(m[a],n[a]) | a <- dom(m) * dom(n) ];

FUNC span(i:INT,d:INT):INT-set
RETURN { i .+ x .- 1 | x <- inseg(d) };

FUNC mmcup(f1:A->(B->INT),f2:A->(B->INT)): A->(B->INT)
RETURN f1 + f2 + [ k -> mcup(f1[k],f2[k]) | k <- dom(f1)*dom(f2) ];

MMCUP(l)=mmcup-orio([],l);

PLUS(l)=plus-orio([],l);

FUNC MAX(s:INT-set):INT
RETURN MAXloop(s,0);

FUNC MAXloop(s:INT-set,m:INT):INT
RETURN if (s=={}) then m
                  else let (x=choice(s))
                       in MAXloop(s-{x}, if (x < m) then m else x);
/* etc */

;---------------------------------------------------------------------
;    1. Actplan
;---------------------------------------------------------------------
;    1.1. Actplan sorts
;---------------------------------------------------------------------

TYPE

  ActPlan = Act -> ActInf;
  ActInf :: De: Desc
            S: Span
            R: Resources
            Dp: Deps;
  Resources = Res -> INT;
  Schedule = Act -> INT;
  ActPlan1 = Act -> ActInf1;
  ActInf1 :: A: INT B: Span C: Resources ;
  ResHist = Res -> (Time -> INT);
  Deps = Act-set;
  Res  = STR;
  Act = INT;
  Desc = STR;
  Span = INT;
  Time = INT;

ENDTYPE

;---------------------------------------------------------------------
;    1.2. Actplan functions
;---------------------------------------------------------------------

FUNC bestSchedule(db:ActPlan):Schedule
RETURN [ a -> bestStart(a,db) | a <- dom(db) ];

FUNC genActPlan1(db:ActPlan,s:Schedule):ActPlan1
RETURN [ a -> let (x=db[a])
              in ActInf1(s[a],S(x),R(x)) | a <- dom(db) * dom(s) ];

FUNC bestStart(a:Act,db:ActPlan):INT
RETURN let (x=db[a],
            D=Dp(x))
       in if D=={} then 0
                   else MAX({ bestStart(aa,db) .+ S(db[aa]) | aa <- Dp(x)});

FUNC genResHist(a:ActPlan1):ResHist
RETURN let (b=[ t -> let (x=a[t])
                     in [ i -> C(x) | i <- span(A(x),B(x)) ]
                   | t <- dom(a) ],
            c=MMCUP(<b[t] | t <- dom(b) >),
            d=f870(c),
            e=f87x(f822->*(d)))
       in e;

FUNC ActPlan2TeX(db:ActPlan):TeX
RETURN let (a=bestSchedule(db),
            b=*->S(db))
       in < TeXCmd("begin",<"tabular","{l}">) > ^
          CONC(<
              < TeXCmd("rule",<strcat(itoa(a[k]),"cm"),"0mm">),
                TeXCmd("rule",<strcat(itoa(b[k]),"cm"),"4mm">),
                TeXCons("\\ ")
               >
          | k <- dom(b) >) ^
          < TeXCmd("end",<"tabular">) >;

/* etc */
;---------------------------------------------------------------------
;    2. Orc
;---------------------------------------------------------------------
;    2.1. Orc sorts
;---------------------------------------------------------------------

TYPE

  Orc  = Item -> Info;
  Info = Acts | SubOrc;
  SubOrc :: O: Orc;
  Acts :: A: Act-set;
  Item = STR;

ENDTYPE

;---------------------------------------------------------------------
;    2.2. Orc functions
;---------------------------------------------------------------------

FUNC total(db:Orc):Act-set
RETURN UNION({
               let (x=db[i])
               in if is-Acts(x) then A(x)
                  else total(O(x))
               | i <- dom(db)
            });

FUNC rubricas(db:Orc):(Item-seq)-set
RETURN UNION({
               let (x=db[i])
               in if is-Acts(x) then { <i> }
                  else { <i> ^ p | p <- rubricas(O(x)) }
               | i <- dom(db)
            });

FUNC cats(db:Orc):(Item-seq)-set
RETURN { <> } U
       UNION({
               let (x=db[i])
               in if is-Acts(x) then { <> }
                  else { <i> ^ p | p <- cats(O(x)) }
               | i <- dom(db)
            });

FUNC novaSubcat(db:Orc,i:Item,c:Item-seq):Orc
RETURN novaInfo(db,i,c,SubOrc([]));

FUNC novaRubrica(db:Orc,i:Item,c:Item-seq):Orc
RETURN novaInfo(db,i,c,Acts({}));

FUNC novaInfo(db:Orc,i:Actm,c:Item-seq,y:Info):Orc
RETURN if c == <>
       then (if i in dom(db) then db else db + [ i -> y ])
       else let (h=hd(c),t=tl(c))
            in if ~(h in dom(db))
               then db
               else let (x=db[h])
                    in if is-Acts(x)
                       then db
                       else db + [ h -> SubOrc(novaInfo(O(x),i,t,y)) ];

FUNC updateInfo(db:Orc,c:Item-seq,f:InfoxInfo->Info,i:Info):Orc
RETURN if c == <>
       then db
       else let (h=hd(c),t=tl(c))
            in if ~(h in dom(db))
               then db
               else let (x=db[h])
                    in if is-SubOrc(x)
                       then db + [ h -> if t==<>
                                        then f(x,i)
                                        else SubOrc(updateInfo(O(x),t,f,i))
                                 ]
                       else  if t==<> then db + [ h -> f(x,i) ]
                                      else db;

FUNC remoInfo(db:Orc,c:Item-seq):Orc
RETURN if c == <>
       then []
       else let (h=hd(c),t=tl(c))
            in if ~(h in dom(db))
               then db
               else let (x=db[h])
                    in if is-Acts(x)
                       then (if t==<> then db \ { h } else db)
                       else  if t==<>
                             then db \ { h }
                             else db + [ h -> remoInfo(O(x),t) ];

/* etc */
;---------------------------------------------------------------------
;    3. Project = Actplan * Orc
;---------------------------------------------------------------------
;    3.1. Project sorts
;---------------------------------------------------------------------

TYPE

  Project :: A: ActPlan O: Orc;

ENDTYPE


;---------------------------------------------------------------------
;    3.3. Project functions
;---------------------------------------------------------------------
/* etc */

;---------------------------------------------------------------------
;    4. System = Collection of Projects
;---------------------------------------------------------------------
;    4.1. System sorts
;---------------------------------------------------------------------

TYPE

  Db = ProjId -> Project;
  ProjId = STR;

ENDTYPE


;---------------------------------------------------------------------
;    4.2. System functions
;---------------------------------------------------------------------
/* etc */
;---------------------------------------------------------------------
;    4.3. System state
;---------------------------------------------------------------------

; STATE db:Db

;---------------------------------------------------------------------
;    4.4. System actions
;---------------------------------------------------------------------

FUNC INIT():SYM
STATE db <- [];

FUNC UPLOAD():SYM
STATE db <- [ "Demo" ->
Project(
   [ 0 ->
        ActInf(
           "Limpeza do terreno",
           1 ,
           [ "Mao de obra"->2  ], {}),
     1 ->
        ActInf(
           "Fundacoes",
           3 ,
           [ "Mao de obra"->5 ,
             "Ferro"->700 ,
             "Massa"  ->100  ],
           { 0 }),
     2 ->
        ActInf(
           "Estrutura r/c",
           5 ,
           [ "Mao de obra"->5 ,
             "Ferro"->800 ,
             "Massa"  ->200  ],
           { 1 }),
     3 ->
        ActInf(
           "Laje piso",
           2 ,
           [ "Mao de obra"->3 ,
             "Ferro"->700 ,
             "Massa"  ->100  ],
           { 2 }),
     4 ->
        ActInf(
           "Massame r/c",
           1 ,
           [ "Mao de obra"->3 ,
             "Massa"  ->100  ],
           { 2,3 }),
     5 ->
        ActInf(
           "Estrutura andar",
           5 ,
           [ "Mao de obra"->5 ,
             "Ferro"->800 ,
             "Massa"  ->200  ],
           { 2 }),
     6 ->
        ActInf(
           "Divisoes interior r/c",
           2 ,
           [ "Mao de obra"->2 ,
             "Tijolo" -> 500 ,
             "Massa"  -> 50  ],
           { 4 }),
     7 ->
        ActInf(
           "Laje cobertura",
           3 ,
           [ "Mao de obra"->5 ,
             "Ferro"->800 ,
             "Massa"  ->200  ],
           { 5 }),
     8 ->
        ActInf(
           "Divisoes interior andar",
           2 ,
           [
                          ],
           { 7 }),
     9 ->
        ActInf(
           "Telha e caleiros",
           1 ,
           [ "Mao de obra"->2 ,
             "Tijolo" -> 500 ,
             "Massa"  -> 50  ],
           { 7 }),
    10 ->
        ActInf(
           "Drenagens e isolamentos",
           1 ,
           [ "Mao de obra"->2 ,
             "Tubagens" -> 100 ,
             "Isolante" ->  50 ,
             "Massa"  -> 10  ],
           { 2,5,9 }),
    11 ->
        ActInf(
           "Portas e vidracas exteriores",
           1 ,
           [ "Mao de obra"->2 ,
             "Madeira"-> 200 ,
             "Vidro" -> 50 ,
             "Ferragens" -> 10 ],
           { 9 }),
    12 ->
        ActInf(
           "Reboco e pintura exterior",
           2 ,
           [ "Mao de obra"->2 ,
             "Tinta" ->  50 ,
             "Massa"  -> 50  ],
           { 9, 10, 11 }),
    13 ->
        ActInf(
           "Instalacao electrica",
           2 ,
           [ "Mao de obra"->2 ,
             "Material electrico" -> 10 ],
           { 6, 8 }),
    14 ->
        ActInf(
           "Instalacao sanitaria",
           2 ,
           [ "Mao de obra"->2 ,
             "Tubagens" -> 40 ],
           { 6, 8 }),
    15 ->
        ActInf(
           "Portas interiores",
           2 ,
           [ "Mao de obra"->2 ,
             "Madeira"-> 150 ,
             "Ferragens" -> 10 ],
           { 13 }),
    16 ->
        ActInf(
           "Rebocos interiores",
           2 ,
           [ "Mao de obra"->2 ,
             "Massa"  -> 30  ],
           { 15, 13, 14 }),
    17 ->
        ActInf(
           "Soalhos e pavimentos",
           2 ,
           [ "Mao de obra"->3 ,
             "Madeira"-> 300 ],
           { 16 }),
    18 ->
        ActInf(
           "Pintura interior",
           2 ,
           [ "Mao de obra"->2 ,
             "Tinta"  -> 30  ],
           { 16, 17 }),
    19 ->
        ActInf(
           "Moveis cozinha etc",
           2 ,
           [ "Mao de obra"->2 ,
             "Mobiliario" -> 10  ],
           { 18 }),
    20 ->
        ActInf(
           "Loucas sanitarias",
           2 ,
           [ "Mao de obra"->2 ,
             "Loucas" -> 10  ],
           { 17 }),
    21 ->
        ActInf(
           "Limpeza geral",
           2 ,
           [ "Mao de obra"->5],
           { 19 }),
    22 ->
        ActInf(
           "Arranjos exteriores",
           2 ,
           [
                          ],
           { 10, 12 }),
    23 ->
        ActInf(
           "Instalacao de aquecimento",
           2 ,
           [ "Mao de obra"->3 ,
             "Tubagens" -> 40,
             "Radiadores" -> 60,
             "Fonte de calor" -> 100 ],
           { 6, 8 })
   ],
   [ "Obra de betao armado"->
        Acts(
           { 1, 2, 3, 5 }),
     "Limpezas e arranjos"->
        Acts(
           { 0, 22 }),
     "Obra de massa ou reboco"->
        Acts(
           { 4, 12, 16 }),
     "Obra de tijolo"->
        Acts(
           { 6, 8 }),
     "Lajes"->
        Acts(
           { 7 }),
     "Cobertura"->
        Acts(
           { 9 }),
     "Isolamentos e drenagens"->
        Acts(
           { 10 }),
     "Equipamento"->
        SubOrc(
           [ "Sanitario"->
                Acts(
                   { 14 }),
             "Electrico"->
                Acts(
                   { 13 }),
             "Aquecimento"->
                Acts(
                   { 23 }),
             "Cozinha"->
                Acts(
                   { 19 }) ]),
     "Carpintaria"->
        SubOrc(
           [ "Aberturas"->
                SubOrc(
                   [ "Janelas e portas"->
                        Acts(
                           { 11 }),
                     "Portas interiores"->
                        Acts(
                           { 15 }) ]),
             "Pavimentos"->
                Acts(
                   { 17 }) ]),
     "Obra de pintor"->
        Acts(
           { 18 }),
     "Pavimentos"->
        Acts(
           { 1000 }) ])
];

/* etc */

;---------------------------------------------------------------------
;    5. API
;---------------------------------------------------------------------
/* etc (All external calls to the overall application) */



Jose Nuno Oliveira
Wed Apr 16 13:41:54 WET DST 1997