2016-09-26 4 views
1

제목 종류는 모두입니다. 두 다항식의 GCD를 계산하려고합니다. 이것이 Prolog에서 수행 될 수있는 방법이 있습니까? 그렇다면 좋은 출발점은 무엇입니까? 특히, 프롤로그를 사용하여 다항식 나누기를 구현하는 방법에 문제가 있습니다.프롤로그를 사용하여 다항식의 GCD를 계산하십시오

편집 예를 들어, 입력 및 출력을 포함합니다 :

예 입력 :

?- GCD(x^2 + 7x + 6, x2 − 5x − 6, X). 

예 출력 : 오프 기회에

X = x + 1. 

솔루션

이 다른 사람 이 작업을 수행해야합니다. 여기에 내 fi가 있습니다. 솔루션 :

tail([_|Tail], Tail). 
head([Head | _], Head). 

norm(Old, N, New) :- 
    length(Tail, N), 
    append(New, Tail, Old). 
norm(Old, N, []) :- 
    length(Old, L), 
    N > L. 

mult_GCD(List, GCD) :- length(List, L), 
    L > 2, tail(List, Tail), 
    mult_GCD(Tail, GCD). 
mult_GCD([H | T], GCD) :- 
    length(T, L), 
    L == 1, head(T, N), 
    gcd(H, N, GCD). 

lead(List, List) :- 
    length(List, L), 
    L == 1. 
lead([0 | Tail], Out) :- 
    !, lead(Tail, Out). 
lead([Head | Tail], [Head | Tail]) :- Head =\= 0. 

poly_deg([], 0). 
poly_deg(F, D) :- 
    lead(F, O), 
    length(O, N), 
    D is N - 1. 

poly_red([0], [0]). 
poly_red(Poly, Out) :- 
    mult_GCD(Poly, GCD), 
    scal_div(Poly, GCD, Out). 

poly_sub(Poly,[],Poly) :- Poly = [_|_]. 
poly_sub([],Poly,Poly). 
poly_sub([P1_head|P1_rest], [P2_head|P2_rest], [PSub_head|PSub_rest]) :- 
    PSub_head is P1_head-P2_head, 
    poly_sub(P1_rest, P2_rest, PSub_rest). 

scal_prod([],_Sc,[]). 
scal_prod([Poly_head|Poly_rest], Sc, [Prod_head|Prod_rest]) :- 
    Prod_head is Poly_head*Sc, 
    scal_prod(Poly_rest, Sc, Prod_rest). 

scal_div([],_,[]). 
scal_div([Poly_head|Poly_rest], Sc, [Prod_head|Prod_rest]) :- 
    Prod_head is Poly_head/Sc, 
    scal_div(Poly_rest, Sc, Prod_rest). 

poly_div(Num, Den, OutBuild, Out) :- 
    poly_deg(Num, X), 
    poly_deg(Den, Y), 
    X < Y, 
    Out = OutBuild. 
poly_div(INum, IDen, OutBuild, Out) :- 
    lead(INum, [NumHead | NumTail]), lead(IDen, [DenHead | DenTail]), 
    Q is NumHead/DenHead, 
    append(OutBuild, [Q], Out1), 
    append([DenHead], DenTail, DenNorm), append([NumHead], NumTail, Num), 
    scal_prod(DenNorm, Q, DenXQ), 
    poly_sub(Num, DenXQ, N), 
    poly_div(N, IDen, Out1, Out). 

poly_mod(Num, Den, Out) :- 
    poly_deg(Num, X), poly_deg(Den, Y), 
    X < Y, 
    lead(Num, Out1), 
    poly_red(Out1, Out2), 
    lead(Out2, Out). 
poly_mod(INum, IDen, Out) :- 
    lead(INum, [NumHead | NumTail]), lead(IDen, [DenHead | DenTail]), 
    Q is NumHead/DenHead, 
    append([DenHead], DenTail, DenNorm), append([NumHead], NumTail, Num), 
    scal_prod(DenNorm, Q, DenXQ), 
    poly_sub(Num, DenXQ, N), 
    poly_mod(N, IDen, Out). 

poly_gcd(X, Y, X):- poly_deg(Y, O), O == 0, !. 
poly_gcd(Y, X, X):- poly_deg(Y, O), O == 0, !. 
poly_gcd(X, Y, D):- poly_deg(X, Xd), poly_deg(Y, Yd), Xd > Yd, !, poly_mod(X, Y, Z), poly_gcd(Y, Z, D). 
poly_gcd(X, Y, D):- poly_mod(Y, X, Z), poly_gcd(X, Z, D). 

gcd(X, Y, Z) :- 
    X < 0, X > Y, !, 
    X1 is X - Y, 
    gcd(-X, Y, Z). 
gcd(X, Y, Z) :- 
    Y < 0, Y >= X, !, 
    Y1 is Y - X, 
    gcd(X, -Y, Z). 
gcd(X, 0, X). 
gcd(0, Y, Y). 
gcd(X, Y, Z) :- 
    X > Y, Y > 0, 
    X1 is X - Y, 
    gcd(Y, X1, Z). 
