Vòng lặp bất biến cho một thuật toán


7

Tôi đã phát triển mã giả sau đây cho bài toán tổng của các cặp:

Cho một mảng A số nguyên và số nguyên b, trả về CÓ nếu có vị trí i,j trong A với A[i]+A[j]=b, KHÔNG khác.

Bây giờ tôi nên nêu một bất biến vòng lặp cho thấy thuật toán của tôi là chính xác. Ai đó có thể cho tôi một gợi ý về một bất biến vòng lặp hợp lệ?

PAIRSUM(A,b):
YES := true;
NO := false;
n := length(A);
if n<2 then
  return NO;

SORT(A);
i := 1;
j := n;
while i < j do  // Here I should state my invariant
   currentSum := A[i] + A[j];
   if currentSum = b  then
      return YES;
   else 
    if currentSum < b then
      i := i + 1;
    else
      j := j – 1;
return NO;

3
Chào mừng bạn Lưu ý rằng một bất biến vòng lặp không chứng minh thuật toán của bạn là chính xác. Nó cần phải là một bất biến chính xác theo nghĩa là nó phù hợp để chứng minh hậu quả mong muốn. Cũng lưu ý rằng bằng chứng như vậy trở nên khó hơn nếu bạn thoát khỏi vòng lặp sớm; nó có thể là một ý tưởng tốt để viết lại thuật toán sao cho toàn bộ vòng lặp luôn được xử lý.
Raphael

1
Bạn thấy cái giá của sự thông minh: bằng chứng trở nên khó khăn. 1) Sự đúng đắn phụ thuộc rất nhiều vào Aviệc được sắp xếp. 2) ijchuyển đổi vai trò ở cuối vòng lặp tùy thuộc vào đầu vào. 3) Số lần thực hiện vòng lặp phụ thuộc vào đầu vào.
Raphael

1
Tôi nghĩ rằng bạn đã quên nói rằng mảng của bạn sẽ được sắp xếp ngày càng nhiều nếu bạn muốn thuật toán này là chính xác.
Gopi

