0% found this document useful (0 votes)
97 views14 pages

Second Formal Report

This document contains a student's coursework submission that includes: 1) A mathematical expression to convert a date to days since January 1st, 1980. 2) A Spec# specification for a method to validate if a date is valid. 3) A Spec# specification for a method to calculate the number of days between a given date and January 1st, 1980. 4) An implementation of the above method with loop invariants. 5) Identification of bound functions for the loops. 6) Augmentation of annotations to show total correctness. 7) Derivation of an inverse method with partial correctness annotations. 8) Identification of bound functions and augmentation for total correctness. 9)

Uploaded by

Mohammed Al-sadi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
97 views14 pages

Second Formal Report

This document contains a student's coursework submission that includes: 1) A mathematical expression to convert a date to days since January 1st, 1980. 2) A Spec# specification for a method to validate if a date is valid. 3) A Spec# specification for a method to calculate the number of days between a given date and January 1st, 1980. 4) An implementation of the above method with loop invariants. 5) Identification of bound functions for the loops. 6) Augmentation of annotations to show total correctness. 7) Derivation of an inverse method with partial correctness annotations. 8) Identification of bound functions and augmentation for total correctness. 9)

Uploaded by

Mohammed Al-sadi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 14

DEPARTMENT OF COMPUTING AND COMMUNICATION

TECHNOLOGIES
P00401: Formal Software Engineering
Course Work Two
MOHAMMED AL-SADI
14075351
Friday, November 29, 2014

1) Write a mathematical expression that related a date in the form year, month, day to
days since January 1st, 1980. You might find it convenient to express this in the
syntax of Spec#.
Inputs:
dd: Given date.
mm: Given month.
yy: Given year.
Days =

(dd-1) +

daysInYear(i) +

daysInMonth(i,yy)

2) Assuming the existence of implemented Spec# methods with specifications:


bool IsLeapYear(int y)
requires y >= 1980;
ensures result == year y is a leap year;
int DaysInMonth(int y, int m) requiresy>=1980&&1<=m&&m<=12;
ensures result == number of days in month m of year y;
formalise the Spec# specification of a method:
bool IsValidDate(int y, int m, int d)
requires y >= 1980;
result == y, m, d is a valid date; // <-- you have to formalise this bit

requires y 1980 && 1m&&m 12 && 1d && d DaysInMonth(y,m)


ensures y 1980 && 1m&&m 12 && 1d && d DaysInMonth(y,m)
or
// A little bit weird but it does its job
ensures forall(int y 1980 , int m in(1:12), int d in(1: DaysInMonth(y,m)) ; true)

3)Complete the Spec# specification of a method with heading: int DaysSince1Jan1980(int


year, int month, int day)
requires ...;
ensures ...;
that need only work where y, m, d constitute a date no earlier than the start of 1980. You may
create your own auxiliary functions if you wish (for example DaysInYear).

Ill assume that I have 2 auxiliary functions


1 DaysInYear(int y) ;

It returns the number of days in given year (int y);

2- DaysInMonth(int y, int m) ; It returns the number of days in given year (int y) and Given
month (int m);

int DaysSince1980(int year, int month, int day )


requires y 1980 && 1 m && m 12 && 1 d && d DaysInMonth(year, month)
ensures result == ( (day-1) +
sum {int i in (1980:year-1); DaysInYear(i)} +

// include all the years except the current year

sum {int k in (1:month-1) ; DaysInMonth (year,k) } // include all the months except the
current month

4) Following the methods taught in the formal-derivation part of the module, derive
an implementation of the method DaysSince1Jan1980 and annotate it with suitable
loop invariants to show its partial correctness.
Hint: You will find it easiest to implement this in two parts: firstly summing the days
in the whole years since 1980 and then the days since the start of year y.
You may use material from the modules formal-derivation lectures without
acknowledgement.
/* I have my own auxiliary functions */
DaysIn(y,m integer): integer;
DaysInYear(y integer): integer;
/* I have my own auxiliary functions */
(*PRE: year1980 && 1month12 && 1dayDaysIn(year,month)*) //Pre
y=1980 ; m=1 ; totalDays=0 //Initi
(*inv: DaysSince1Jan1980 = (i:1980<=i<=y-1.DaysInYear(i)) *)
while y year do
(*inv& (yyear))*)
if( isLeapYear(y) ) {
totalDays: totalDays +366}
else{
totalDays: totalDays +365}
y:y+1
(*inv *)
end
(*inv&(~ yyear) post*)
(*Inv: DaysSince1Jan1980 = (i:1<=i<=month-1 .DaysIn (year,i )) *)
while m month do
(* inv&(mmonth) *)
totalDays: totalDays + DaysIn(m,year)
m:m+1
(* inv *)
end
(*inv&(~ ymonth) post*)
totalDays = totalDays + day
(*Post: (i:1980<=i<=y-1.DaysInYear(i)) +
(i:1<=i<=month-1 .DaysIn (year,i )) + day-1
*)

