modify physop package

Help
Andy
2012-05-30
2012-11-20
  • Andy
    Andy
    2012-05-30

    Hello,

    I want to modify the physop-package in order to get a package for fermion-operators.
    First of all  I want to add the functionality that the operator A and the adjoint operator A!+ do not commutate any longer.
    Therefor I added a "noncom(list(x, adjp x));" after "reset!_opnums();   %1.03" in the procedure "scalop" of the physop-package:

    % scalar operator
    symbolic procedure scalop u;
    begin scalar y;
    for each x in u do
    if not idp x then
      msgpri("cannot declare",x,"a scalar operator",nil,nil)
    else if physopp x then
      msgpri(x,"already declared as",get(x,'phystype),nil,nil)
    else <<y :=gettype x;
           if y memq '(matrix operator array procedure) then
              msgpri(x,"already defined as",y,nil,nil)
           else <<
                  put(x,'rtype,'physop);
                  put(x,'phystype,'scalar);
                  put(x,'psimpfn,'physopsimp);
                  put(x,'physopname,x); % 1.02
                  defoporder!* := nconc(defoporder!*,list(x));
                  oporder!* := nconc(oporder!*,list(x));
                  physoplist!* := nconc(physoplist!*,list(x));
                  invphysop x; adj2 x; invadj x; %1.01
                  reset!_opnums();   %1.03
            noncom(list(x, adjp x));
                >>;
         >>;
    return nil
    end;
    

    Unfortunately I get the following message when I load the modified file:
    ***** list unit unit

    Cont? (Y or N)

    What did I wrong? Here is the noncom procedure I call (noncom2 package):

    symbolic procedure noncom u; %new
      begin scalar y,liste;
        if not listp u then rederr(u, "invalid argument to noncom");
        for each x in u do <<
          if not idp x then rederr(x, "invalid argument to noncom");
          noncom1 x;
          liste:=get(x,'noncommutes);
          y := delete(x,u);
          put(x, 'noncommutes, deletemult!* nconc(liste,y));
    % the following is needed for the physop package  added  2.1 140891 mw
          if (get(x,'rtype) = 'physop) then <<
           print("Drin!");
            noncom1 adjp x;
            liste:=get(adjp x, 'noncommutes);
            y := delete(adjp x, for each j in u collect adjp j);
            put(adjp x, 'noncommutes, deletemult!* nconc(liste,y));
            noncom1 invp x;
            liste:=get(invp x, 'noncommutes);
            y := delete(invp x,for each j in u collect invp j);
            put(invp x,'noncommutes,deletemult!* nconc(liste,y)) >> >>;
       return nil
     end;
    

    I'm not very expired in Lisp, so I don't understand why "noncom x;" works but "noncom(list(x, adjp x));" not, because in noncom is testet wether u is a list or not: "if not listp u then rederr(u, "invalid argument to noncom");"

    Can anybody help me - thank you very much for help :-)

    Andy

     
  • Rainer Schöpf
    Rainer Schöpf
    2012-05-31

    Hi Andy,

    there are two different issues here: first of all the calls to rederr in the noncom procedure are wrong, which is why you don't get a sensible error message. rederr has only one parameter, not two, so the first few lines of noncom must be

    symbolic procedure noncom u; %new
      begin scalar y,liste;
        if not listp u then rederr list(u, "invalid argument to noncom");
        for each x in u do <<
          if not idp x then rederr list (x, "invalid argument to noncom");
          noncom1 x;
    

    I have just commited this correction to the source repository.

    Secondly, and more important, noncom is not only a procedure, but also a statement, which means that its parameters are handled differently. Simply put, they are passed without evaluation. so that you don't pass the list

      (x x!+)

    but the unevaluated version

    (list x (adjp x))

    to noncom.

    You might try to call the procedure noncom indirectly instead, like:

    lispapply('noncom,list list(x, adjp x))
    

    which bypasses the special argument preparation step.

    A final comment: it might be better not to redefine scalop, but to create a new procedure, e.g. fermi_scalop for your purpose, so as to be able to define boson and fermion type operators seperately.

       Rainer

     
  • Andy
    Andy
    2012-05-31

    Hello Rainer,

    thank you very much for your answer :-)

    lispapply('noncom,list list(x, adjp x))
    

    works but I've a few problems to understand the solution.

    I thought that I can call noncom like adjp is called in noncom. And this is not possible because of the line "deflist('((noncom rlis)),'stat);" - right?
    This line means that you can call noncom also from algebraic mode? (Or what else do you mean with statement?)

    If a statement needs the unevaluated version - why can't I use the quote-operator in order to do so? Why do I need the extra function lispapply?
    In lispapply you use two times the word list - because list list(…) evaluates to list(…) like 'noncom to noncom?

    Thanks again for an answer,

    Andy

     
  • Rainer Schöpf
    Rainer Schöpf
    2012-06-05

    Hello Andy,

    basically the

    deflist('((noncom rlis)),'stat);
    

    defines a special syntax for noncom. That means that

    noncom foo,bar
    

    is first transformed into something else before the procedure noncom is actually called. By using the trick with lispapply the special parsing is skipped, and noncom called directly.

    The clean way to avoid that would be to define a procedure, say, noncom_internal that can be called as a normal procedure, and define  the procedure noncom to be just a wrapper that checks its parameters and calls noncom_internal for the real work. Unfortunately, the noncom2 package doesn't do it that way. I'll have a look at it.

    As for your question about lispapply, the additional call to list is needed because lispapply' second parameter is the list of arguments to its first parameter. So, to call a procdure with two arguments, you write

    lispapply('proc2,'(a1 a2))
    

    and for a procedure of one argument:

    lispapply('proc2,'(a1))
    

    Since noncom has only one parameter, which is to be the list generated by

    list(x,adjp x)
    

    , you have to pass a list containing only this one parameter.

      Rainer