0
 find(c: CHARACTER; position: INTEGER): INTEGER

This feature finds a character by starting at position i and searching. Once it finds the index it outputs it. However if no such character exists in the word then 0 is output

Question: The postcondition must assert that the query returns the index of a character c in word in range pos .. word.count, or zero if there is no such character.

My Code:

find(c: CHARACTER; position: INTEGER): INTEGER
   require
            .....
   do

            .....
   ensure 
        across word as w
        some
             (w.item = c and w.cursor_index >= position)
        end
   end

Problem with this boolean equality is that when find(c,pos) is used and nothing is found the feature throws a post-condition violation.

I'm trying to make it allow the feature to output ONLY when the given c character does not exist in the word

geforce
  • 61
  • 6
  • I'm not sure that I understand correctly the question, but for your postcondition, you can do someting like: Result = 0 or else (Result >= position and word.at(Result) = c) – Louis M Jan 11 '16 at 23:42
  • No that won't work because I can't output integers it only takes boolean value – geforce Jan 12 '16 at 00:29
  • Then I don't understand your function `find'. It has an INTEGER Result type. – Louis M Jan 12 '16 at 01:17

2 Answers2

1

Assuming that it should be a complete postcondition, let's look at the problem on a case-by-case basis:

  1. Q. What is the allowed range of output values?
    A. The result can be 0 or any valid position in the word starting from position:

    valid_result_range: Result = 0 or position <= Result and Result <= word.count
    

    Here we assume that position is non-negative (hopefully this is specified in the precondition).

  2. Q. What is the output value if there are no matching characters?
    A. The output is 0. All characters with indexes starting from position do not match:

    zero_if_not_found: (Result = 0) =
        across word as wc all
            position <= wc.target_index implies wc.item /= c
        end
    
  3. Q. What is the output value if there is a matching character?
    A. It is the first position of the corresponding character starting from position:

    non_zero_if_found: (Result /= 0) implies
       (
          word [Result] = c
       and
          across word as wc all
             (position <= wc.target_index and w.target_index < Result) implies
             wc.item /= c
          end
       )
    

    This postcondition has two parts. One checks that the character is found. The other checks that there are no matching characters before that position.
    EDIT: The original code started with (Result /= 0) = ... instead of (Result /= 0) implies .... This would cause assertion violation in word [Result] when Result = 0. The code with implies if free from this issue because if an expression before implies is False then an expression after it is not evaluated.

The final postcondition is the combination of all the assertions above. The order of assertions is important because non_zero_if_found relies on the fact that Result is a valid index for word.

Alexander Kogtenkov
  • 5,770
  • 1
  • 27
  • 35
  • Just wondering, is there no reason to put "wc.target_position <= word.count"? Does the iterator do it by itself? – geforce Jan 12 '16 at 21:56
  • 1
    @GeForce, an `across` loop runs through all valid indexes only, therefore there is no need to check that the current index is a valid one, in this case in the range `1`..`word.count`. – Alexander Kogtenkov Jan 13 '16 at 05:21
1

I would change Alexander's answer very slightly:

zero_if_not_found: (Result = 0) implies ... non_zero_if_found: (Result /= 0) implies ...

To see why, consider what happens when Result = 0 and we evaluate Alexander's non_zero_if_found:

(Result /= 0) evaluates to False Then word [Result] = c evaluates to a precondition failure (valid_index - I'm assuming word is a STRING type). (changing w [Result] to word [Result] as that was a typo by Alexander, i think)

Using implies protects you against this, as the RHS doesn't get evaluated.

  • Indeed there was a mistake in my code for `non_zero_if_found`, it is corrected now. As to adding `implies` to `zero_if_not_found`, leaving the equality seems better to me, because then we know when `Result` is `0` directly from the assertion and it is safe to use equality in this case. Thank you! – Alexander Kogtenkov Jan 12 '16 at 09:53
  • OK. Looks like target_position is another typo for target_index? – user2783273 Jan 13 '16 at 10:17