5) Identify a suitable bound function for each loop in your method and explain your
choice.
First loop:
bound=(year-y)
The bound function is year-y because with every loop the year
Second loop:
bound=(month-m)
6) Augment the annotation of your implementation to show its total correctness.
DaysSince1Jan1980 (year, month, day)
(*year1980 && 1month12 && 1dayDaysIn(year,month)*) //Pre
y=1980 ; m=1 totalDays=0 //Initi
(*inv: DaysSince1Jan1980 = (i:1980<=i<=y-1.DaysInYear(i)) & (year-y)>0*)
while y year do
(*inv& (yyear) & bound=(year-y)*)
if( isLeapYear(y) ) {
totalDays: totalDays +366}
else{
totalDays: totalDays +365}
y:y+1
(*inv& (year-y)<bound*)
end
(*inv&(~ yyear)=>post*)
(*Inv: DaysSince1Jan1980 = (i:1<=i<=month-1 .DaysIn (year,i )) &(month-m)>0
*)
while m month do
(* inv&(mmonth)&bound=(month-m)*)
totalDays: totalDays + DaysIn(m,year)
m:m+1
(* inv & (month-m) < bound*)
end
(*inv&(~ ymonth)=>post*)
totalDays = totalDays + day
(*Post: (i:1980<=i<=y-1.DaysInYear(i)) +
(i:1<=i<=month-1 .DaysIn (year,i )) + day-1
*)

7)Derive a Spec# implementation to be the inverse operation to DaysSince1Jan1980:


