2012-02-25 44 views
5
object Prop { 
    def simplify(prop : Prop) : Prop = { 
    prop match { 
     case Not(Or(a,b)) => simplify(And(Not(a),Not(b))) 
     case Not(And(a,b)) => simplify(Or(Not(a),Not(b))) 
     case Not(Not(a)) => simplify(a) 
     case _ => { 
     if (simplify(prop) == prop) prop 
     else prop 
     } 
    } 
    } 
} 

Tôi chắc chắn tôi đã có vòng lặp vô hạn do trường hợp 'mặc định' của tôi gây ra. Tôi đang sử dụng đệ quy trong mọi trường hợp. Đó là có nghĩa là, nhưng, chỉ khi Prop có thể được đơn giản hóa. Ngay khi Prop không thể được đơn giản hóa, nó sẽ trả về toàn bộ.Đoạn mã scala vòng lặp vô hạn

Tôi không thấy cách tôi có thể kiểm tra để đơn giản hơn nữa. (Tôi không được phép sử dụng các thư viện khác, như được đề xuất trong kênh freenodes #scala).

Ai đó có thể giải thích cho dù đó là 'trường hợp _' gây ra vòng lặp và cách giải quyết nó? Làm thế nào tôi có thể thử nghiệm để đơn giản hóa có thể mà không cần thực hiện một vòng lặp?

Cảm ơn trước!

Trả lời

6

Vấn đề là bạn đang cố gắng làm hai việc trong một bước cần phải xảy ra theo thứ tự - áp dụng luật của De Morgan (và loại bỏ đôi phủ định) và đệ quy đơn giản hóa mọi trẻ em. Đây là lý do tại sao chỉ cần thả một số case And(a, b) => And(simplify(a), simplify(b)) vào số match của bạn sẽ không hoạt động.

Hãy thử như sau:

val deMorganAndDoubleNegation: Prop => Prop = { 
    case Not(Or(a, b)) => And(Not(a), Not(b)) 
    case Not(And(a, b)) => Or(Not(a), Not(b)) 
    case Not(Not(a)) => a 
    case a => a 
} 

val simplify: Prop => Prop = deMorganAndDoubleNegation andThen { 
    case And(a, b) => And(simplify(a), simplify(b)) 
    case Or(a, b) => Or(simplify(a), simplify(b)) 
    case Not(a) => Not(simplify(a)) 
    case a => a 
} 
+0

Tôi hiểu ý của bạn. Mặc dù, nhiệm vụ của tôi cho tôi biết rõ ràng để sử dụng một đối tượng đồng hành. Prop.simplify (Prop): Prop trả về một mệnh đề đơn giản và tương đương bằng cách liên tục áp dụng định luật de Morgan và phép nhân đôi phủ định đối số với mệnh đề đối số. Đề xuất kết quả phải đáp ứng các yêu cầu được nêu bên dưới. (chúng tôi có một hệ thống để chạy công việc của chúng tôi chống lại một thử nghiệm) Xem: http://pastebin.com/WDuQKreD (cũng cho cá tuyết đầy đủ e tại thời điểm này) Cảm ơn anyway! – Sander

+0

@Sander: Bạn chỉ cần thêm trường hợp để 'đơn giản hóa' cho các hoạt động khác (ngoài ra, tôi xin lỗi vì tôi không hiểu rằng đây là bài tập về nhà — tôi sẽ không trực tiếp trả lời như vậy). –

+0

@Sander: Ngoài ra, cả hai kế thừa từ một trường hợp lớp và có một trường hợp lớp với một constructor trống là hình thức xấu. 'đặc điểm Prop; đối tượng trường hợp Đúng mở rộng Prop' là tốt hơn. –

9

Khá rõ ràng điều gì xảy ra và bạn phù hợp với mặc định case. Nếu đầu vào của bạn prop không khớp với bất kỳ trường hợp nào bạn đang gọi:

simplify(prop) 

với cùng một đối số. Vì trước đây nó đã gây ra cuộc gọi đệ quy đến simplify() và bạn đang gọi hàm của mình với cùng một đầu vào, nó sẽ nhập lại simplify(). Vì vậy, đây không phải là một vòng lặp vô hạn mà không bao giờ chấm dứt cuộc gọi đệ quy:

...simplify(simplify(simplify(simplify(simplify(simplify(simplify(prop))))))) 

Tuy nhiên việc sửa chữa (dựa trên mã của bạn) rất đơn giản:

if (simplify(prop) == prop) prop 
    else prop 

chỉ cần thay thế nó với ...

case _ => prop 

Cả hai chi nhánh đều trả về cùng một giá trị. Điều này thực sự đúng nếu bạn nghĩ về một thời gian. Bạn có một bộ tối ưu hóa. Nếu không ai trong số họ phù hợp với các biểu thức của bạn, điều đó có nghĩa là nó không còn có thể được đơn giản hóa nữa. Do đó bạn đang trả lại nó như là.

BTW có vẻ như bạn đang thực hiện đơn giản hóa biểu thức boolean bằng cách sử dụng các kiểu chữ. Bạn có thể quan tâm đến tôi article nơi tôi làm như vậy nhưng với các biểu thức số học.

+0

Cám ơn câu trả lời của bạn. Tôi đã cố gắng làm như vậy. (Xin lỗi, nhấn enter, và đăng mà không muốn). Nhưng trong một số trường hợp, kết quả đơn giản hóa trong một chuỗi có chứa một Not (Not (a)) mới chẳng hạn, do đó, việc chạy lại đơn giản hóa sẽ loại bỏ chúng. Nhưng, tôi không thể làm cho nó chạy nó một lần nữa khi chúng dường như là một kết hợp mới trên bất kỳ trường hợp nào trước đây ..: \ – Sander

+2

@Sander: bạn có thể cho chúng ta thấy đầu vào không đơn giản hóa 'Không (Không phải)) '? Điều này có thể được sửa bằng cách gọi 'simplify()' theo các từ riêng biệt như, e.g: để đơn giản hóa 'Và (Không (Không (a)), b)' bạn phải trả về 'Và (đơn giản hóa (Không (Không (a)), đơn giản hóa (b))' (mẫu đơn giản hóa là: 'Và (a , b) => Và (đơn giản hóa (a), đơn giản hóa (b)) ' –

+0

@Thomasz' Không (Và (Không (a), Không (b))) 'Điều này trước tiên sẽ đơn giản hóa thành' Hoặc (Không (Không phải) (a)), Không (Không (b))) 'như xa như tôi có thể thấy. Mã nên chạy lại để loại bỏ mới được tạo ra Không (Không (a)) và Không (Không (b)) – Sander

2

Có, trường hợp mặc định đang gây ra vòng lặp. if (simplify(prop) == prop) prop là dòng có vấn đề. Bạn không cần phải thử nghiệm nếu nó có thể được đơn giản hóa hơn nữa bởi vì khi bạn đang ở trong trường hợp mặc định tất cả các đơn giản hóa có thể được cố gắng.

Các vấn đề liên quan