(oups, Raphael đã nói rằng :(, mặc dù bạn vẫn chưa sửa đổi nó.)
Gopi

Câu trả lời:


5

Đơn giản hóa đầu tiên: thuật toán này, bằng cách kiểm tra, không thể nói CÓ khi không nên, vì nói CÓ ngay sau khi kiểm tra xác minh rằng tổng tại các vị trí hiện tại là b.

Đơn giản hóa thứ hai: Nó luôn chấm dứt, kể từ khi ijdi chuyển theo cách đơn điệu lên xuống tương ứng, và người ta luôn di chuyển. Vì vậy, cuối cùng họ trở nên bằng nhau và vòng lặp kết thúc.

Vì vậy, hãy giả sử rằng câu trả lời là CÓ, và xy là những chỉ số chúng ta quan tâm, sau khi sắp xếp, với x càng nhỏ càng tốt và sau đó ycàng lớn càng tốt (chúng ta có thể có một vài cặp có thể với tổng đúng). Đây là bất biến:

  • Khi bắt đầu vòng lặp, ixjy.

Nếu i=xj=y, sau đó thuật toán sẽ dừng lại và nói CÓ. Bất biến vòng lặp là tầm thường khi bắt đầu, và cũng không quan trọng khii<xj>y. Nhưng nếui=xj>y, sau đó, vì mảng được sắp xếp A[i]+A[j]>b, bởi vì làm thế nào yđã được lựa chọn. Vì thếj giảm trong tất cả các lần lặp lại trong tương lai cho đến khi nó đạt được y. Trường hợp khác, nơij được cho y đầu tiên là đối xứng.

Như đã lưu ý ở trên, thuật toán luôn chấm dứt, ngụ ý thuật toán sẽ thực sự nói CÓ, vậy là xong.

Chỉnh sửa: Vì câu hỏi này là về văn bản chứng minh, đây là một lựa chọn khác, mà tôi nghĩ là khó hiểu hơn và nghiệt ngã hơn. Tôi không biết Tony Hoare có chấp thuận hay không.

Đây là bất biến: Một đỉnh của vòng lặp,

  • Nếu s<i, sau đó, cho bất kỳ x[n], A[s]+A[x]b
  • Nếu t>j, sau đó, cho bất kỳ x[n], A[x]+A[t]b

Một lần nữa, điều này giữ trống ngay từ đầu. Bây giờ chúng tôi kiểm tra một số trường hợp:

  • Nếu i=j, sau đó trong bất kỳ cặp chỉ số xy ít nhất một trong x hoặc là y nhỏ hơn i hoặc lớn hơn j. Điều này loại trừ đầu vào là CÓ. Vòng lặp kết thúc và nói KHÔNG, vì vậy chúng tôi đang trong tình trạng tốt.
  • Giả sử vòng lặp không kết thúc. NếuA[i]+A[j]=b, câu trả lời là CÓ, và thuật toán hoạt động.
  • Giả định A[i]+A[j]b.
  • Subcase: Nếu có một j, theo giả thuyết j<j, như vậy mà A[i]+A[j]=b, sau đó A[j]<A[j] bởi vì mảng đã được sắp xếp, vì vậy A[i]+A[j]>b, nguyên nhân jLàm giảm xuống. Điều này cho thấy rằng bất biến được duy trì choi. Để xem nó choj, chỉ lưu ý rằng nếu có một x như vậy mà A[x]+A[j]=b, sau đó x<i, được loại trừ bởi giả thuyết quy nạp.
  • Subcase: Nếu có một i, theo giả thuyết i>i, như vậy mà A[i]+A[j]=b, sau đó A[i]>A[i] bởi vì mảng đã được sắp xếp, vì vậy A[i]+A[j]<b, nguyên nhân ităng. Điều này cho thấy rằng bất biến được duy trì choj. Để xem nó choi, chỉ lưu ý rằng nếu có một x như vậy mà A[i]+A[x]=b, sau đó x>j, được loại trừ bởi giả thuyết quy nạp.
  • Subcase: Nếu cả hai trường hợp còn lại đều giữ, thì bất biến được duy trì một cách tầm thường.

Cuối cùng, chúng tôi lưu ý rằng khoảng cách giữa ij luôn luôn nhỏ hơn, vì vậy cuối cùng chúng phải trở nên bằng nhau và thuật toán sẽ dừng lại.

Lưu ý: Đây là lập luận chính xác, nhưng khó theo dõi hơn. Bạn cũng có thể viết bằng chứng như thế này bằng một số kỹ thuật chuyên môn:

  • Đừng nói những gì thuật toán làm. Ở đây, nếu đầu vào là CÓ, thuật toán LUÔN LUÔN cung cấp cho bạn các chỉ số xác nhận càng gần đầu càng tốt. Bằng chứng thứ 2 khéo léo che giấu điều này trong một phân tích trường hợp.
  • Đừng đặt tên cho mọi thứ. Đã ẩn những gì thuật toán làm, cũng không đặt tên điểm dừng.
  • Đừng bỏ qua các trường hợp dễ dàng. Thuật toán này rõ ràng hoạt động cho các trường hợp KHÔNG. Bằng cách không lưu ý rằng lên phía trước, chúng ta có được một bất biến phức tạp hơn.

Đây là một bằng chứng cấp cao đẹp, nhưng làm thế nào để bạn sử dụng ý tưởng này trong một bằng chứng kiểu Hoare nghiệt ngã? Đặc biệt, bạn nhận được ở đâux,ytừ (như họ có thể không tồn tại)?
Raphael

@Louis Tôi cũng nghĩ mỉa mai là một ý tưởng tồi vì nó có thể dễ dàng bị hiểu lầm. Ngoài ra, bạn Misfire ở đây vì phiên bản thứ hai của bạn cũng ở cấp độ cao. Bằng chứng kiểu Hoare sử dụng các đối số cục bộ , di chuyển giữa các câu lệnh mã riêng lẻ. Tôi không biết OP thực sự muốn đi theo hướng đó; Tôi giả định rằng.
Raphael

3

Có lẽ một cái gì đó như thế này?

Sau các klần lặp của vòng lặp, A[i...j]chứa một phân đoạn kích thước được sắp xếp n - k, với kcác phần tử ban đầu, không có phần tử nào kết hợp bvới bất kỳ phần tử nào khác A, đã bị xóa.

Có lẽ một cách rõ ràng hơn để nói điều này chỉ đơn giản là:

Sau các klần lặp của thân vòng lặp, for 0 <= k < n, A[i...j]là một phân đoạn (tiếp giáp) được sắp xếp của A[1...n](có các phần tử theo cùng thứ tự và có cùng giá trị như trước lần lặp đầu tiên) của thân vòng lặp chứa kcác phần tử (ví dụ i + j = k + 1:) A[1...n]có chứa một cặp yếu tố mong muốn nếu và chỉ khi A[i...j]có, là tốt.

Bất biến vòng lặp này rất hữu ích bởi vì, nếu vòng lặp kết thúc (nghĩa là đạt đến điều kiện kết thúc), thì đó Alà mảng được sắp xếp với một phần tử và chúng ta có thể kết luận rằng không có cặp phần tử nào trong đó A.

Dưới đây là một bản phác thảo / ý tưởng cho bất biến này:

  • Trước khi vòng lặp, A[1...n]là một mảng được sắp xếp và i = 1, j = n. Do đó, bất biến vòng lặp được đảm bảo sau các k = 0lần lặp của thân vòng lặp.
  • Giả sử rằng bất biến vòng lặp giữ đúng cho kđến và bao gồm k'.
  • Bây giờ chúng ta chỉ ra rằng vòng lặp bất biến giữ cho k' + 1. Có ba trường hợp cho hành vi của thân vòng lặp trong quá trình lặp tương ứng với k = k' + 1:
    • A[i] + A[j] = b, trong trường hợp vòng lặp trả về đúng YESvà không có phép lặp sau lần lặp này của vòng lặp;
    • A[i] + A[j] < b, Trong trường hợp mà chúng tôi có thể yên tâm loại bỏ các phần tử nhỏ nhất của A, A[i]. Để thấy điều này, lưu ý rằng vì A[j]là phần tử lớn nhất trong A, nếu tổng của phần tử đó và phần tử khác Anhỏ hơn b, thì tổng của phần tử khác đó và bất kỳ phần tử nào Acũng được đảm bảo nhỏ hơn b.
    • A[i] + A[j] > b, Trong trường hợp mà chúng tôi có thể yên tâm loại bỏ các phần tử lớn nhất của A, A[j]. Lý do tương tự như trường hợp A[i] + A[j] < b.
  • Sau khi chấm dứt thân vòng lặp, i = jvà do đó Achỉ chứa một phần tử. Vì Abây giờ chỉ chứa một phần tử, nên trường hợp Akhông chứa hai phần tử này là không đáng kể b.

Chứng minh tính đầy đủ của bất biến vòng lặp cho thấy rằng không có giải pháp nào sau khi chấm dứt vòng lặp

Điều này giải quyết một câu hỏi được đưa ra trong các ý kiến ​​của Raphael, đây là một số giải thích rõ ràng về lý do tại sao vòng lặp bất biến này là đủ.

Để vòng lặp chấm dứt, chúng ta phải có i = j. Cũng lưu ý rằng vòng lặp này luôn kết thúc, bằng cách phát ra chính xác YESnếu tìm thấy kết quả khớp hoặc bằng cách loại bỏ các phần tử mảng cho đến khi chỉ còn lại một phần tử (bằng cách tăng ihoặc giảm j). Đối số chấm dứt này không được đưa ra trong bản phác thảo ở trên, nhưng nên đơn giản.

i = j, Alà một phân đoạn được sắp xếp của kích thước một. Bởi vì không có mảng kích thước 1 thỏa mãn yêu cầu tồn tạix,y(lưu ý rằng tôi đang giải thích điều này có nghĩa là duy nhất x,y, vì nếu không thì thuật toán được cung cấp là không chính xác; xem xét A = [1]b = 2) ở đâuA[x]+A[y]=bvà bởi vì bất biến vòng lặp, chúng ta biết rằng không có phần tử nào A[k], ở đâu k != i = j, có thể được thêm vào bất kỳ phần tử nào A[k'], ở đó k' != k, để đạt được tổng b, điều này hoàn thành ý tưởng chứng minh.

Giả định / sự kiện được sử dụng cho điều kiện chấm dứt:

  • Câu hỏi đã được giải thích chính xác, tức là xylà khác biệt; bạn phải thêm các phần tử tại các vị trí khác nhau trong mảng ban đầu.
  • i = j sau khi chấm dứt (bình thường) của thân vòng lặp và vòng lặp luôn kết thúc;
  • Không có hai cái khác biệt xygiữa ijnếu i = j; không có hai chỉ số trong một phân khúc cỡ 1.
  • Vào bất biến vòng lặp, cho k != i = j, không có cách nào để thêm A[k]bất kỳ A[k'], k != k', để có được b; chúng ta chỉ loại bỏ, bằng cách tăng ivà giảm j, các phần tử không thể kết hợp bvới bất kỳ phần tử nào của mảng ban đầu.

Xin vui lòng giúp đỡ nếu tôi tiếp tục thiếu một cái gì đó tinh tế.


Tôi nghĩ bằng chứng của bạn là chính xác (nhưng lưu ý rằng tôi chỉ lướt qua nó). Làm thế nào bạn đến trên nó? Đây là một bài tập học tập, vì vậy chỉ ra cách bạn thực hiện phương pháp của mình để giải quyết vấn đề sẽ được đánh giá cao.
Gilles 'SO- ngừng trở nên xấu xa'

3

Luôn luôn có vô số vòng lặp bất biến hợp lệ. Mẹo nhỏ là tìm một cái đủ để chứng minh những gì bạn muốn chứng minh về thuật toán và bạn có thể chứng minh (thường là bằng cách cảm ứng qua số lần lặp lặp).

Có ba phần trong việc chứng minh tính đúng đắn của thuật toán này:

  • Thuật toán không bao giờ thực hiện một bước không chính xác. Ở đây, các bước không chính xác tiềm năng là truy cập vào một phần tử mảng nằm ngoài giới hạn của mảng.
  • Khi thuật toán trả về YEShoặc NO, đầu ra này là chính xác.
  • Thuật toán chấm dứt cho mọi đầu vào.

Để cho chính xác, bạn cần phải chứng minh rằng 1in1jn. Điều này tốt hơn là một phần của bất biến của bạn. Đưa ra điều kiện vòng lặpi<j, bạn có thể ngưng tụ điều này để 1i<jntại lối vào cơ thể vòng lặp. Điều kiện này không đúng khi kết thúc kiểm tra vòng lặp, nhưng nó có thể hữu ích để nhận thấy rằngij (bởi vì bên trong thân vòng lặp, với i<j, ij chỉ thay đổi bởi 1, điều tồi tệ nhất có thể biến bất bình đẳng nghiêm ngặt này thành một đẳng thức).

Khi return YESđược thực thi,A[i]+A[j]=brõ ràng. Vì vậy, phần này không cần bất cứ điều gì cụ thể để được chứng minh.

Khi return NOcâu lệnh cuối cùng được thực thi, có nghĩa là vòng lặp kết thúc bình thường (và vì vậyi<j là sai), bạn cần chứng minh rằng i,j,A[i]+A[j]b. Tài sản này rõ ràng là không đúng nói chung: nó không giữ nếu câu trả lời là YES. Bạn cần tăng cường tài sản này: bạn có một trường hợp đặc biệt, cần phải được khái quát hóa. Đây là trường hợp điển hình của một thuộc tính chỉ áp dụng cho một phần của mảng đã được duyệt qua: vòng lặp được xây dựng sao cho nếu(x,y) là một giá trị trước đó của (i,j) (I E 1xijyn(x,y)(i,j)) sau đó A[x]+A[y]b. Điều này đã được thể hiện tốt hơn trong bất biến vòng lặp.

Chúng ta đã xong chưa? Không hẳn; tất cả những gì chúng ta biết về việc chấm dứt vòng lặp thông thường làxi,yj,A[x]+A[y]b. Nếu chúng ta cóx>iyj, hoặc là xiy>j: liệu chúng ta có thể có A[x]+A[y]b? Thật khó để nói mà không có thêm thông tin. Trong thực tế, chúng ta nên phân biệt một số trường hợp khiA[x]+A[y]>b và các trường hợp khi A[x]+A[y]<b. Với các thuộc tính này, chúng ta có thể sử dụng thực tế là mảng được sắp xếp để suy ra sự thật về các vị trí khác trong mảng; chỉ vớib, chúng tôi không có gì để làm việc. Chúng tôi không biết đường nàoA[x]+A[y] nói dối cho một số ngẫu nhiên x<iy>j; nhưng chúng ta biết điều gì xảy ra ở ranh giới: nếui được tăng lên, đó là bởi vì A[i]+A[j] quá nhỏ, và nếu j đang giảm dần, đó là vì A[i]+A[j]nó quá rộng. Hãy nghĩ những gì bất biến vòng lặp có thể diễn tả điều này; Tôi sẽ đưa ra một khả năng dưới đây.

Lưu ý rằng thuộc tính này không trực tiếp cung cấp cho bạn điều kiện mong muốn cho return NOcâu lệnh; bạn sẽ vẫn cần xem xét những gì đã xảy ra trong lần chạy cuối cùng của vòng lặp, hoặc cách khác để chứng minh một bất biến vòng lặp mạnh hơn, xem xét kỹ hơn khi nàoA[x]+A[y]<b và khi A[x]+A[y]>b.

Cuối cùng, để chấm dứt, bạn cần liên quan ijvới số lần lặp qua vòng lặp. Ở đây, điều này là đơn giản: hoặci hoặc là j di chuyển ở mỗi lượt, vì vậy ji giảm bởi 1tại mỗi vòng lặp; bạn không cần phải sử dụng bất biến vòng lặp để chứng minh điều này.

Chúng tôi đã thu được bất biến sau:

1ijn(x<i,y<j,A[x]+A[y]b)(x<i,A[x]+A[j]<b)(y>j,A[i]+A[y]>b)

Và bạn đang thiếu phần sau khi bạn có bất biến. Và, như bạn nói, "Ađược sắp xếp "phải là một phần của bất biến.
Raphael

Ồ, và một lỗi nhỏ: i<jkhông phải là bất biến.
Raphael

1
@Raphael Điểm tốt với i<j. Thực sự không cần thiết phải thực hiện điều đó thông qua cảm ứng, nhưng như một điểm phương pháp luận, nó quan trọng. Tôi xem xét thực tế rằngAkhông thay đổi trong vòng lặp (và do đó vẫn được sắp xếp, nhưng thực tế là nó không thay đổi cũng rất quan trọng) rõ ràng ở đây (về mặt kỹ thuật nó cũng phải được chứng minh, nhưng tôi sẽ làm riêng và nhận được nó ra khỏi đầu tiên). Điều gì xảy ra sau khi bạn có bất biến không phải là một phần của câu hỏi; đó là một phần của bài tập có thể được thực hiện khá máy móc.
Gilles 'SO- ngừng trở nên xấu xa'

Phần sau đó cho thấy tại sao bất biến là đủ; nhưng sau đó, bạn (loại) bao gồm điều đó trong đạo hàm của bạn.
Raphael

2

Không có cách nào dễ dàng để rút ra một bất biến hữu ích; lưu ý rằng vấn đề không thể tính toán được (nếu không chúng ta có thể giải quyết vấn đề tạm dừng). Do đó, bạn quay lại dùng thử và lỗi với các heuristic được đào tạo bằng kinh nghiệm. Xem câu trả lời của Gilles cho một quá trình suy nghĩ mẫu mực. Nói chung, trước tiên bạn cần điều kiện bài mong muốn (nghĩa là đặc tả đầu ra) và tìm một bất biến ngụ ý nó (cùng với điều kiện vòng lặp phủ định).

Đây là những gì tôi nghĩ làm việc:

I= A is sorted and has not been changed 1i,jn ji i<i. j>j. A[i]+A[j]b i<i. b>A[i]+A[j] j>j. b<A[i]+A[j]

Rằng ba mệnh đề sau thực sự được duy trì bởi vòng lặp - giả sử bạn không chấm dứt với CÓ, điều này là chính xác - rất tẻ nhạt để hiển thị vì chúng phụ thuộc rất nhiều và i,j có thể chuyển đổi vai trò.

Cuối cùng, bạn nhận được i=j cho phép kết hợp hai mệnh đề cuối với thực tế là phần tử cuối cùng A[i] không tổng hợp bvới bất kỳ yếu tố nào khác Kết hợp giữa các yếu tố từ trái và phải được loại trừ bởi khoản ba. Cuối cùng, hai yếu tố còn lại củai không thể tổng hợp b bởi vì mệnh đề bốn và một, và tương tự cho hai yếu tố bên phải của i.

Nếu bạn làm bằng chứng, hãy đảm bảo tuân thủ chặt chẽ các quy tắc của logic Hoare .


Điều tôi bỏ lỡ trong câu trả lời của bạn là cách bạn quyết định về sự bất biến này. (Điều đó, và bạn đã không thể hiện điều đóijluôn ở trong giới hạn của mảng, nhưng đừng bận tâm, tôi là một người sửa lỗi phần mềm.)
Gilles 'SO- ngừng trở nên xấu xa'

Điểm tốt về các chỉ số. Những điều kiện như vậy thường bị lãng quên vì chúng không cần thiết để hiển thị hậu điều kiện nhưng "chỉ" cần thiết để cho thấy rằng bạn đến đó. Cần có quy tắc Hoare cho truy cập mảng bảo vệ truy cập mảng, ví dụ:{1iA.lengthP(X)}A[i]=X;{P(A[i])}, buộc bạn phải theo dõi các chỉ số.
Raphael
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.