[WikiDyd] [TitleIndex] [WordIndex

Materiały zostały opracowane w ramach realizacji Programu Rozwojowego Politechniki Warszawskiej.

http://prpw.iem.pw.edu.pl/images/KAPITAL_LUDZKI.gif http://prpw.iem.pw.edu.pl/images/EU+EFS_P-kolor.gif

http://www.pr.pw.edu.pl/ jest projektem współfinansowanym przez Unię Europejską w ramach Europejskiego Funduszu społecznego (działanie 4.1.1 Programu Operacyjnego Kapitał Ludzki) i ma na celu poprawę jakości kształcenia oraz dostosowanie oferty dydaktycznej Politechniki Warszawskiej do potrzeb rynku pracy. Będzie on realizowany przez Uczelnię w latach 2008-2015.


Laboratorium metodyki programowania

Ćwiczenie 9: Zarządzanie wersjami oprogramowania

Scenariusz

Uwaga! Ćwiczenie realizowane jest w dwuosobowych zespołach. Każdy z zespołów ma dostęp do wspólnego repozytorium svn z prawami odczytu i zapisu. (W laboratorium JiMP należy wykorzystać do tego celu system Projektor, który jest wydziałową usługą projektów svn.)

  1. Student loguje się do systemu LOP (Laboratorium Otwartego Programowania).
  2. Student przechodzi do katalogu roboczego dla zajęć LMP.
  3. Student pobiera z repozytorium szkielet kodu programów.
  4. Po wyjaśnieniach prowadzącego student przystępuje do implementacji zadań w kodzie, kompilacji i uruchomienia programów. Porównuje wynik działania z oczekiwanym wynikiem. W trakcie prac zadaniem studenta jest wykonanie szeregu zatwierdzeń lokalnych zmian w repozytorium, w trakcie których oczekiwane jest rozwiązanie podstawowych problemów związanych z konfliktami, scalaniem gałęzi rozwojowych, itp.
  5. Student modyfikuje programy według wskazówek prowadzącego (patrz opis szczegółowy). Powtarza próbę kompilacji i uruchomienia.
  6. Ćwiczenie zaliczeniowe: studenci pracując na własnych gałęziach rozwojowych rozszerzają funkcjonalność programu według zamówienia prowadzącego a następnie w końcowej fazie scalają swoje implementacje w jeden projekt.

Opis szczegółowy

W trakcie zajęć nauczymy się korzystania z narzędzi do kontroli wersji oprogramowania. W szczególności praca będzie dotyczyła systemu do zarządzania wersjami Subversion (komenda w konsoli tekstowej svn). Aby poprawnie wykonac niniejsze ćwiczenie niezbędne jest samodzielne przygotowanie się w posługiwaniu narzędziem Subversion na podstawie dokumentacji oraz materiałów z wykładu.

Rozpoczęcie pracy

Zajęcia będą prowadzone na komputerze stud.iem.pw.edu.pl. W celu rozpoczęcia pracy należy zalogować się na tym komputerze za pomocą usługi ssh. Można w tym celu wykorzystać albo dostępny w każdym praktycznie systemie Unix/Linux program ssh albo klienta SSH dla systemu Windows - PuTTY. Na maszynach studenckich w IETiSIP PW można podnieść różne dystrybucje Uniksa/Linuksa lub system Windows, ale w każdej z nich jest zainstalowane oprogramowanie ssh.

Do logowania na maszynie stud.iem.pw.edu.pl należy użyć takiego samego loginu i hasła jakie wykorzystywane sa do dostępu do usług wydziałowych (poczta, e-dziekanat, itd.).

Po zalogowaniu się należy przejść do utworzonego na pierwszych zajęciach katalogu lmp:

 cd lmp

Kod do zajęć

lmp9.tgz

Opis zadania

W trakcie zajęć należy zaimplementować program, który będzie rozwiązywał układy algebraicznych równań linowych za pomocą trywialnej metody Gaussa (http://edu.i-lo.tarnow.pl/inf/alg/005_root/0006.php) oraz wstecznego podstawienia. Pierwszym etapem prac jest implementacja podstawowej wersji algorytmu. Następnie, w drugiej części należy uwzględnić selekcję elementu diagonalnego, który będzie wykorzystany do eliminacji (np. maksymalny element w danej kolumnie). Selekcja polega na zamianie wierszy wykorzystywanego w aktualnej fazie eliminacji z wierszem poniżej aktualnego, który ma największą wartość elementu w kolumnie, w której eliminujemy elementy.

Poszczególne etapy prac należy wykonywać w dwuosobowym zespole wykonując zatwierdzenia zmian do repozytorium zgodnie z poniższym harmonogramem. Zachowanie poniższego harmonogramu pozwoli zapoznać się z właściwościami pracy zespołowej przy wykorzystaniu narzędzi do wersjonowania.

Faza 1 - przygotowania szkieletu projektu (praca przez dwie osoby przy tym samym komputerze)

Utworzenie szkieletu projektu:

Na koniec tej fazy szkielet projektu należy zatwierdzić w repozytorium (komenda: svn commit). Proszę sensownie opisywać zmiany, które są zatwierdzane w ramach każdego 'commita' w ramach niniejszego ćwiczenia. Opisy zatwierdzane w ramach ćwiczenia podlegają ocenie na końcu ćwiczenia. Opisy powinny zwięźle (zazwyczaj w formie jednego lub dwóch zdań, lub w podpunktach) przedstawiać główne zmiany, które zostają wprowadzane do projektu przy danym zatwierdzeniu.

Faza 2 - implementacja trywialnej metody Gaussa (każdy ze studentów pracuje przy własnym komputerze)

Samodzielne rozdzielenie zadań w dwuosobowym zespole. Każdy ze studentów zajmuje się osobną częścią implementacji zadania. Najłatwiej podział ten zrealizować w ten sposób, że każdy ze studentów implementuje osobny zestaw funkcji.

Na koniec fazy, kiedy projekt nie jest jeszcze przetestowany studenci powinni zatwierdzić swoje implementacje (UWAGA! każdy projekt musi kompilować się bezbłędnie - to jest podstawowe, kryterium, które dopuszcza zatwierdzenie zmian do repozytorium.)

Faza 3 - równoległa implementacja selekcji elementu diagonalnego (każdy ze studentów pracuje przy własnym komputerze)

Każdy ze studentów powinien samodzielnie rozszerzyć implementację algorytmu o selekcję elementu diagonalnego, wykorzystywanego w eliminacji Gaussa.

Pod koniec, gdy obie implementacje będą gotowe, studenci powinni wykonać próbę zatwierdzenia swoich zmian do repozytorium. W przypadku wystąpienia konfliktów studenci powinni dokonać wyboru ostatecznej wersji implementacji.

Faza 4 - utworzenie osobnych gałęzi rozwojowych

W fazie tej studenci za pomocą komendy svn copy powinni utworzyć własne gałęzie rozwojowe i przenieść do nich swoje prace rozwojowe. W fazie tej studenci powinni niezależnie od siebie zaimplementować gruntowne testy funkcjonalne w głównym module programu (procedurze main) lub w osobnym pliku zawierającym metody testujące, lub nawet w pliku Makefile. W ramach tej fazy powinnien powstać zestaw co najmniej 4-5 plików z różnymi zestawami danych testowych, które będą podlegać testom. Uwaga! Testy powinny automatycznie weryfikowac poprawność wyniku - tzn. na ekranie powinien wyświetlić się przykładowo komunikat: "Test 1 - poprawne dane 2x2: OK.", lub "Test 1 - poprawne dane 2x2: Wystąpił BŁĄD!!!"

W skład testów powinny wchodzić następujące elementy:

Efektem końcowym tej fazy są działające automatyczne testy funkcjonalne w każdej gałęzi rozwojowej projektu oraz jedna z implementacji studentów przeniesiona do głównej gałęzi projektu (trunk).

Krótka instrukcja jak wykonać scalenie zmian (ang. merge): http://www.sepcot.com/blog/2007/04/SVN-Merge-Branch-Trunk Dłuższa instrukcja dotycząca tworzenia gałęzi rozwojowych: http://svnbook.red-bean.com/en/1.5/svn.branchmerge.html

Program na zaliczenie

Zaliczenie laboratorium realizowane jest na podstawie działającej aplikacji, służącej do rozwiązywania układów równań za pomocą eliminacji Gaussa oraz pobrana za pomocą komendy svn history historia wersji oprogramowania zgodna z zamieszczonym w niniejszej instrukcji harmonogramem.

Szkielet kodu do niniejszego ćwiczenia

Szkielet kodu składa się z kilku gotowych, które student ma za zadanie uzupełnić o zasadniczą część ćwiczenia (eliminacja Gaussa, selekcja elementu diagonalnego, wsteczne podstawienie, testy).

Plik main.c który implementuje scenariusz główny programu (wczytanie danych macierzy A, wektora b, utoworzenie wektora wynikowego x, elimacje Gaussa, wsteczne podstawienie oraz wyświetlenie wyniku):

   1 #include "gauss.h"
   2 #include "backsubst.h"
   3 #include "mat_io.h"
   4 #include <stdlib.h>
   5 #include <stdio.h>
   6 
   7 
   8 int main(int argc, char ** argv) {
   9   int res;
  10   Matrix * A = readFromFile(argc > 1 ? argv[1] : "A.txt" );
  11   Matrix * b = readFromFile(argc > 2 ? argv[2] : "b.txt" );
  12   Matrix * x;
  13 
  14   if (A == NULL) return -1;
  15   if (b == NULL) return -2;
  16   printToScreen(A);
  17   printToScreen(b);
  18 
  19   res = eliminate(A,b);
  20   x = createMatrix(b->r, 1);
  21   if (x != NULL) {
  22     res = backsubst(x,A,b);
  23 
  24     printToScreen(x);
  25     freeMatrix(x);
  26   } else {
  27           fprintf(stderr,"Błąd! Nie mogłem utworzyć wektora wynikowego x.\n");
  28   }
  29 
  30   freeMatrix(A);
  31   freeMatrix(b);
  32 
  33   return 0;
  34 }

Przed analizą implementacji poszczególnych plików warto zaznajomić się z głównymi (trzema) plikami nagłówkowymi, które definiują interfejs komunikacyjny pomiędzy poszczególnymi modułami projektu:

mat_io.h (plik zawierający definicję struktury danych do przechowywania macierzy (pamiętaj, że wektor to specjalna macierz, w naszym projekcie warto założyć, że to wektor kolumnowy - czyli o wymiarach n wierszy na 1 kolumnę), oraz deklaracje metod do podstawowych operacji na macierzach):

   1 #ifndef _MAT_IO_H
   2 #define _MAT_IO_H
   3 
   4 typedef struct _Matrix {
   5         int r,c;
   6         double **data;
   7 } Matrix;
   8 
   9 /**
  10  * Zwraca 0 - udalo sie wczytac
  11  * Zwraca 1 - podczas wczytywania wystapil blad
  12  */
  13 Matrix * readFromFile(char * fname);
  14 void printToScreen(Matrix *mat);
  15 
  16 Matrix * createMatrix(int r, int c);
  17 void freeMatrix(Matrix *mat);
  18 
  19 #endif
  20 

gauss.h - plik z deklaracją metody dla eliminacji Gaussa:

   1 #ifndef _GAUSS_H
   2 #define _GAUSS_H
   3 
   4 #include "mat_io.h"
   5 
   6 /**
   7  * Zwraca 0 - elimnacja zakonczona sukcesem
   8  * Zwraca 1 - macierz osobliwa - dzielenie przez 0
   9  */
  10 int eliminate(Matrix *mat, Matrix *b);
  11 
  12 #endif
  13 

bachsubst.h - plik z deklaracją metody realizujacej wsteczne podstawienie:

   1 #ifndef _BACKSUBST_H
   2 #define _BACKSUBST_H
   3 
   4 #include "mat_io.h"
   5 
   6 /**
   7  * Zwraca 0 - wsteczne podstawienie zakonczone sukcesem
   8  * Zwraca 1 - błąd dzielenia przez 0 (element na diagonali = 0)
   9  * Zwraca 2 - błąd nieprawidłowych rozmiarów macierzy
  10  */
  11 int  backsubst(Matrix *x, Matrix *mat, Matrix *b);
  12 
  13 #endif
  14 

Pomocniczy plik do wczytywania macierzy z pliku, wypisywania macierzy na ekranie oraz alokacji i zwalniania pamięci dla macierzy:

   1 #include "mat_io.h"
   2 #include <stdio.h>
   3 #include <stdlib.h>
   4 
   5 /**
   6  * Zwraca <> NULL - udalo sie wczytac
   7  * Zwraca == NULL - podczas wczytywania wystapil blad
   8  */
   9 Matrix * readFromFile(char * fname) {
  10         int r,c;
  11         int ir, ic;
  12         FILE * fin =  fopen(fname,"r");
  13         Matrix * mat = NULL;
  14 
  15         if (fin != NULL) {
  16           fscanf(fin,"%d %d",&r,&c);
  17           mat = createMatrix(r,c);
  18           if (mat != NULL) {
  19             for (ir = 0; ir < r; ir++)
  20               for (ic = 0; ic < c; ic++)
  21                 fscanf(fin, "%lf",&(mat->data[ir][ic]));
  22           } else {
  23                 fprintf(stderr,"Wystąpił problem podczas tworzenia macierzy o rozmiarach %d x %d dla danych z pliku: %s\n", r, c, fname);
  24           }
  25 
  26           fclose(fin);
  27         } else {
  28                 fprintf(stderr,"Nie mogę otworzyć pliku o nazwie: %s\n", fname);
  29         }
  30 
  31         return mat;
  32 }
  33 
  34 void printToScreen(Matrix *mat) {
  35   int i,j;
  36   printf("[ \n");
  37   for (i = 0; i<mat->r; i++) {
  38     printf("  ");
  39     for (j = 0; j < mat->c; j++) {
  40       printf("%f ", mat->data[i][j]);
  41     }
  42     printf("; \n");
  43   }
  44   printf("]\n");
  45 }
  46 
  47 Matrix * createMatrix(int r, int c) {
  48     int i;
  49     Matrix * mat = (Matrix*) malloc(sizeof(Matrix));
  50     if (mat != NULL) {
  51       mat->r = r;
  52       mat->c = c;
  53       mat->data = (double**) malloc(sizeof(double*) * r);
  54       for (i=0; i < r; i++) {
  55           mat->data[i] = (double*) malloc(sizeof(double) * c);
  56       }
  57     }
  58 
  59     return mat;
  60 }
  61 
  62 void freeMatrix(Matrix * mat) {
  63   int i;
  64   for (i=0;i < mat->r; i++)
  65     free(mat->data[i]);
  66   free(mat->data);
  67   free(mat);
  68 }

Projekt składa się również z dwóch dodatkowych plików stanowiących szkielet metod do eliminacji Gaussa i wstecznego podstawienia.

gauss.c:

   1 #include "gauss.h"
   2 
   3 /**
   4  * Zwraca 0 - elimnacja zakonczona sukcesem
   5  * Zwraca 1 - macierz osobliwa - dzielenie przez 0
   6  */
   7 int eliminate(Matrix *mat, Matrix *b){
   8     /**
   9      * Tutaj należy umieścić właściwą implementacje.
  10      */
  11 
  12     return 0;
  13 }

backsubst.c:

   1 #include "backsubst.h"
   2 /**
   3  * Zwraca 0 - wsteczne podstawienie zakonczone sukcesem
   4  * Zwraca 1 - błąd dzielenia przez 0 (element na diagonali = 0)
   5  * Zwraca 2 - błąd nieprawidłowych rozmiarów macierzy
   6  */
   7 int  backsubst(Matrix *x, Matrix *mat, Matrix *b) {
   8         /**
   9          * Tutaj należy umieścić właściwą implemntację.
  10          */
  11 
  12         /* Ponizszy kod jest trywialnym przepisaniem b do x. Nalezy to poprawic! */
  13 
  14         int i;
  15         for (i =0; i < x->r; i++) {
  16                 x->data[i][0] = b->data[i][0];
  17         }
  18 
  19         return 0;
  20 }


To już prawie wszystko, ale nie wolno nam zapomnieć, że

materiały zostały opracowane w ramach realizacji Programu Rozwojowego Politechniki Warszawskiej.

http://prpw.iem.pw.edu.pl/images/KAPITAL_LUDZKI.gif http://prpw.iem.pw.edu.pl/images/EU+EFS_P-kolor.gif

http://www.pr.pw.edu.pl/ jest projektem współfinansowanym przez Unię Europejską w ramach Europejskiego Funduszu społecznego (działanie 4.1.1 Programu Operacyjnego Kapitał Ludzki) i ma na celu poprawę jakości kształcenia oraz dostosowanie oferty dydaktycznej Politechniki Warszawskiej do potrzeb rynku pracy. Będzie on realizowany przez Uczelnię w latach 2008-2015.


2015-09-23 06:44