void DaysBackToDate(int days; out int y, out int m, out int d)
requires days > 0;
ensures IsValidDate(y, m, d) && days == DaysSince1Jan1980(y, m, d);
including invariants that show it to be partially correct.
Note: an out parameter in C# is like a var parameter in Pascal. It requires the actual
parameter to be a variable and it carries a value out of the method through the
parameter.
(*Pre days1*) // days is given and must be greather than one
(*INITI*)
days=days-1; // when days equal one, it means we should not add any days & It remains one, the ini
support this
int year = 1980 ; int day = 1 ; int month =1; // I have ini day to one, so if the input days is 1, the day
remain
(*Inv: days365 & !(isLeapYear(year) & days==365)) *)
While(days365 && !(days==365 && isLeapYear(year)) // if we have 365 days & leap year dont enter
loop
{
(*INV & (days365 && !(days==365 && isLeapYear(year)) *)
if(leapYear(year) && days366) {
days=days-366;
year++;}
else{
days = days-365;
year ++;
}

// if it is leap year , subtract 366 and add a year

// if common year , subtract 365 and add a year

(*INV *)
}

// end of loop
(*INV & ~( days365 && !(days==365 && isLeapYear(year)) *)
(*POST 1 days<365 *)

(*INV: 1 days=days-daysInMonth(month,year) *)
While (days >= daysInMonth(month,year)) {
// month calculation if current day days in current month
add one month
(*INV & (days>= daysInMonth(month,year)) *)
days=days-daysInMonth(month,year);
month++;
(*INV *)
}
//end of loop
(*INV & ~ (days >= daysInMonth(month,year)* )
(*post: days< daysInMonth(month,year) *)
day = day + days; // add the extra days

8) Identify suitable bound functions and augment the annotation of your


implementation to show its total correctness.
(*Pre days1*) // days is given
(*INITI*)
int year = 1980 ; int day = 1 ; int month =1;
(*Inv: days365 & !(isLeapYear(year) & days==365)) & (bound =days) 1 *)
While(days365 && !(days==365 && isLeapYear(year)) { // if we have 365 days & leap year dont enter
loop
(*INV & (days365 && !(days==365 && isLeapYear(year)) & (bound=days) *)
if(leapYear(year) && days366) {
days=days-366;
year++;}
else {
days = days-365;
year ++;
}

// if it is leap year , subtract 366 and add a year

// if common year , subtract 365 and add a year

(*INV & (days-365 OR days-366 ) < (bound=days) *)


}
// end of loop
(*INV & ~( days365 && !(days==365 && isLeapYear(year)) *)
(*POST 1 days<365 *)

(*INV: 1 days=days-daysInMonth(month,year) & (bound=days) daysInMonth(month,year) *)


While (days >= daysInMonth(month,year)) {
// month calculation if current day days in current month add
one month
(*INV & (days>= daysInMonth(month,year)) & (bound=days) *)
days=days-daysInMonth(month,year);
month++;
(*INV & (1<=days)< bound *)
}
//end of loop

(*INV & ~ (days >= daysInMonth(month,year)* )


(*post: days< daysInMonth(month,year) *)
day = day + days; // add the extra days

9) Study the some of the many posts about the Zune bricking code. Criticise them
where you think they are wrong or poorly expressed or where the corrections offered
are either wrong or messy.
The post from Brian Hayes in his blog (2009) is an interesting material because he has
also criticized other posts. Going through his post allows criticizing more than one view at
the same time. After the introduction of the problem and the quote of the original source
code, Hayes spotted the problem technically, and described it clearly. He supposed the case
when the value of days is 366 and traced the code. After that he said:
This is just what happened on December 31, 2008, which was day 10,593 in Zune time. The
bug would be triggered on the last day of any leap year; it wasnt observed before now
simply because the Zune didnt yet exist the last time February had 29 days.
Brian Hayes(2009)
Then he directly moved to criticize others posts. Hayes didnt describe the problem of the
code from a general view. Assuming the case when the variable days equal 366 is enough for
spotting the bug in 31 Dec 2008. A critical part missing from Hayess description is why the
code doesnt crash while the year is 1980? The code start counting from 1980 (leap year) and
goes till 31 Dec 2008 then crash. The code doesnt crash on 1980 and all the following 6
years (84,88,02,04), which is the missing part that Hays didnt, explored clearly.
The first two solutions that Hayes criticized are wrong. The third one is a good solution but
Hayess notion of using break statement is interesting. Hayes considered using a break
statement is not a good practice. He didnt justify his view of not using break statement but
formally he was right. In formal method, using the break clause means the guard will still
true after the loop. Well, the guard must be not true after the loop execution to get the right
post condition. (*post: Inv & ~(guard) *)
Hayes solution:
Below, the code by Brian to solve the problem.
year=ORIGINYEAR;
while(days>0)
{
if(IsLeapYear(year))

days=366;
else
days=365;
if(days>0)
year+=1;}

Hayes proposed this solution, which works very well in 31 Dec 2008 and any following year.
However, it is not general and cant be used in earlier days. The final result of the variable
days would be a negative number, which is a fatal error. He mentioned that later and
proposed another solution on Lisp. The problem with his Lisp solution that the code starts
counting from 1979, which is the idea that he had already rejected before when he said:
I suppose I consider this an improvement over the alternatives given above, but I dont
really like it. What annoys me most is the trick of initially setting year to ORIGINYEAR - 1.
This violates an implicit assumption that year will always be equal to or greater than 1980.
Brian Hayes has proposed some well-documented solution especially the Lisp solution. Well
he hasnt addressed how he solved the problem clearly. Another issue is his Lisp solution
considers the original year 1979. Which is not the case in Zune code, because the Zune
counts the days given the number of days since 1980. Which means his solution will not
work in Zune.
Another post to consider is by Steven Pigeon (2008) blog. He has provided brief overview of
when the code will crash and why. He has also proposed an interesting ways of testing the
code before releasing it. There is a completed testing code by him. Unfortunately it is not
enough to provide a solution for this problem rather than it is useful to know how to detect
this bug. Compared to Brian Hayes (2009) post, Pigeon did more tests to aid how to detect
the bug than Brian. In the other hand, Brian has provided a wide range of solution although
they arent satisfied.

10) Devise your own explanation of what is wrong with the Zune code, making reference to
the ideas of formal derivation.
The problem with the zone code may happens in any current leap year and to understand
whats go wrong with code lets me down these 2 rules that could be inferred from the Zune
code (The bugged version):
1-In the case of common year and 365 days or more; add new year and subtract 365.
2- In the case of leap year and 367 days or more; subtract 366 days and add new year.
The problem related to the 2nd rule. What would happen if it is leap year and the days equal
366? The code clearly says, DO NOTHING! technically go in loop for about 24 hours.
Below a simple tracing for the code using the figure.

In term of formal program derivation, terminating loop must be done using suitable bound
function.
At 31 Dec 2008 when days =366, the first IF guard will be satisfied because 2008 is a leap
year, but the internal IF will not because days are equal to 366 not greater.
The problem here there is no bound function executed in case we havent satisfied the
internal IF which causes the infinite loop. So the number of days will not go down to exit the
loop and the value of days will remain the same and the loop will never exit.
The last question here is, In 2012, will the code crash in 2008 or only in 2012?
Well, both of 2012 and 2008 are leap years, but when we are in 31 Dec 2012, and while the
code is counting days from 2008, the days will be more than 367 in 31 Dec 2008 (actually,
366+(days of 2009,2010,2011 and 2012)). So it will handle the leap year 2008 correctly. In
31 Dec 2012 the days will be exactly 366 and the code will crash. In formal programming,
the bound must not remain the same. If the bound remains the same while executing the loop,
the loop will not exit, which is the problem with Zune code. Specifying suitable bound (that

changes in any loop repartition) and handling the selection statement correctly could prevent
the errors in Zune code.
Part II:

2.1 Formal and Typical Development Approaches

he core feature of formal methods is to ensure holding the specification and


invariants during the machine life. Which makes it a perfect choice for safety
critical systems. Understanding the specification of such a system aids in inferring
the invariants in mathematical way. Specifying certain invariants is done (like
number of days must not be minus value in any condition) to be valid and satisfied all the
time. Determining the specification for the machine is to some extent the equivalent stage to
the REQUIREMENT GATHERING in traditional methodologies, while in formal methods the
engineers use Software Requirement Document to specify and understand the details of the
proposed system (Abrial,2006). Introducing the mathematical principals in the formal
development approaches help verifying rigorously critical systems and produce concrete
units of code. A tool like AtelierB provides the result whether we have any proof obligations
or not. Which is the same of TESTING phase in the traditional approaches. The main point of
formal method main delivery is to deliver a good tested and verified code so engineers can
pass to the next stage with a confident the ABSTRACT MODEL they have done is correct so
far. The refinement stage in formal methods, allows building a precise model gradually by
specifying more details. Dealing with data structure rather than the abstract models (e.g. set
theory) is a key point of the refinement stage. Data structures (e.g. arrays or sequences)
replace the normal sets used in the basic machine. In this stage, we are drawing a clearer
shape for the machine, but it is not the end according to Abrial in his book (2010, pp. xv).
Incorporating the data structures and introduce them with the abstract operations - that we
developed before refinement is also required for a success refinement. Before the end of
this stage, it is necessary to check the proof again so the machine or the model we are
developing can pass the equivalent stage to the DESIGN and IMPLEMENTATION thats used
in the traditional developments approaches. The outcome of this stage sometimes called the
CONCRETE MODEL referring to Abrial article (Abrial,2006).The last stage of the system
production is to rely on tools to produce the executable code. Some tools like AtelierB could
generate an equivalent executable code in programming language like C. However, the code
is not always correct while some parts of the last model. The imprecise model could forces
developer to make changes to get correct translation. Translation problem is one of the
weakest points in formal developments and the formal approach is usually criticized
regarding this issue. Another critical issue is the fail of proofer in some situation. A tool like
AtelierB allows the engineers to add their own rules of proof, however, it is not always the
case. The proofer sometimes fails on clearly correct logical situations. As the main feature of
formal methods is to create proofed units of code, proof failures would definitely contradict
this feature. Which means using formal methods in some applications would be difficult and
even not efficient especially when the proofer fail or give wrong-negative results.

2.2 Other Formal Development Approaches


Declarative programming or declarative modeling is an example of formal development
techniques. The non-imperative style that declarative programming follows aids in describing
the final result of such a system. Declarative programming technique is concerned with
specifying the general logic of what the program should do. In other words, its about the
result not how to deliver this result (Control flow of program). Declarative programming uses
many tools like regular expression and database query languages to specify the general rules
of the system. The declarative programming term is a general term and this technique
includes other techniques. One of those is the functional programming, which allows
specifying the result for certain function rather than the way to deliver this result. Haskell is
one of the functional programming languages, and the interesting thing about functional
languages the ability of compiler to re-write the code while the result remains the same
('Declarative programming', 2014). Another interested formal development technique is
Design by contract. In Design by contract, pre condition, post condition and the invariant are
written and defined in a formal way to ensure holding them before during and after the
execution of code. Spec# and Eiffel are examples of programming by contract languages
('Design by contract', 2014). In Spec# (Programming language by Microsoft) developers
specified the ensures and requires clauses formally, to check them before and after the
execution. As Spec# is extended from C#. Its syntax is self-descriptive and any C# developer
could learn it easily. It allows many developers to take the advantage of formal approaches in
their programs, hence, producing error free programs (Barnett et al.,2005) .

2.3 Related case study to the course work


My first course work was about Cargo system. The main idea was about handling the process
delivering a parcel to a certain location after going through many locations (HUBS). Roissy
Airport shuttle system is in general view handle the same logic (Badeau and Amelot
,2005). The Roissys system manages the shuttles between terminals, which is related to
manage the parcels.The parcels go through many location till it arrives the final destination.
Roissys developers started by specifying the general specification of the system then going
in depth gradually. After that , building the abstract model and refine it many times to reach
to free of errors state using the proofer. The figure1 (CLEARSY SYSTEM ENGINEERING,
http://www.clearsy.com/pdf/val-roissy.pdf, no date). shows the repetition of building the
abstract model and the process of checking the specification document (Requirement) and
compare them with the current model (Inspection) to be sure thar the required specifiation
has been implemented correctly.
In Cargo system the same process has been in a high level way. The main requirement of any
cargo system has been specified. After that, the process of making sure that current abstract
model comply with the requirement has been done. Next, it should be clear that the abstract
model describes and contains the same rules and specification of the proposed to be able to
processed and start system proofing. Finally, the concrete model is done in the cargo system
by refining the abstract model. However, it should be mentioned that the first course work

Figure 1: Abstract and concrete model of Roissy system.

didnt include translating the system


into another programming language
like C or ADA as the developer of
Roissy did (figure 1).

REFERENCES

Hayes,B. (2009) 'The Zune Bug', bit-player, 3 January. Available at: http://bitplayer.org/2009/the-zune-bug (Accessed: 30 November 2014).
Pigeon,S. (2008) 'The Zune Freezes: A Stupid, Avoidable Bug. ', Harder, Better, Faster,
Stronger, 31 December. Available at: https://hbfs.wordpress.com/2008/12/31/the-zunefreezes-a-stupid-avoidable-bug/ (Accessed: 30 November 2014).
Abrial, J. (2006) 'Formal methods in industry: achievements, problems, future.', Proceedings
of the 28th international conference on Software engineering,2006 pp. 761-768. doi:
10.1145/1134285.1134406
Abrial, J. R. (2010). Modeling in Event-B: system and software engineering. Cambridge
University Press.
'Declarative programming' (2014) Wikipedia. Available at:
http://en.wikipedia.org/wiki/Declarative_programming (Accessed: 30 November 2014).
'Design by contract' (2014) Wikipedia. Available at:
http://en.wikipedia.org/wiki/Design_by_contract (Accessed: 30 November 2014).
Barnett, M., Leino, K. & Schulte, W. (2005) 'The Spec# programming system: An overview.
', Construction and analysis of safe, secure, and interoperable smart devices, 2005. 49-69.
Badeau, F & Amelot, A. (2005) ' Using b as a high level programming language in an
industrial project: roissy VAL ', Proceedings of the 4th international conference on Formal
Specification and Development in Z and B (ZB'05),2006, pp. 334-354. doi: 10.1007/11415787_20

CLEARSY SYSTEM ENGINEERING (no date) Using B as a High Level


ProgrammingLanguage in an Industrial Project: Roissy VAL. Available at:
http://www.clearsy.com/pdf/val-roissy.pdf (Accessed: 30 November 2014).

You might also like