SAGE: Automorphism group of finite abelian group? - linear-algebra
For a finite abelian group G, say,
G = AbelianGroup((4,4,5)),
I want Sage to return the automorphism group of G. Is this implemented?
You can get it partway easily.
G = AbelianGroup((4,4,5))
gap(G).AutomorphismGroup()
Group( [ Pcgs([ f1, f2, f3, f4, f5 ]) -> [ f1*f3*f4, f2*f4, f3*f4, f4, f5 ],
Pcgs([ f1, f2, f3, f4, f5 ]) -> [ f1*f3*f4, f2*f4, f3*f4, f4, f5 ],
Pcgs([ f1, f2, f3, f4, f5 ]) -> [ f1, f2, f1*f2*f3, f2*f4, f5 ],
Pcgs([ f1, f2, f3, f4, f5 ]) -> [ f1, f2, f2*f3*f4, f4, f5 ],
Pcgs([ f1, f2, f3, f4, f5 ]) -> [ f1, f2, f3, f4, f5^2 ] ] )
Unfortunately this particular group type doesn't seem to have an obvious way to get it back into Sage. This answer luckily gives it: otherwise it's buried as a parameter in the official permutation group doc. Here you go, though the generators may not be what you were looking for:
G = AbelianGroup((4,4,5))
H = gap(G).AutomorphismGroup()
PermutationGroup(gap_group = H.AsPermGroup())
Permutation Group with generators [(1,21)(2,22)(3,24)(4,23)(5,17)(6,18)(7,20)(8,19)(9,13)(10,14)(11,16)(12,15)(25,45)(26,46)(27,48)(28,47)(29,41)(30,42)(31,44)(32,43)(33,37)(34,38)(35,40)(36,39)(49,81)(50,82)(51,84)(52,83)(53,77)(54,78)(55,80)(56,79)(57,73)(58,74)(59,76)(60,75)(61,93)(62,94)(63,96)(64,95)(65,89)(66,90)(67,92)(68,91)(69,85)(70,86)(71,88)(72,87)(97,117)(98,118)(99,120)(100,119)(101,113)(102,114)(103,116)(104,115)(105,109)(106,110)(107,112)(108,111)(121,141)(122,142)(123,144)(124,143)(125,137)(126,138)(127,140)(128,139)(129,133)(130,134)(131,136)(132,135)(145,177)(146,178)(147,180)(148,179)(149,173)(150,174)(151,176)(152,175)(153,169)(154,170)(155,172)(156,171)(157,189)(158,190)(159,192)(160,191)(161,185)(162,186)(163,188)(164,187)(165,181)(166,182)(167,184)(168,183)(193,213)(194,214)(195,216)(196,215)(197,209)(198,210)(199,212)(200,211)(201,205)(202,206)(203,208)(204,207)(217,237)(218,238)(219,240)(220,239)(221,233)(222,234)(223,236)(224,235)(225,229)(226,230)(227,232)(228,231)(241,273)(242,274)(243,276)(244,275)(245,269)(246,270)(247,272)(248,271)(249,265)(250,266)(251,268)(252,267)(253,285)(254,286)(255,288)(256,287)(257,281)(258,282)(259,284)(260,283)(261,277)(262,278)(263,280)(264,279)(289,309)(290,310)(291,312)(292,311)(293,305)(294,306)(295,308)(296,307)(297,301)(298,302)(299,304)(300,303)(313,333)(314,334)(315,336)(316,335)(317,329)(318,330)(319,332)(320,331)(321,325)(322,326)(323,328)(324,327)(337,369)(338,370)(339,372)(340,371)(341,365)(342,366)(343,368)(344,367)(345,361)(346,362)(347,364)(348,363)(349,381)(350,382)(351,384)(352,383)(353,377)(354,378)(355,380)(356,379)(357,373)(358,374)(359,376)(360,375), (1,61)(2,62)(3,63)(4,64)(5,67)(6,68)(7,65)(8,66)(9,70)(10,69)(11,72)(12,71)(13,49)(14,50)(15,51)(16,52)(17,55)(18,56)(19,53)(20,54)(21,58)(22,57)(23,60)(24,59)(25,85)(26,86)(27,87)(28,88)(29,91)(30,92)(31,89)(32,90)(33,94)(34,93)(35,96)(36,95)(37,73)(38,74)(39,75)(40,76)(41,79)(42,80)(43,77)(44,78)(45,82)(46,81)(47,84)(48,83)(97,157)(98,158)(99,159)(100,160)(101,163)(102,164)(103,161)(104,162)(105,166)(106,165)(107,168)(108,167)(109,145)(110,146)(111,147)(112,148)(113,151)(114,152)(115,149)(116,150)(117,154)(118,153)(119,156)(120,155)(121,181)(122,182)(123,183)(124,184)(125,187)(126,188)(127,185)(128,186)(129,190)(130,189)(131,192)(132,191)(133,169)(134,170)(135,171)(136,172)(137,175)(138,176)(139,173)(140,174)(141,178)(142,177)(143,180)(144,179)(193,253)(194,254)(195,255)(196,256)(197,259)(198,260)(199,257)(200,258)(201,262)(202,261)(203,264)(204,263)(205,241)(206,242)(207,243)(208,244)(209,247)(210,248)(211,245)(212,246)(213,250)(214,249)(215,252)(216,251)(217,277)(218,278)(219,279)(220,280)(221,283)(222,284)(223,281)(224,282)(225,286)(226,285)(227,288)(228,287)(229,265)(230,266)(231,267)(232,268)(233,271)(234,272)(235,269)(236,270)(237,274)(238,273)(239,276)(240,275)(289,349)(290,350)(291,351)(292,352)(293,355)(294,356)(295,353)(296,354)(297,358)(298,357)(299,360)(300,359)(301,337)(302,338)(303,339)(304,340)(305,343)(306,344)(307,341)(308,342)(309,346)(310,345)(311,348)(312,347)(313,373)(314,374)(315,375)(316,376)(317,379)(318,380)(319,377)(320,378)(321,382)(322,381)(323,384)(324,383)(325,361)(326,362)(327,363)(328,364)(329,367)(330,368)(331,365)(332,366)(333,370)(334,369)(335,372)(336,371), (1,85,37,49)(2,86,38,50)(3,88,39,52)(4,87,40,51)(5,96,44,58)(6,95,43,57)(7,93,42,59)(8,94,41,60)(9,90,47,55)(10,89,48,56)(11,91,45,54)(12,92,46,53)(13,73,25,61)(14,74,26,62)(15,76,27,64)(16,75,28,63)(17,84,32,70)(18,83,31,69)(19,81,30,71)(20,82,29,72)(21,78,35,67)(22,77,36,68)(23,79,33,66)(24,80,34,65)(97,181,133,145)(98,182,134,146)(99,184,135,148)(100,183,136,147)(101,192,140,154)(102,191,139,153)(103,189,138,155)(104,190,137,156)(105,186,143,151)(106,185,144,152)(107,187,141,150)(108,188,142,149)(109,169,121,157)(110,170,122,158)(111,172,123,160)(112,171,124,159)(113,180,128,166)(114,179,127,165)(115,177,126,167)(116,178,125,168)(117,174,131,163)(118,173,132,164)(119,175,129,162)(120,176,130,161)(193,277,229,241)(194,278,230,242)(195,280,231,244)(196,279,232,243)(197,288,236,250)(198,287,235,249)(199,285,234,251)(200,286,233,252)(201,282,239,247)(202,281,240,248)(203,283,237,246)(204,284,238,245)(205,265,217,253)(206,266,218,254)(207,268,219,256)(208,267,220,255)(209,276,224,262)(210,275,223,261)(211,273,222,263)(212,274,221,264)(213,270,227,259)(214,269,228,260)(215,271,225,258)(216,272,226,257)(289,373,325,337)(290,374,326,338)(291,376,327,340)(292,375,328,339)(293,384,332,346)(294,383,331,345)(295,381,330,347)(296,382,329,348)(297,378,335,343)(298,377,336,344)(299,379,333,342)(300,380,334,341)(301,361,313,349)(302,362,314,350)(303,364,315,352)(304,363,316,351)(305,372,320,358)(306,371,319,357)(307,369,318,359)(308,370,317,360)(309,366,323,355)(310,365,324,356)(311,367,321,354)(312,368,322,353), (1,289,97,193)(2,290,98,194)(3,291,99,195)(4,292,100,196)(5,293,101,197)(6,294,102,198)(7,295,103,199)(8,296,104,200)(9,297,105,201)(10,298,106,202)(11,299,107,203)(12,300,108,204)(13,301,109,205)(14,302,110,206)(15,303,111,207)(16,304,112,208)(17,305,113,209)(18,306,114,210)(19,307,115,211)(20,308,116,212)(21,309,117,213)(22,310,118,214)(23,311,119,215)(24,312,120,216)(25,313,121,217)(26,314,122,218)(27,315,123,219)(28,316,124,220)(29,317,125,221)(30,318,126,222)(31,319,127,223)(32,320,128,224)(33,321,129,225)(34,322,130,226)(35,323,131,227)(36,324,132,228)(37,325,133,229)(38,326,134,230)(39,327,135,231)(40,328,136,232)(41,329,137,233)(42,330,138,234)(43,331,139,235)(44,332,140,236)(45,333,141,237)(46,334,142,238)(47,335,143,239)(48,336,144,240)(49,337,145,241)(50,338,146,242)(51,339,147,243)(52,340,148,244)(53,341,149,245)(54,342,150,246)(55,343,151,247)(56,344,152,248)(57,345,153,249)(58,346,154,250)(59,347,155,251)(60,348,156,252)(61,349,157,253)(62,350,158,254)(63,351,159,255)(64,352,160,256)(65,353,161,257)(66,354,162,258)(67,355,163,259)(68,356,164,260)(69,357,165,261)(70,358,166,262)(71,359,167,263)(72,360,168,264)(73,361,169,265)(74,362,170,266)(75,363,171,267)(76,364,172,268)(77,365,173,269)(78,366,174,270)(79,367,175,271)(80,368,176,272)(81,369,177,273)(82,370,178,274)(83,371,179,275)(84,372,180,276)(85,373,181,277)(86,374,182,278)(87,375,183,279)(88,376,184,280)(89,377,185,281)(90,378,186,282)(91,379,187,283)(92,380,188,284)(93,381,189,285)(94,382,190,286)(95,383,191,287)(96,384,192,288)]
Related
Symply.py for getting coefficients for ALL combination of the variables of a multivariable polynomial
How to get coefficients for ALL combinations of the variables of a multivariable polynomial using sympy.jl or another Julia package for symbolic computation? Here is an example from MATLAB, syms a b y [cxy, txy] = coeffs(ax^2 + by, [y x], ‘All’) cxy = [ 0, 0, b] [ a, 0, 0] txy = [ x^2y, xy, y] [ x^2, x, 1] My goal is to get [ x^2y, xy, y] [ x^2, x, 1] instead of [x^2, y] I asked the same question at https://github.com/JuliaPy/SymPy.jl/issues/482 and https://discourse.julialang.org/t/symply-jl-for-getting-coefficients-for-all-combination-of-the-variables-of-a-multivariable-polynomial/89091 but I think I should ask if this can be done using Sympy.py. Using Julia, I tried the following, julia> #syms x, y, a, b julia> ff = sympy.Poly(ax^2 + by, (x,y)) Poly(ax**2 + by, x, y, domain='ZZ[a,b]') julia> [prod(ff.gens.^i) for i in ff.monoms()] 2-element Vector{Sym}: x^2 y
This is a longer form rewrite of the one-liner in the comment. It uses Pipe.jl to write expressions 'functionally', so familiarity with pipe operator (|>) and Pipe.jl will help. using SymPy using Pipe #syms x, y, a, b ff = sympy.Poly(a*x^2 + b*y, (x,y)) max_degrees = #pipe ff.monoms() .|> collect |> hcat(_...) |> reduce(max, _, dims=2) |> vec degree_iter = #pipe max_degrees .|> UnitRange(0, _) |> tuple(_...) |> CartesianIndices result = [prod(ff.gens.^Tuple(I)) for I in degree_iter] |> reverse |> eachcol |> collect or using more of the python methods: [prod(ff.gens.^I) for I in Iterators.product((0:d for d in ff.degree.(ff.gens))...)] |> reverse |> eachcol |> collect Both give the desired result: 2-element Vector{...}: [x^2*y, x*y, y] [x^2, x, 1] UPDATE: In case there are more than 2 generators, the result needs to be a Array with higher dimension. The last bits of matrix transposes is immaterial and the expressions become: Method 1: max_degrees = #pipe ff.monoms() .|> collect |> hcat(_...) |> reduce(max, _, dims=2) |> vec degree_iter = #pipe max_degrees .|> UnitRange(0, _) |> tuple(_...) |> CartesianIndices result = [prod(ff.gens.^Tuple(I)) for I in degree_iter] Method 2: result = [prod(ff.gens.^Tuple(I)) for I in degree_iter]
Thanks a lot #Dan Getz. Your solution works for the TOY example from MATLAB. My real case is more complicated, which has more variables and polynominals. I tried your method for 3 variables, using SymPy #syms x, y, z, a, b ff = sympy.Poly(a*x^2 + b*y + z^2 + x*y + y*z, (x, y, z)) [prod(ff.gens.^Tuple(I)) for I in CartesianIndices(tuple(UnitRange.(0,vec(reduce(max, hcat(collect.(ff.monoms())...), dims=1)))...))] I got the following error, ERROR: LoadError: DimensionMismatch: arrays could not be broadcast to a common size; got a dimension with lengths 3 and 5 Stacktrace: How to generate your method to any number of variables with different degrees, e.g., x^3 + y^3 + z^3 + xyz + xy^2z?
You can find the degree of each of the two variables of interest and then use them to create the matrix of generators; you can use them to get the coefficients of interest. I am not sure what you expect if the equation were like a*x**2 + b*y + c... >>> from sympy import * >>> from sympy.abc import a, b, x, y >>> eq = a*x**2 + b*y >>> deg = lambda x: Poly(eq, x).degree() # helper to give degree in "x" >>> v = (Matrix([x**i for i in range(deg(x),-1,-1)] ... )*Matrix([y**i for i in range(deg(y),-1,-1)]).T).T; v Matrix([[x**2*y, x*y, y], [x**2, x, 1]]) >>> Matrix(*v.shape, [eq.coeff(i) if i.free_symbols else eq.as_coeff_Add()[0] ... for i in v]) Matrix([[0, 0, b], [a, 0, 0]]) From #jverzani (thanks) using SymPy; #syms a b x y; eq = a*x^2 + b*y; deg = x -> sympy.Poly(eq, x).degree(); xs, ys = [x^i for i ∈ range(deg(x):-1:0], [y^i for i ∈ deg(y):-1:0]; v = permutedims(xs .* permutedims(ys)); M = [x^2*y x*y y; x^2 x 1]; [length(free_symbols(i)) > 0 ? eq.coeff(i) : eq.as_coeff_add()[1] for i ∈ v]; [0 0 b; a 0 0]
Tail-Recursion in Prolog
I'm new to Prolog and I'm having trouble with a practise question on tail recursion. Question: Define a relationship, where the first argument is a list of objects, the second is a number, and the third is the total price of the objects in the list plus the second argument; and also ensure that the call to the recursion is the last clause of your rule. Object list: cost( table, 1000). cost( chair, 100). cost( lamp, 80). cost( oven, 800). e.g. totalTail( [chair,table], 100, X) ==> X = 1200. What rules should I be defining?
You can start by defining what you already know it ought to be: totalTail( [chair, table], 100, X) :- X = 1200. or, equivalently, totalTail( [Chair, Table], 100, X) :- Chair = chair, cost( Chair, 100), Table = table, cost( Table, 1000), X is 100 + 100 + 1000. or, equivalently, totalTail( [Chair, Table], InitialCost, X) :- InitialCost = 100, Chair = chair, cost( Chair, ChairCost), ChairCost = 100, Table = table, cost( Table, TableCost), TableCost = 1000, X is InitialCost + ChairCost + TableCost. or, equivalently, totalTail( [Chair, Table], InitialCost, X) :- cost( Chair, ChairCost), cost( Table, TableCost), X is InitialCost + ChairCost + TableCost. (Boom!) Or, equivalently, totalTail( [A, B], InitialCost, X) :- cost( A, ACost), cost( B, BCost), X is InitialCost + ACost + BCost. or even totalTail( [A, B, C], Z, X) :- cost( A, ACost), cost( B, BCost), cost( C, CCost), X is Z + ACost + BCost + CCost. which is the same as totalTail( [A, B, C], Z, X) :- cost( A, ACost), totalTail( [B, C], Z, X2) X is Z + ACost + X2. Right? Wrong! Can you spot the error? Did we count something twice, there? So fixing it, we get totalTail( [A, B, C], Z, X) :- cost( A, ACost), Z2 is .... + .... , totalTail( [B, C], Z2, X). Right. But isn't it the same as totalTail( [A | BC], Z, X) :- BC = [B, C], cost( A, ACost), Z2 is .... + .... , totalTail( BC, Z2, X). But, again, why limit yourself to that very specific option, BC = [B, C]? Do we really have to specify it? And what if the first argument does not match the [A | BC] list at all? What kind of a list would that be? And what should X be in that case?
Decompression of a list in prolog
I need to decompress a list in prolog , like in the example below : decode([[a,1],[b,2],[c,1],[d,3]],L). L = [a, b, b, c, d, d, d] ; I made this code : divide(L,X,Y):-length(X,1),append(X,Y,L). divide2(L,X,Y):-divide(L,[X|_],[Y|_]). makelist(_,N,[]):- N =< 0 . makelist(X,Y,[X|Result]):-Y1 is Y-1,makelist(X,Y1,Result). makelist2(L,L2):-divide2(L,X,Y),makelist(X,Y,L2). decode([],[]). decode([H|T],L):-makelist2(H,H2),append(H2,L,L2),decode(T,L2). and when i call makelist2([a,3],L2). L2 = [a,a,a]. but when i call decode([[a,3],[b,1],[c,4]],L) runs continuously. What am i doing wrong ?
Another variation of the theme, using a slightly modified version of Boris' repeat/3 predicate: % True when L is a list with N repeats of X repeat([X, N], L) :- length(L, N), maplist(=(X), L). decode(Encoded, Decoded) :- maplist(repeat, Encoded, Expanded), flatten(Expanded, Decoded). If Encode = [[a,1],[b,2],[c,1],[d,3]], then in the above decode/2, the maplist/3 call will yield Expanded = [[a],[b,b],[c],[d,d,d]], and then the flatten/2 call results in Decoded = [a,b,b,c,d,d,d]. In SWI Prolog, instead of flatten/2, you can use append/2 since you only need a "flattening" at one level. EDIT: Adding a "bidirectional" version, using a little CLPFD: rle([], []). rle([X], [[1,X]]). rle([X,Y|T], [[1,X]|R]) :- X \== Y, % use dif(X, Y) here, if available rle([Y|T], R). rle([X,X|T], [[N,X]|R]) :- N #= N1 + 1, rle([X|T], [[N1,X]|R]). This will yield: | ?- rle([a,a,a,b,b], L). L = [[3,a],[2,b]] ? ; (1 ms) no | ?- rle(L, [[3,a],[2,b]]). L = [a,a,a,b,b] ? ; no | ?- rle([a,a,a,Y,Y,Z], [X, [N,b],[M,c]]). M = 1 N = 2 X = [3,a] Y = b Z = c ? a no | ?- rle([A,B,C], D). D = [[1,A],[1,B],[1,C]] ? ; C = B D = [[1,A],[2,B]] ? ; B = A D = [[2,A],[1,C]] ? ; B = A C = A D = [[3,A]] ? ; (2 ms) no | ?- rle(A, [B,C]). A = [D,E] B = [1,D] C = [1,E] ? ; A = [D,E,E] B = [1,D] C = [2,E] ? ; A = [D,E,E,E] B = [1,D] C = [3,E] ? ; ... | ?- rle(A, B). A = [] B = [] ? ; A = [C] B = [[1,C]] ? ; A = [C,D] B = [[1,C],[1,D]] ? ; ... As #mat suggests in his comment, in Prolog implementations that have dif/2, then dif(X,Y) is preferable to X \== Y above.
The problem is in the order of your append and decode in the last clause of decode. Try tracing it, or even better, trace it "by hand" to see what happens. Another approach: see this answer. So, with repeat/3 defined as: % True when L is a list with N repeats of X repeat(X, N, L) :- length(L, N), maplist(=(X), L). You can write your decode/2 as: decode([], []). decode([[X,N]|XNs], Decoded) :- decode(XNs, Decoded_rest), repeat(X, N, L), append(L, Decoded_rest, Decoded). But this is a slightly roundabout way to do it. You could define a difference-list version of repeat/3, called say repeat/4: repeat(X, N, Reps, Reps_back) :- ( succ(N0, N) -> Reps = [X|Reps0], repeat(X, N0, Reps0, Reps_back) ; Reps = Reps_back ). And then you can use a difference-list version of decode/2, decode_1/3 decode(Encoded, Decoded) :- decode_1(Encoded, Decoded, []). decode_1([], Decoded, Decoded). decode_1([[X,N]|XNs], Decoded, Decoded_back) :- repeat(X, N, Decoded, Decoded_rest), decode_1(XNs, Decoded_rest, Decoded_back). ?- decode([[a,1],[b,2],[c,1],[d,3]],L). L = [a, b, b, c, d, d, d]. ?- decode([[a,3],[b,1],[c,0],[d,3]],L). L = [a, a, a, b, d, d, d]. ?- decode([[a,3]],L). L = [a, a, a]. ?- decode([],L). L = [].
You can deal with both direction with this code : :- use_module(library(lambda)). % code from Pascal Bourguignon packRuns([],[]). packRuns([X],[[X]]). packRuns([X|Rest],[XRun|Packed]):- run(X,Rest,XRun,RRest), packRuns(RRest,Packed). run(Var,[],[Var],[]). run(Var,[Var|LRest],[Var|VRest],RRest):- run(Var,LRest,VRest,RRest). run(Var,[Other|RRest],[Var],[Other|RRest]):- dif(Var,Other). %end code pack_1(In, Out) :- maplist(\X^Y^(X = [V|_], Y = [V, N], length(X, N), maplist(=(V), X)), In, Out). decode(In, Out) :- when((ground(In); ground(Out1)),pack_1(Out1, In)), packRuns(Out, Out1). Output : ?- decode([[a,1],[b,2],[c,1],[d,3]],L). L = [a, b, b, c, d, d, d] . ?- decode(L, [a,b,b,c,d,d,d]). L = [[a, 1], [b, 2], [c, 1], [d, 3]] .
a compact way: decode(L,D) :- foldl(expand,L,[],D). expand([S,N],L,E) :- findall(S,between(1,N,_),T), append(L,T,E). findall/3 it's the 'old fashioned' Prolog list comprehension facility
decode is a poor name for your predicate: properly done, you predicate should be bi-directional — if you say decode( [[a,1],[b,2],[c,3]] , L ) You should get L = [a,b,b,c,c,c]. And if you say decode( L , [a,b,b,c,c,c] ) . You should get L = [[a,1],[b,2],[c,3]]. So I'd use a different name, something like run_length_encoding/2. I might also not use a list to represent individual run lengths as [a,1] is this prolog term: .(a,.(1,[]). Just use a simple term with arity 2 — myself, I like using :/2 since it's defined as an infix operator, so you can simply say a:1. Try this on for size: run_length_encoding( [] , [] ) . % the run-length encoding of the empty list is the empty list. run_length_encoding( [X|Xs] , [R|Rs] ) :- % the run-length encoding of a non-empty list is computed by rle( Xs , X:1 , T , R ) , % - run-length encoding the prefix of the list run_length_encoding( T , Rs ) % - and recursively run-length encoding the remainder . % Easy! rle( [] , C:N , [] , C:N ) . % - the run is complete when the list is exhausted. rle( [X|Xs] , C:N , [X|Xs] , C:N ) :- % - the run is complete, X \= C % - when we encounter a break . % rle( [X|Xs] , X:N , T , R ) :- % - the run continues if we haven't seen a break, so.... N1 is N+1 , % - increment the run length, rle( Xs, X:N1, T, R ) % - and recurse down. . % Easy!
In direct answer to the original question of, What am I doing wrong?... When I ran the original code, any expected use case "ran indefinitely" without yielding a result. Reading through the main predicate: decode([],[]). This says that [] is the result of decoding []. Sounds right. decode([H|T],L) :- makelist2(H,H2), append(H2,L,L2), decode(T,L2). This says that L is the result of decoding [H|T] if H2 is an expansion of H (which is what makelist2 does... perhaps - we'll go over that below), and H2 appended to this result gives another list L2 which is the decoded form of the original tail T. That doesn't sound correct. If I decode [H|T], I should (1) expand H, (2) decode T giving L2, then (3) append H to L2 giving L. So the corrected second clause is: decode([H|T], L) :- makelist2(H, H2), decode(T, L2), append(H2, L2, L). Note the argument order of append/3 and that the call occurs after the decode of the tail. As Boris pointed out previously, the incorrect order of append and the recursive decode can cause the continuous running without any output as append with more uninstantiated arguments generates a large number of unneeded possibilities before decode can succeed. But now the result is: | ?- decode([[a,3]], L). L = [a,a,a] ? ; L = [a,a,a,a] ? ; ... If you try out our other predicates by hand in the Prolog interpreter, you'll find that makelist2/2 has an issue: It produces the correct result, but also a bunch of incorrect results. Let's have a look at makelist2/2. We can try this predicate by itself and see what happens: | ?- makelist2([a,3], L). L = [a,a,a] ? ; L = [a,a,a,a] ? ; ... There's an issue: makelist2/2 should only give the first solution, but it keeps going, giving incorrect solutions. Let's look closer at makelist/2: makelist2(L,L2) :- divide2(L,X,Y), makelist(X,Y,L2). It takes a list L of the form [A,N], divides it (via divide2/3) into X = A and Y = N, then calls an auxiliary, makelist(X, Y, L2). makelist(_,N,[]):- N =< 0 . makelist(X,Y,[X|Result]):-Y1 is Y-1,makelist(X,Y1,Result). makelist/3 is supposed to generate a list (the third argument) by replicating the first argument the number of times given in the second argument. The second, recursive clause appears to be OK, but has one important flaw: it will succeed even if the value of Y is less than or equal to 0. Therefore, even though a correct solution is found, it keeps succeeding on incorrect solutions because the base case allows the count to be =< 0: | ?- makelist(a,2,L). L = [a,a] ? ; L = [a,a,a] ? ; We can fix makelist/2 as follows: makelist(_,N,[]):- N =< 0 . makelist(X,Y,[X|Result]):- Y > 0, Y1 is Y-1, makelist(X,Y1,Result). Now the code will generate a correct result. We just needed to fix the second clause of decode/2, and the second clause of makelist/3. | ?- decode([[a,3],[b,4]], L). L = [a,a,a,b,b,b,b] yes The complete, original code with just these couple of corrections looks like this: divide(L, X, Y) :- length(X, 1), append(X, Y, L). divide2(L, X, Y) :- divide(L, [X|_], [Y|_]). makelist(_, N, []) :- N =< 0 . makelist(X, Y, [X|Result]) :- Y > 0, Y1 is Y-1, makelist(X,Y1,Result). makelist2(L, L2) :- divide2(L, X, Y), makelist(X, Y, L2). decode([], []). decode([H|T], L) :- makelist2(H,H2), decode(T,L2), append(H2,L2,L). Note some simple, direct improvements. The predicate, divide2(L, X, Y) takes a list L of two elements and yields each, individual element, X and Y. This predicate is unnecessary because, in Prolog, you can obtain these elements by simple unification: L = [X, Y]. You can try this right in the Prolog interpreter: | ?- L = [a,3], L = [X,Y]. L = [a,3] X = a Y = 3 yes We can then completely remove the divide/3 and divide2/3 predicates, and replace a call to divide2(L, X, Y) with L = [X,Y] and reduce makelist2/2 to: makelist2(L, L2) :- L = [X, Y], makelist(X, Y, L2). Or more simply (because we can do the unification right in the head of the clause): makelist2([X,Y], L2) :- makelist(X, Y, L2). You could just remove makelist2/2 and call makelist/2 directly from decode/2 by unifying H directly with its two elements, [X, N]. So the original code simplifies to: makelist(_, N, []) :- N =< 0 . makelist(X, Y, [X|Result]) :- Y > 0, Y1 is Y-1, makelist(X,Y1,Result). decode([], []). decode([[X,N]|T], L) :- makelist(X, N, H2), decode(T, L2), append(H2, L2, L). And makelist/3 can be performed a bit more clearly using one of the methods provided in the other answers (e.g., see Boris' repeat/3 predicate).
recursively unfold function with univ predicate
I want to replace for example a with 2 in this term f(a,b,g(a,h(a))). For this I first wanna unfold this term with the univ predicate =... So far I have: unfold(T1, T2) :- T1 =.. T1list, T2 = T1list. which is true when T2 is the list represantation of T1. But in this example I need a way to do this recursively because some arguments are functions as well! After substitution I need to do all the way back to get f(2,b,g(2,h(2))) as an example for the substitution I have replace(X,Y,[],[]). replace(X,Y,[X|T1],[Y|T2]):- replace(X,Y,T1,T2). replace(X,Y,[H|T1],[H|T2]):- not(X=H), replace(X,Y,T1,T2). EDIT: My current Solution: my problem is, it does not work for replace(a, 1, X, f(1,b,g(1,h(1)))). replace(_, _, [], []). replace(X, Y, L1, L2) :- not(is_list(L1)), not(is_list(L2)), unfold(L1, L1unfold), replace(X,Y, L1unfold, L2sub), refold(L2sub, L2), !. replace(X, Y, [X|T1], [Y|T2]) :- replace(X, Y, T1, T2), !. replace(X, Y, [H|T1], [H|T2]) :- \+ is_list(H), replace(X, Y, T1, T2), !. replace(X, Y, [H1|T1], [H2|T2]) :- replace(X, Y, H1, H2), replace(X, Y, T1, T2). unfold(T1, [H|T2]) :- T1 =.. [H|T1Expanded], maplist(unfold, T1Expanded, T2). refold([H|T2],T1):- maplist(refold,T2,R), T1 =.. [H|R].
You're surprisingly close. unfold(T1, [H|T2]) :- T1 =.. [H|T1Expanded], maplist(unfold, T1Expanded, T2).
(Beginner's) issue with redundant case statement in SML
I'm trying to write a function in SML to compute the partial sum of an alternating harmonic series, and for the life of me I can't figure out why the compiler says one of the cases is redundant. I haven't used case statements before(or local, for that matter), but the order of these cases seems right to me. local fun altHarmAux (x:int, y:real) = case x of 1 => 1.0 | evenP => altHarmAux(x-1, y - y/(real x)) | oddP => altHarmAux(x-1, y + y/(real x)) in fun altHarmonic (a:int) = altHarmAux(a, real a) end
Even if you have defined the two predicate functions somewhere, they can't be used in a case like that. whatever you write on the left hand of => will be bound to the value you are matching on, thus the two last matches in your case will match the same input, rendering the last one useless, as the first one will always be used You will have to apply your predicate function to the value directly, and then match on the result local fun altHarmAux (x, y) = case (x, evenP x) of (1, _) => 1.0 | (_ true) => altHarmAux(x-1, y - y/(real x)) | (_, false) => altHarmAux(x-1, y + y/(real x)) in fun altHarmonic a = altHarmAux(a, real a) end or perhaps simpler local fun altHarmAux (1, _) = 1.0 | altHarmAux (x, y) = altHarmAux (x-1, y + (if evenP x then ~y else y) / (real x)) in fun altHarmonic a = altHarmAux (a, real a) end or local fun altHarmAux (1, _) = 1.0 | altHarmAux (x, y) = if evenP x then altHarmAux (x-1, y - y/(real x)) else altHarmAux (x-1, y + y/(real x)) in fun altHarmonic a = altHarmAux (a, real a) end