Open SebastianHalbig opened 4 years ago
I keep my points numbered so that you can address them specifically if you want.
What is the advantage of specifying with root of unity to be taken, rather than always assuming that the root of unity to be created should be primitive? E.g., is there a differente from the point of view of the algebra relations if we take a the second 3rd root of unity or the first? One is the square of the other and vice-versa, but the behavior in terms of the relations is pretty much the same.
For the matrix, I implemented in the constructor a NumPy Array. I think this has several advantages of list of lists. In a list of lists, there is no control over what should be the size of the outter list and the sizes of the inner lists may be different. An array behaves like a rectangle and has access a shape method, that returns a tuple with the dimensions of the array. I use this to test if the input q-matrix has the correct dimensions and raise an error otherwise (see free_algebra.py lines 17-26)
Are you proposing that PBWAlgebra objects are created via a method of FreeAlgebra, instead of calling the constructor PBWAlgebra in the main file? Any advantage of this. I would lean towards using the constructor of PBWAlgebra and keep the syntax as similar as possible, i.e., have a string of handles as first argument.
A change that I implemented but we didn't get to discuss was to add an argument 'definitions' to the PBWAlgebra constructor, consisting of a list of Elements of the same size as the list of string handles that maps every PBW generator to its definition (i.e., by creating PBWLetter objects using the handle and the presentation). One alternative would be to create the PBWLetters before and separately and pass to PBWAlgebra constructor the list of the PBWLetters instead of both the handles and presentations.
1) Consider a pair of roots of unity (p,q) such that p =1 mod 3 and q = 1 mod 6 then q^2=p but q^2 /= 2 mod 3. When we define the Nichols algebra this might become important. (Note the point here isn't that we care about which subgroup of the unit circle they create but rather we look at a set of roots of unity and their relations to each other)
2) Sounds very good, I wasn't aware of that package!
3) Yes kind of. (Internally the constructor of PBWAlgebra would be called) The idea is to basically have a dict pbw_generators in FreeAlgebra. Whenever you generate a new PBWElement it is added to the dict. Once you're done defining your PBWgenerators you call generate_PBWAlgebra(pbw_generators: dict = None) which then passes the dict or a subset of the dict to the constructor of PBWAlgebra. The reason s that in algebra the setElement/setWord/.. methods constantly check that the defined elements are consistent. I.e. you can't define the same element twice. Words must be composits of already defined letters, etc. This way we further ensure that nothing "unexpected" happens.
Example: u = Word([a,b]) v = Word([a,b]) e = Element({u:1, v:-1}) -> should be zero but the constructor of element does not necessarily notice these subtleties.
4) I would opt for your seccond suggestion: pass a list of PBWElements to the constructor of PBWalgebra (this could be implicit, see 3)
What do you think of the following rough scheme for the free_algebra workflow? (Will certainly need improvement but it's a start)
alg = FreeAlgebra("a, b", {'q':[3,2], 'r': [3,5]} , [["q","r"],["r","q"]])
Explanation:
The letters "a" and "b" define the alphabet used in this algebra
internally the letter.Letter() is called on them and they are stored in a dict.
The dict is used to define the second third root of unity
(i.e the root corresponding to an angle of 240°).
The following tuple of tuples is the matrix of the braiding.
Here we need to make a consistent choice of column vs row.
u = alg.create_pbw_letter("u" , alg.bracket( alg.letters("a"), alg.letters("b")) ) v = ...
Here we set up the PBW vocabulary
pbw_alg = alg.setup_pbw_algebra([u, v])
To define the PBW-algebra