gcd(X, Y, Z) :- 
    X =< Y, X > 0, 
    Y1 is Y - X, 
    gcd(X, Y1, Z). 
gcd(X, Y, Z) :- 
    X > Y, Y < 0, 
    X1 is X + Y, 
    gcd(Y, X1, Z). 
gcd(X, Y, Z) :- 
    X =< Y, X < 0, 
    Y1 is Y + X, 
    gcd(X, Y1, Z). 
+0

예, 모든 지수를 처리 할 수 ​​있어야합니다.전적으로 프롤로그에서 가능하지 않다는 것이 전적으로 가능합니다. 프롤로그를 실제로 잘 알고있는 사람이 저에게 말하기를 원했습니다. – bendl

+1

Prolog는 범용 프로그래밍 언어입니다. 당신이 컴퓨터로 할 수 있다면, 당신은 프롤로그와 함께 할 수 있어야합니다. 먼저, 문제가 이미 해결되지 않았는지 검색하고 찾으십시오. 그런 다음, 필요하지 않은 알고리즘을 찾아 Prolog에서 구현하십시오. 문제가 발생하면 스스로 해결할 수없고, 코드를 보여주고, 문제를 설명하고, 스스로 해결할 수없는 것이 무엇인지 설명하십시오. 나는이 질문을 투표 마감에 대해 투표하지는 않을 것이지만, 그 질문은 매우 잘 익는다. –

+0

제 문제는 제가 어떻게 시작 해야할지 모르겠다는 것입니다. 정수에 대한 GCD를 계산하는 버전이 있지만 다항식 분할로 어디서 시작해야할지 모르겠습니다. 이것은 처음이 아니며, 묻기 전에 검색하는 것을 알고 있습니다. 온라인에서이 주제에 관해서는 제가 말할 수있는 한 실제로 아무것도 없습니다. – bendl

답변

5

이 답변은 올바른 방향으로 밀어 넣기위한 것입니다.

먼저, x^2 + 7x + 6과 같은 표현식을 구문 분석해야한다는 것을 잊어 버리십시오. 이것은 아직 프롤로그에서 적절한 용어조차 아니다. 당신이 최고 수준에이를 작성하려고하면 오류가 발생합니다 :

?- Expr = x^2 + 7x + 6. 
ERROR: Syntax error: Operator expected 
ERROR: Expr = x^2 + 
ERROR: ** here ** 
ERROR: 7x + 6 . 

프롤로그 당신이 가지고있는 7x 처리하는 방법을 알고하지 않습니다. 식을 구문 분석하는 것은 자신의 문제, 그리고 당신이 이미 그것을 구문 분석과 같은 예를 들어 보이는 표현 입수했습니다 가정하는 경우 어쩌면 쉽게 :

[6, 7, 1] 

마찬가지로, x^2 − 5x − 6이된다을 :

[-6, -5, 1] 
지금

[] 

algorithm at the Wikipedia page를 살펴 :

및 나타내는 0 당신은 빈 목록을 사용합니다. 학위는 deg이고 주요 계수는 lc입니다. 위의 목록 표현으로, 당신은 사람들을 정의 할 수 있습니다

poly_lc(F, C) :- 
    last(F, C). 

poly_deg(F, D) :- 
    length(F, N), 
    D is N - 1. 

The leading coefficient is the last element of the list.

The degree is one less then the length of the list holding the coefficients.

당신은 또한 다항식으로 간단한 산술 연산을 수행 할 수 있어야합니다. Wikipedia page의 정의를 사용하면 예를 들어 [][1]을 추가하면 [1]을 얻게되며 [-2, 2][1, -3, 1]과 곱하면 [-2, 8, -8, 2]이됩니다. precursory search은 나에게 this question here on Stackoverflow을주었습니다. 이 정의 술어를 사용 : 당신이 시도하고 내가 위의 링크 된 위키 문서에 설명 된대로 다항식 부문을 구현하기 위해

?- poly_prod([-2,2], [1, -3, 1], P). 
P = [-2.0, 8.0, -8.0, 2] . 

?- poly_sum([], [1], S). 
S = [1]. 

여기부터, 그것은 수 있어야한다. 더 많은 문제가 발생하면 질문을 수정하거나 새 질문을해야합니다.

+0

글쎄, 지금은 바보 같아. 다른 언어로 구현하려고 했더라면 아마도 목록을 사용할 생각이었을 것입니다. 그러나 어쨌든 이것은 결코 저에게 발생하지 않았습니다. 이것은 정확히 내가 뭘 찾고 있었는지, 감사합니다! – bendl

+0

@bendl 나는이 실제로 당신이 행운을 –

+2

한 의견을 :) 도움 것을 매우 기쁘게 생각합니다 : 코드에서 poly_deg (F, D) : - 길이 (P, N), D는 N입니다 - 1. 것은이어야한다 poly_deg (F, D) : 길이 (F, N), D는 N-1입니다. 내가 잘못하지 않는 한. – bendl