2016-07-20 4 views
5

나는 프롤로그를 배우기 시작하고 정수가 주어진 프로그램을 원한다. PABP = A² + B²과 같은 정수를 준다. 이 식을 만족하고 AB의 값이 아닌 경우, 예를 들어 false 두 정수 제곱의 합으로 (정수) 숫자를 얻기위한 프롤로그 프로그램은 왜 작동하지 않습니까?

를 반환해야 P = 5 경우가 A = 1 B = 2 및 (또는 A = 2B = 1) 1² + 2² = 5 있으므로 제공한다.

나는이 작동합니다 생각 :

giveSum(P, A, B) :- integer(A), integer(B), integer(P), P is A*A + B*B. 

를 쿼리 :

giveSum(5, A, B). 

을하지만, 그렇지 않습니다. 어떻게해야합니까? 나는 프롤로그에게 매우 익숙하므로 아직도 많은 실수를하고있다.

미리 감사드립니다.

답변

6

integer/1은 비 단조 술어입니다. 아니요이 경우에 적용 할 추측을 허용하는 관계입니다. 이 예시하려면

 
?- integer(I). 
false. 

없음 정수 예, 존재하지 않는다? 놀랍게도 색상은 놀랍지 만입니다.

이러한 비 관계형 구조 대신, Prolog 시스템의 CLP (FD) 제약을 사용하여 정수를 추론하십시오. 예를 들어

:

 
?- 5 #= A*A + B*B. 
A in -2..-1\/1..2, 
A^2#=_G1025, 
_G1025 in 1..4, 
_G1025+_G1052#=5, 
_G1052 in 1..4, 
B^2#=_G406, 
B in -2..-1\/1..2 

그리고 콘크리트 솔루션 :

 
?- 5 #= A*A + B*B, label([A,B]). 
A = -2, 
B = -1 ; 
A = -2, 
B = 1 ; 
A = -1, 
B = -2 ; 
etc. 

CLP (FD) 제약은 예상대로 사용할 수 있습니다 완전히 순수한 관계입니다. 자세한 내용은 을 참조하십시오.

다른 것들은 내가주의 : 대신 ofMixingTheCasesToMakePredicatesHardToRead

  • use_underscores_for_readability_as_is_the_convention_in_prolog합니다.
  • 선언적 이름을 사용하십시오. 필수를 피하십시오. 예를 들어 give_sum으로 전화하는 이유는 무엇입니까? 에 이미이 있으면이 술어도 완벽합니다. 예를 들어, sum_of_squares/3은 어떨까요?
+0

답변 해 주셔서 감사합니다. 몇 가지 질문이 있습니다. 당신이 대답 할 수 있다면 그것은 최고 일 것입니다. '단조롭지 않은 술어'란 무엇을 의미합니까?/1 또는/3은 무엇을 의미하며 label() 함수는 무엇을합니까? 인터넷에서 나는 "Vars의 각 변수에 값을 지정합니다. 라벨링이란 체계적으로 유한 도메인 변수 Vars에 대한 값을 체계적으로 시도한 후에 모두 접지 될 때까지는 의미합니다." 함수 레이블()에 대한,하지만 난 정말 그것을 이해하지 않습니다. 나쁜 습관을 고백 해 주셔서 감사 드리며, 이름을 변경했으며 미래에 밑줄과 선언적 이름을 사용합니다. – Kevin

+1

별도의 질문을하십시오. 그들은 모두 스스로 논의 할 가치가 있습니다 : 1) 단조 로움의 정의와 2) "라벨링"은 무엇입니까? 여러분의 질문 중 단 하나만 주석에 대답 할만큼 간단합니다 :'f/3'은 ** 술어 지시자 **이며,'f'라는 술어를 3 * 인수 *로 표시합니다. 우리는 ** 술어 **에 대해 항상 이야기하지만, ** 술어 **는 * 함수 *보다 일반적입니다. 이름을 위해 중대하다! 술어의 ** 일반성 **에 대한 정의를하는 좋은 선언적 이름을 찾아 사용하는 것은 Prolog에서 프로그래밍 할 때 매우 중요한면이며 아마도 더 어려운 것 중 하나 일 것입니다. – mat

1

효율성을 위해 Prolog 구현 자들은 수년 전에 많은 것을 선택했습니다. 자, Prolog가 CLP (FD)처럼 고급 정수 연산을 구현할 가능성이 있습니다. 이 경우 매트의 대답은 완벽합니다. 그러나 일부 Prolog (ISO Prolog 순응 프로세서)는 누락 된 레이블/1 및 (# =)/2에 대해 불만을 제기 할 수 있습니다.따라서, 기존의 프롤로그 솔루션 :이 기술이 생성 라는 테스트된다

giveSum(P, A, B) :- 
    (integer(P) -> between(1,P,A), between(1,P,B) ; integer(A),integer(B)), 
    P is A*A + B*B. 

3/사이를 그것이 ISO의 내장 아니지만,보다 오히려 쉽게 (# =)/2 및 레이블/1 쓰기 :)

어쨌든 매트의 조언에 따라 '필수'이름 지정을 피하십시오. 관계에 대한 설명이 더 나은 경우가 많습니다. Prolog는 관계형 언어이기 때문에 더 좋습니다.

+2

나는 보통 downvoting을 삼가고 있지만 ... – repeat