Hello,
There are many easy examples of this when you use the Axiom interpreter.
Perhaps the following is related:
Trying to implement free products of monoids
FreeProductMonoid(M1:Monoid,M2:Monoid)
(see attachment, not very elegant, but I don't know how to avoid "mixed
lists" otherwise). I am stuck at the following problem:
There are two converters
coerce:M1 -> %
coerce:M2 -> %
but somehow always the first converter is called,
in the order where they are found in the source file,
leading to strange results:
(1) -> Z2:=CyclicGroup(2,'a)
(1) CyclicGroup(2,a)
Type: Domain
(2) -> Z3:=CyclicGroup(3,'b)
(2) CyclicGroup(3,b)
Type: Domain
(3) -> G:=FreeProductMonoid(Z2,Z3)
(3) FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
Type: Domain
(4) -> a1:=a::Z2
(4) a
Type: CyclicGroup(2,a)
(5) -> b1:=b::Z3
(5) b
Type: CyclicGroup(3,b)
(6) -> a2:=a1::G
(6) a
Type: FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
(7) -> b2:=b1::G
(7) a
Type: FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
(8) -> b2a:= (b1^2) ::G
2
(8) a
Type: FreeProductMonoid(CyclicGroup(2,a),CyclicGroup(3,b))
(9) -> b2a * 1::G
(9) 1
(10) -> b::Z2
>> System error:
wrong symbol
Especially (8) is pretty strange. (9) shows that indeed b made it
into M1 and is the identity element. (10) shows that coercion in
CyclicGroup filters out the wrong symbols as it should.
What am I missing? Somehow the interpreter is confused by two almost equal
signatures (both M1 and M2 are Monoids). Is this forbidden?
Renaming the converters to coerce1 and coerce2 makes it work.
regards
Franz
#include "axiom"
define FreeProductCategory(M1:Monoid, M2:Monoid):Category == with {
coerce:M1 -> %;
coerce:M2 -> %;
length:% -> Integer;
}
FreeProductMonoid(M1: Monoid,M2: Monoid):
Join(FreeProductCategory(M1,M2),Monoid) == add {
+++ FreeProductMonoid(M1,M2) ist the free product of the monoids M1 and
M2
+++ where the neutral elements are identified
+++ Representation by two lists of factors:
+++ factors1 = [a1,a2,a3,...,am] and factors2 = [b1,b2,b3,...,bm]
+++ corresponds to the element a1*b1*a2*b2*a3*b3*...*am*bm
+++ a1 and bm are possibly the neutral element
+++ the neutral element is represented by [EMAIL PROTECTED] [EMAIL
PROTECTED]
Rep == Record(factors1:List M1, factors2:List M2);
1:% == {
import from Rep,M1,M2;
per [ [EMAIL PROTECTED],[EMAIL PROTECTED];
}
one?(x:%):Boolean == {
import from M1,M2,Rep;
one? first ((rep x) factors1) and one? first ((rep x) factors2);
}
coerce(x:M1):% == {
import from List M1,List M2,Rep;
per [[x],[EMAIL PROTECTED];
}
coerce(y:M2):% == {
import from List M1,List M2,Rep;
per [EMAIL PROTECTED],[y]];
}
_=(x:%,y:%):Boolean == rep x = rep y;
coerce(w:%):OutputForm == {
import from Integer;
one? w => outputForm([EMAIL PROTECTED]);
import from List OutputForm,List List OutputForm;
import from OutputForm;
import from Symbol;
infix("*"::Symbol::OutputForm, reduce(concat,[ (if one? a then
[b::OutputForm] else if one? b then [a::OutputForm] else [a::OutputForm,
b::OutputForm]) for a:M1 in (rep w) factors1 for b:M2 in (rep w) factors2 ]));
}
reduceword!:Rep -> Rep;
reduceword!(x:Rep):Rep == {
x1:List M1 := x factors1;
x2:List M2 := x factors2;
import from NonNegativeInteger,List M1, List M2;
-- length one is in reduced form already
if(#x1 = 1) then x;
while (#x2 > 1) repeat {
while(#x2 > 1 and (one? second x1 or one? first x2))
repeat {
setfirst!(x1, first x1 * second x1);
setrest!(x1,rest rest x1);
setfirst!(x2, first x2 * second x2);
setrest!(x2,rest rest x2);
-- if there is change, we need to go back
if(one? first x1 or one? first x2) then {
reduceword!(x);
}
}
--next letter
x1:= rest x1;
x2:= rest x2;
}
x;
}
_*(x:%,y:%):% == {
w1:List M1 := concat((rep x) factors1, (rep y) factors1);
w2:List M2 := concat((rep x) factors2, (rep y) factors2);
res:Rep:=[w1,w2];
reduceword! res;
per res;
}
length(w:%):Integer == {
import from Rep, List M1, List M2, NonNegativeInteger;
n:Integer := (# ((rep w) factors1))::Integer + (# ((rep w)
factors2))::Integer;
if(one? first ((rep w) factors1)) then n:=n-1;
if(one? last ((rep w) factors2)) then n:=n-1;
n;
}
}
#include "axiom"
CyclicGroup(n:PositiveInteger,g:Symbol): Group with {
1: %;
coerce : % -> OutputForm;
one?: % -> Boolean;
coerce:Symbol -> %;
genrtr: %;
} == add {
Rep == Integer;
import from Integer;
1:% == per 0;
genrtr: % == per ([EMAIL PROTECTED]);
coerce(x:%):OutputForm == {
zero? rep x => outputForm([EMAIL PROTECTED]);
z where {import from Fraction Polynomial Integer; import from
Polynomial Integer;
z:OutputForm := ((g::Polynomial Integer)::Fraction
Polynomial Integer^(rep x))::OutputForm;
}
};
coerce(x:Symbol):% == {
x ~= g => error "wrong symbol";
per ([EMAIL PROTECTED]);
}
(x:%) * (y:%): % == per addmod(rep x,rep y,n::Integer);
(x:%) = (y:%): Boolean == rep x = rep y;
one?(x:%):Boolean == zero? rep x;
inv(x:%):% == { one? x => 1; per( n::Integer - rep x)};
}
_______________________________________________
Axiom-developer mailing list
Axiom-developer@nongnu.org
http://lists.nongnu.org/mailman/listinfo/axiom-developer