1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488 |
- module physop;
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % %
- % P H Y S O P %
- % %
- % A Package for Operator Calculus %
- % in Physics %
- % %
- % Author: Mathias Warns %
- % Physics Institute %
- % University of Bonn %
- % Nussallee 12 %
- % D-5300 BONN 1 (F.R.G.) %
- % <UNP008@DBNRHRZ1.bitnet> %
- % %
- % Version: 1.5 06 Jan 1992 %
- % %
- % Designed for: REDUCE version 3.4 %
- % Tested on : - Intel 386/486 AT compatible computers %
- % PSL implementation of REDUCE 3.4 %
- % - IBM 3084/9000-620 MVS/XA %
- % PSL implementation of REDUCE 3.4 %
- % %
- % CAUTION: (i) The NONCOM2 package is needed to run this package %
- % (ii) This package cannot be used simultaneously with %
- % packages modifying the standard GETRTYPE procedure %
- % %
- % Copyright (c) Mathias Warns 1990 - 1992 %
- % %
- % Permission is granted to any individual or institution to %
- % use, copy or re-distribute this software as long as it is %
- % not sold for profit, provided that this copyright notice %
- % is retained and the file is not altered. %
- % %
- % *** Revision history since issue of Version 0.99 *** %
- % %
- % - sloppy use of CAR on atoms corrected in various procedures %
- % - MUL and TSTACK added in PHYSOPTIMES %
- % - Bug in CLEARPHYSOP corrected %
- % - ordering procedures recoded for greater efficiency %
- % - handling of PROG expressions included via %
- % procedure PHYSOPPROG %
- % - procedures PHYSOPTIMES and MULTOPOP!* modified %
- % - extended error handling inclued via REDERR2 %
- % - PHYSOPTYPELET recoded %
- % - PHYSOPCONTRACT modified for new pattern natcher %
- % - EQ changed to = in MULTF and MULTFNC %
- % - PHYSOPCOMMUTE/PHYSOPANTICOMMUTE and COMM2 corrected %
- % - Handling of SUB and output printing adapted to 3.4 %
- % %
- % 1.1 130791 mw %
- % - Modifications for greater efficiency in procedures ORDOP, %
- % ISANINDEX and ISAVARINDEX %
- % - PHYSOP2SQ slightly modified for greater efficiency %
- % - Procedure COLLECTPHYSTYPE added %
- % - handling of inverse and adjoint operators modified %
- % procedures INV and ADJ2 modified %
- % procedures INVP and ADJP recoded %
- % - procedures GETPHYSTYPE!*SQ and GETPHYSTYPESF added for greater %
- % efficiency in type checking of !*SQ expressions %
- % - procedure GETPHYTYPE modified accordingly %
- % - SIMP!* changed to SUBS2 in procedure PHYSOPSUBS %
- % - Bug in EXPTEXPAND and PHYSOPEXPT corrected %
- % - PHYSOPORDCHK and PHYSOPSIMP slightly enhanced %
- % - PHYSOPTYPELET enhanced (COND treatment) %
- % - phystypefn for PLUS and DIFFERENCE changed to GETPHYSTYPEALL %
- % - GETPHYSTYPEALL added %
- % - GETPHYSTYPETIMES modified %
- % 1.2 190891 mw %
- % - implementation of property PHYSOPNAME for PHYSOPs %
- % - procedures SCALOP,VECOP,TENSOP,STATE,INV,ADJ2,INVADJ modified %
- % - procedure ORDOP recoded, NCMPCHK and PHYSOPMEMBER modified %
- % - procedure PHYSOPSM!* enhanced %
- % 1.3 test implementation of a new ordering scheme 260891 mw %
- % - Procedure OPNUM!* and RESET!_OPNUMS added %
- % - procedure ORDOP recoded %
- % - procedure SCALOP,VECOP,TENSOP,STATE,OPORDER modified %
- % - procedure !*XADD added %
- % - procedure PHYSOPSIMP corrected %
- % 1.4 181291 mw %
- % - bug in procedures SCALOPP, PHYSOPSIMP and TENSOP corrected %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- create!-package('(physop),'(contrib physics));
- %-------------------------------------------------------%
- % This part has to be modified by the user if required %
- %-------------------------------------------------------%
- % input the NONCOM2 package here for a compiled version
- % input noncom2;
- load!-package 'noncom2;
- % Modify the infix character for the OPAPPLY function if needed
- newtok'((|) opapply);
- flag('(opapply), 'spaced);
- %-------------------------------------------------------%
- % E N D of user modifiable part %
- %-------------------------------------------------------%
- %**************** the following is needed for REDUCE 3.4 *************
- fluid '(!*nosq); % controls proper use of !*q2a
- !*nosq := t;
- % ************** end of 3.4 modifications **************************
- fluid '(frlis!* obrkp!*);
- newtok '((d o t) dot);
- flag ('(dot), 'spaced);
- % define some global variables from REDUCE needed in the package
- fluid '(alglist!* subfg!* wtl!*);
- Global '(tstack!* mul!*);
- % ---define global variables needed for the package---
- FLuid '(oporder!* defoporder!* physopindices!* physopvarind!*);
- Fluid '(physoplist!*);
- Global '(specoplist!*);
- % define global flags
- fluid '(!*anticom !*anticommchk !*contract !*contract2 !*hardstop);
- fluid '(!*indflg indcnt!* !*ncmp ncmp!*);
- indcnt!* := 0;
- % additional flag needed for contraction
- !*contract2 := nil;
- % flag indicating that one elementary comm or opapply has not
- % been found --> print warning message
- !*hardstop := nil;
- % this are algebraic mode switches
- switch contract;
- switch anticom;
- % reserved operators and variables;
- % idx is the basic identifier for system created indices
- Global '(idx);
- % ----- link new data type PHYSOP in REDUCE ------
- % physop is the new datatype containing all subtypes
- put('physop,'name,'physop); %datatype name
- put('physop,'evfn,'!*physopsm!*); % basic simplification routine
- put('physop,'typeletfn,'physoptypelet); % routine for type assignements
- % Note: we need to make gamma a regular id.
- remprop('gamma,'simpfn); remflag('(gamma),'full);
- % ----RLISP procedures which have been modified -----
- % procedure for extended error handling
- symbolic procedure rederr2(u,v);
- begin
- msgpri("Error in procedure ",u, ": ", nil,nil);
- rederr v
- end ;
- % procedures multf and multfnc have to be redefined to avoid
- % contraction of terms after exptexpand
- symbolic procedure multf(u,v); % changed
- %U and V are standard forms.
- %Value is standard form for U*V;
- begin scalar ncmp,x,y;
- a: if null u or null v then return nil
- else if u=1 then return v % ONEP
- else if v=1 then return u % ONEP
- else if domainp u then return multd(u,v)
- else if domainp v then return multd(v,u)
- else if not(!*exp or ncmp!* or wtl!* or x)
- then <<u := mkprod u; v := mkprod v; x := t; go to a>>;
- x := mvar u;
- y := mvar v;
- % if (ncmp := noncomp y) and noncomp x then return multfnc(u,v)
- if noncommuting(x,y) then return multfnc(u,v)
- % we have to put this clause here to prevent evaluation in case
- % of equal main vars
- else if noncommutingf(y, lc u) or (ordop(x,y) and (x neq y))
- then << x := multf(lc u,v);
- y := multf(red u,v);
- return if null x then y else lpow u .* x .+ y>>
- else if x = y and (not physopp x or !*contract2)
- % two forms have the same mvars
- % switch contract added here to inhibit power contraction
- % if not wanted (used by PHYSOP)
- then << x := mkspm(x,ldeg u+ldeg v);
- y := addf(multf(red u,v),multf(!*t2f lt u,red v));
- return if null x or null(u := multf(lc u,lc v))
- then <<!*asymp!* := t; y>>
- else if x=1 then addf(u,y)
- else if null !*mcd then addf(!*t2f(x .* u),y)
- else x .* u .+ y>>;
- x := multf(u,lc v);
- y := multf(u,red v);
- return if null x then y else lpow v .* x .+ y
- end;
- symbolic procedure multfnc(u,v);
- %returns canonical product of U and V, with both main vars non-
- %commutative;
- begin scalar x,y;
- x := multf(lc u,!*t2f lt v);
- if null x
- then return addf(multf(red u,v),multf(!*t2f lt u,red v));
- % switch contract added here to avoid contraction of equal powers
- % used by PHYSOP
- return addf((if not domainp x and (mvar x = mvar u) and
- ((not physopp mvar x) or !*contract2)
- then addf(if null (y := mkspm(mvar u,ldeg u+ldeg v))
- then nil
- else if y = 1 then lc x
- else !*t2f(y .* lc x),
- multf(!*p2f lpow u,red x))
- else !*t2f(lpow u .* x)),
- addf(multf(red u,v),multf(!*t2f lt u,red v)))
- end;
- symbolic procedure opmtch!* u;
- % same as opmtch but turns subfg!* on
- begin scalar x,flg;
- flg:= subfg!*; subfg!* := t;x:= opmtch u; subfg!* := flg;
- return x
- end;
- symbolic procedure reval3 u;
- % this is just a redefinition of reval2(u,nil)
- % which call simp instead of simp!*
- % it saves at lot of writing in some procedures
- mk!*sq x where x := simp u;
- % ---- procedure related to ordering of physops in epxr -------
- symbolic procedure oporder u;
- % define a new oporder list
- begin
- if not listp u then rederr2('oporder, "invalid argument to oporder");
- if (u = '(nil)) then oporder!* := defoporder!* % default list
- else for each x in reverse u do <<
- if not physopp x then rederr2('oporder,
- list(x," is not a PHYSOP"));
- oporder!* := nconc(list(x),physopdelete(x,oporder!*)) >>; %1.01
- % write "oporder!* set to: ",oporder!*;terpri();
- reset!_opnums(); %1.03
- rmsubs()
- end;
- rlistat '(oporder);
- symbolic procedure physopdelete(u,v);
- % u is a physop, v is a list of physops
- % deletes u from v
- if atom u then delete(u,v)
- else
- delete(u,delete(car u,delete(removeindices(u,collectindices u),v)));
- symbolic procedure opnum!* u; % new 1.03
- begin scalar op,arglist;
- if not idp u then u := removeindices(u,collectindices u);
- if idp u then op := u
- else << op := car u; arglist := cdr u;>>;
- return
- if null (u:= assoc(arglist,get(op,'opnum))) then
- cdr assoc(nil,get(op,'opnum))
- else cdr u
- end;
- symbolic procedure reset!_opnums();
- begin scalar x,lst,n,op,arglist;
- lst := oporder!*;
- n := 1;
- a: if null lst then return;
- x := car lst; lst := cdr lst;
- if idp x then <<op := x; arglist := nil>>
- else <<op := car x; arglist := cdr x>>;
- put(op,'opnum,!*xadd((arglist . n),get(op,'opnum)));
- n:= n+1;
- go to a
- end;
- symbolic procedure !*xadd(u,v); % new 1.03
- % u is assignement , v is a table
- % returns updated table
- begin scalar x;
- x := v;
- while x and not (car u = caar x) do x := cdr x;
- if x then v := delete(car x,v);
- v := u . v;
- return v
- end;
- symbolic procedure ordop(u,v);
- % recoded ordering procedure of operators
- % checks new list oporder!* for physops or calls ordop2
- % default is to put anything ahead of physops
- % we use !*physopp instead of physopp in order to use
- % ordop even if we hide the physop rtype
- begin scalar x,y,z,nx,ny;
- % this are the trivial cases
- if not (!*physopp u and !*physopp v) then return
- if !*physopp u then nil
- else if !*physopp v then t
- else ordop2(u,v);
- % now come the cases with 2 physops
- % following section modified 1.02
- if idp u then x:= get(u,'physopname)
- else
- <<
- x:=get(car u,'physopname);
- x:= x . cdr u;
- u := car u;
- >>;
- if member(u,specoplist!*) then return t;
- if idp v then y:= get(v,'physopname)
- else
- <<
- y:= get(car v, 'physopname);
- y := y . cdr v;
- v := car v;
- >>;
- if member(v,specoplist!*) then return t;
- % end of modifications 1.02
- % from here it is 1.03
- nx := opnum!* x;
- ny := opnum!* y;
- return
- if nx < ny then t
- else if nx > ny then nil
- else if idp x then t
- else if idp y then nil
- else ordop(cdr x, cdr y);
- end;
- symbolic procedure ordop2(u,v);
- % this is nothing but the standard ordop procedure
- begin scalar x;
- x := kord!*;
- a: if null x then return ordp(u,v)
- else if u eq car x then return t
- else if v eq car x then return;
- x := cdr x;
- go to a
- end;
- % obsolete in 1.03
- %symbolic procedure physopmember(u,v); % 1.02 order modified
- % u is a physop, v is a list
- % return part of v starting with u
- %member(u,v) or ((not atom u) and (member(car u,v)
- % or member(removeindices(u,collectindices u),v)));
- symbolic procedure physopordchk(u,v); % new version 080591
- % u and v are physopexpr
- % builds up a list of physops of u and v
- % checks if there is a pair of wrong ordered noncommuting operators
- % in these lists
- begin scalar x,y,z,oplist,lst;
- x := deletemult!* !*collectphysops u; %1.01
- y := deletemult!* !*collectphysops v; % 1.01
- return
- if null x then t
- else if null y then nil
- else if member('unit,x) or member('unit,y) then nil %further eval needed
- else physopordchk!*(x,y);
- end;
- symbolic procedure ncmpchk(x,y); % order changed 1.02
- % x and y are physops
- % checks for correct ordering in noncommuting case
- (not noncommuting(x,y)) or ordop(x,y);
- symbolic procedure physopordchk!*(u,v);
- % u and v are lists of physops
- % checks if there is a pair of wrong ordered noncommuting operators
- % in this list
- begin scalar x,y,lst;
- x:= car u; u := cdr U;
- if null u then
- if null cdr v then
- return (ncmpchk(x,car v) and not (invp x = car v))
- else
- <<
- lst := for each y in v collect ncmpchk(x,y);
- if member(nil,lst) then return nil
- else return t
- >>
- else return (physopordchk!*(list(x),v) and physopordchk!*(u,v));
- end;
- % ---general testing functions for PHYSOP expressions----
- symbolic procedure physopp u;
- if atom u then (idp u and (get(u,'rtype) eq 'physop))
- else (idp car u and (get(car u,'rtype) eq 'physop));
- % slightly more general
- symbolic procedure !*physopp u;
- % used to determine physops when physop rtype is hidden
- if atom u then (idp u and get(u,'phystype))
- else (idp car u and get(car u,'phystype));
- symbolic procedure physopp!* u;
- physopp u or (not atom u and (flagp(car u,'physopfn) or
- (flagp(car u,'physoparith) and
- hasonephysop cdr u) or (flagp(car u,'physopmapping) and
- hasonephysop cdr u)));
- symbolic procedure !*physopp!* u;
- physopp!* u or getphystype u;
- symbolic procedure hasonephysop u;
- if null u then nil
- else (physopp!* car u) or hasonephysop cdr u;
- symbolic procedure areallphysops u;
- if null u then nil
- else if null cdr u then !*physopp!* car u
- else (!*physopp!* car u) and areallphysops cdr u;
- % *****defining functions for different data subtypes******
- % 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
- >>;
- >>;
- return nil
- end;
- symbolic procedure scalopp u;
- (idp u and get(u,'phystype) = 'scalar) or (not atom u and (
- (get(car u,'phystype) = 'scalar) or
- ((get(car u,'phystype) = 'vector) and isanindex cadr u)
- or ((get(car u,'phystype) = 'tensor) and
- (length(cdr u) >= get(car u,'tensdimen)) and
- areallindices(for k:=1 :get(car u,'tensdimen) collect nth(cdr u,k)))));
- symbolic procedure vecop u;
- begin scalar y;
- for each x in u do
- if not idp x then
- msgpri("cannot declare",x,"a vector 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,'vector);
- 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();
- >>;
- >>;
- return nil
- end;
- symbolic procedure vecopp u;
- (idp u and (get(u,'phystype) = 'vector)) or (not atom u and
- ((get(car u,'phystype) ='vector) and not isanindex cadr u));
- symbolic procedure tensop u;
- begin scalar y,n;
- % write "car u=",car u;terpri();
- for each x in u do
- <<
- if idp x or not numberp cadr x then
- msgpri("Tensor operator",x,"declared without dimension",nil,nil)
- else
- <<
- n:= cadr x; x:= car x;
- if not idp x then
- msgpri("cannot declare",x,"a tensor 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,'tensor);
- put(x,'psimpfn,'physopsimp);
- put(x,'physopname,x); % 1.02
- put(x,'tensdimen,n);
- 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();
- >>
- >>
- >>
- >>;
- return nil
- end;
- symbolic procedure tensopp u;
- (idp u and (get(u,'phystype) = 'tensor)) or (not atom u and
- ((get(car u,'phystype) ='tensor) and not isanindex cadr u));
- symbolic procedure state u;
- begin scalar y;
- for each x in u do
- if not idp x then msgpri("cannot declare",x,"a state",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,'state);
- 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));
- adj2 x;
- reset_opnums(); % 1.03
- >>
- >>;
- return nil
- end;
- symbolic procedure statep u;
- (idp u and get(u,'phystype) = 'state) or (not atom u and
- (idp car u and get(car u,'phystype) = 'state));
- symbolic procedure statep!* u;
- % slightly more general since state may be hidden in another operator
- (getphystype u = 'state);
- % some procedures for vecop and tensop indices
- symbolic procedure physindex u;
- begin scalar y;
- for each x in u do <<
- if not idp x then msgpri("cannot declare",x,"an index",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(y,"already defined as",y,nil,nil)
- else putanewindex x >>
- >>;
- return nil
- end;
- symbolic procedure physindexp u;
- % boolean function to test if an id is a physindex
- % in algebraic mode
- if idp u and isanindex u then t
- else if idlistp u and areallindices u then t
- else nil;
- flag ('(physindexp),'opfn);
- flag ('(physindexp),'boolean);
- deflist('((scalop rlis) (vecop rlis) (tensop rlis)
- (state rlis) (physindex rlis)),'stat);
- symbolic procedure isanindex u; %recoded 1.01
- idp u and (memq(u,physopindices!*) or member(u,physopvarind!*)
- or (memq(u,frlis!*) and member(revassoc(u,frasc!*),
- physopindices!*)));
- symbolic procedure isavarindex u; % recoded 1.01
- member(u,physopvarind!*);
- symbolic procedure areallindices u;
- isanindex car u and (null cdr u or areallindices cdr u);
- symbolic procedure putanewindex u;
- % makes a new index available to the system
- begin scalar indx;
- indx := u;
- if isanindex indx then nil
- else if (not atom indx) or getrtype indx then
- rederr2('putanewindex,list(indx,"is not an index"))
- else physopindices!* := nconc(physopindices!*,list(indx));
- return nil
- end;
- symbolic procedure putanewindex!* u;
- % used by ISANINDEX to recognize unresolved IDXn indices
- begin scalar x;
- if not idp u then return;
- x:= explode u;
- if length(x) < 4 then return;
- x := for j:= 1 : 3 collect nth(x,j);
- if not(x='(I D X ) or x='(!i !d !x)) then return; % check both cases.
- physopindices!* := nconc(physopindices!*,list(u));
- return t
- end;
- symbolic procedure makeanewindex();
- % generates a new index
- begin scalar x,n;
- n:=0;
- a: n:=n+1;
- x:= mkid('idx,n);
- if isanindex x then go to a
- else putanewindex x;
- return x
- end;
- symbolic procedure makeanewvarindex();
- % generates a new variable index
- % for patterm matching
- % physopvarind!* keeps var indices to avoid inflation
- begin scalar x,y,n;
- n:=0;
- y:= makeanewindex();
- x := intern compress append(explode '!=,explode y);
- nconc(frlis!*,list(x));
- physopvarind!*:= nconc(physopvarind!*,list(x));
- frasc!* := nconc(frasc!*,list((y . x)));
- return x
- end;
- symbolic procedure getvarindex n;
- begin scalar ilen;
- if not numberp n then rederr2 ('getvarindex,
- "invalid argument to getvarindex");
- ilen := length(physopvarind!*);
- return
- if n > ilen then makeanewvarindex()
- else nth(physopvarind!*,n);
- end;
- symbolic procedure transformvarindex u;
- % u is a free index
- % looks for the corresponding index on the frasc
- % or creates a new one
- begin scalar x;
- x := explode u;
- if length(x) < 3 or not(nth(x,2) eq '=) then return u;
- x := intern compress pnth(x,3);
- putanewindex x;
- if not atsoc(x,frasc!*) then
- frasc!* := nconc(frasc!*,list((x . u)));
- return x
- end;
- symbolic procedure insertindices(u,x);
- % u is a vecopp or tensopp
- % x is an index or a list of indices
- if (idp x and not isanindex x) or (idlistp x and not areallindices x)
- then rederr2('insertindices, "invalid indices to insertindex")
- else if vecopp u then if idp u then list(u,x)
- else car u . ( x . cdr u)
- else if tensopp u then if idp u then u . x
- else car u . nconc(x,cdr u)
- % do not insert any index in states or scalops
- else u;
- symbolic procedure insertfreeindices(u,flg);
- % procedure to transform vecop and tensop into scalops
- % by inserting free indices taken from the varindlist
- % flg is set to t if variable indices are requested
- begin scalar n,x;
- if vecopp u then <<x:= if flg then
- transformvarindex getvarindex(indcnt!* + 1)
- else getvarindex(indcnt!* + 1);
- return insertindices(u,x)>>
- else if tensopp u then <<n:= get(u,'tensdimen);
- x:= for k:=1 :n collect if flg then
- transformvarindex getvarindex(indcnt!* +k)
- else getvarindex(indcnt!* +k);
- return insertindices(u,x) >>
- else rederr2('insertfreeindices,
- "invalid argument to insertfreeindices");
- end;
- symbolic procedure collectindices u;
- % makes a list of all indices in a.e. u
- begin scalar v,x;
- if atom u then
- if isanindex u then return list(u)
- else return nil;
- a: v := car u;
- u := cdr u;
- x :=nconc(x,collectindices v);
- if null u then return x;
- go to a
- end;
- symbolic procedure removeindices(u,x);
- % u is physop (scalop) containing physindices
- % x is an index or a list of indices
- begin scalar op;
- trwrite('removeindices,"u= ",u," x= ",x);
- if null x or idp u or not !*physopp u then return u;
- if (idp x and not isanindex x) or (idlistp x and not areallindices x)
- then rederr2('removeindices, "invalid arguments to removeindices");
- op:=car u;u := cdr u;
- if null u then return op;
- if idp x then u := delete(x,u)
- else for each y in x do u:= delete(y,u);
- return if null u then op else op . u
- end;
- symbolic procedure deadindices u;
- % checks an a.e. u to see if there are dead indices
- % i.e. indices appearing twice or more
- %returns the list of dead indices in u
- begin scalar x,res;
- if null u or atom u then return nil;
- x := collectindices u;
- for each y in x do
- if memq(y,memq(y,x)) then res :=nconc(res,list(y));
- return res
- end;
- symbolic procedure collectphysops u;
- % makes a list of all physops in a.e. u
- begin scalar v,x;
- if atom u then
- if physopp u then return list(u)
- else return nil
- else if physopp u then return list(removeindices(u,collectindices u));
- a: v := car u;
- u := cdr u;
- x :=nconc(x,collectphysops v);
- if null u then return x;
- go to a
- end;
- symbolic procedure !*collectphysops u;
- % makes a list of all physops in a.e. u
- % with ALL indices
- begin scalar v,x;
- if physopp u then return list(u);
- if atom u then return nil;
- a: v := car u;
- u := cdr u;
- x :=nconc(x,!*collectphysops v);
- if null u then return x;
- go to a
- end;
- symbolic procedure collectphysops!* u;
- begin scalar x;
- x:= for each y in collectphysops u collect if idp y then y
- else car y;
- return x
- end;
- symbolic procedure collectphystype u; % new 1.01
- % makes a list of all physops in u
- % with ALL indices
- if physopp u then list(getphystype u)
- else if atom u then nil
- else deletemult!* (for each v in u collect getphystype v);
- % ---- PHYSOP procedures for type check and assignement ----
- % modify the REDUCE GETRTYPE routine to get control over PHYSOP
- % expressions
- symbolic procedure getrtype u; %modified
- % Returns overall algebraic type of u (or NIL if expression is a
- % scalar). Analysis is incomplete for efficiency reasons.
- % Type conflicts will later be resolved when expression is evaluated.
- begin scalar x,y;
- return
- if atom u
- then if not idp u then nil
- else if flagp(u,'share) then getrtype eval u
- else if x := get(u,'rtype)
- then if y := get(x,'rtypefn) then apply1(y,nil)
- else x
- else nil
- else if not idp car u then nil
- else if physopp!* u then 'physop % added
- else if (x := get(car u,'rtype)) and (x := get(x,'rtypefn))
- then apply1(x, cdr u)
- else if x := get(car u,'rtypefn) then apply1(x, cdr u)
- else nil
- end;
- symbolic procedure getrtypecadr u;
- not atom u and getrtype cadr u;
- symbolic procedure getnewtype u;
- not atom u and get(car u,'newtype);
- symbolic procedure getphystype u;
- % to get the type of a PHYSOP object
- begin scalar x;
- return
- if physopp u then
- if scalopp u then 'scalar
- else if vecopp u then 'vector
- else if tensopp u then 'tensor
- else if statep u then 'state
- else nil
- else if atom u then nil
- % following line suppressed 1.01
- % else if car u = '!*sq then return getphystype physopaeval u
- else if (x:=get(car u,'phystype)) then x
- else if (x:=get(car u,'phystypefn)) then
- apply1(x,cdr u)
- % from here it is 1.01
- else if null (x := collectphystype u) % 1.01
- then nil
- else if null cdr x then car x
- else if member('state,x) then 'state
- else rederr2('getphystype,list(
- "PHYSOP type conflict in",u));
- end;
- symbolic procedure getphystypecar u;
- not atom u and getphystype car u;
- symbolic procedure getphystypeor u;
- not atom u and (getphystype car u or getphystypeor cdr u);
- symbolic procedure getphystypeall args; % new 1.01
- begin scalar x;
- if null (x := collectphystype deleteall(0,args)) then
- return nil
- else if cdr x then
- rederr2('getphystypeall,
- list("PHYSOP type mismatch in",args))
- else return car x
- end;
- % ***** dirty trick *****
- % we introduce a rtypefn for !*sq expressions to get
- % proper type checking in assignements
- symbolic procedure physop!*sq U;
- % u is a !*sq expressions
- % checks if u contains physops
- begin scalar x;
- x:= !*collectphysops !*q2a car u;
- return
- if null x then nil
- else 'physop
- end;
- deflist('((!*sq physop!*sq)), 'rtypefn);
- % 1.01 we add also a phystypefn for !*sq
- symbolic procedure getphystype!*sq u; % new 1.01
- getphystypesf caar u;
- deflist('((!*sq getphystype!*sq)), 'phystypefn);
- symbolic procedure getphystypesf u; % new 1.01
- % u is a s.f.
- % returns the phystype of u
- if null u or domain!*p u then nil
- else getphystype mvar u or getphystypesf lc u;
- %-----end of 1.01 modifications -----------------
- % we have also to modify the simp!*sq routine since
- % there is no type checking included
- symbolic procedure physopsimp!*sq u;
- if cadr u then car u
- else if physop!*sq u then physop2sq physopsm!* !*q2a car u
- else resimp car u;
- put('!*sq,'simpfn,'physopsimp!*sq);
- % ***** end of dirty trick ******
- % ----PHYSOP evaluation and simplification procedures----
- symbolic procedure !*physopsm!* (u,v);
- % u is the PHYSOP expression to simplify
- begin scalar x,contractflg;
- % if contract is set to on we keep its value at the top level
- % (first call to physopsm) and set it to nil;
- contractflg:=!*contract;!*contract := nil;
- !*hardstop := nil;
- if physopp u then
- if (x:= get(u,'rvalue)) then u := physopaeval x
- else if idp u then return u
- else if x:=get(car u,'psimpfn) then u:= apply1(x,u)
- else return physopsimp u;
- u:= physopsm!* u;
- if !*hardstop then <<
- write " *************** WARNING: ***************";terpri();
- write "Evaluation incomplete due to missing elementary relations";
- terpri();
- return u>>;
- % the next step is to do substitutions if there are someones on
- % the matching lists
- if !*match or powlis1!* then <<
- u := physopsubs u;
- % now eval u with the substitutions
- u := physopsim!* u; >>;
- if not contractflg then return u
- else <<
- !*contract:=contractflg;
- return physopcontract u >>
- end;
- symbolic procedure physopsim!* u;
- if !*physopp!* u then physopsm!* u else u;
- symbolic procedure physop2sq u; %modified 1.01
- % u is a physop expr
- % returns standard quotient of evaluated u
- begin scalar x;
- return
- if physopp u then if (x:= get(u,'rvalue)) then physop2sq x
- else if idp u then !*k2q u
- else if (x:= get(car u,'psimpfn)) then
- if physopp (x:=apply1(x,u)) then
- !*k2q x
- else cadr physopsm!* x
- else if get(car u,'opmtch) and
- (x:= opmtch!* u) then physop2sq x
- else !*k2q u
- else if atom u then simp u % added 1.01
- else if car u eq '!*sq then cadr u
- else if null getphystype u then simp u % moved from top 1.01
- else physop2sq physopsm!* u
- end;
- symbolic procedure physopsm!* u;
- % basic simplification routine
- begin scalar oper,args,y,v,physopflg;
- % the following is 1.02
- if (null u or numberp u) then v := u
- else if physopp u then v:= if (y:= get(u,'rvalue)) then physopaeval y
- else if idp u then u
- else if (y:=get(car u,'psimpfn)) then
- apply1(y,u)
- else if get(car u,'opmtch) and
- (y:=opmtch!* u) then y
- else u
- else if atom u then v := aeval u
- else <<
- oper := car u;
- args := cdr u;
- if y:= get(oper,'physopfunction) then
- % this is a function which may also have normal scalar arguments
- % eg TIMES so we must check if args contain PHYSOP objects
- % or if it is an already evaluated expression of physops
- if flagp(oper,'physoparith) then
- if hasonephysop args then v:= apply(y,list args)
- else v := reval3 (oper . args)
- else if flagp(oper,'physopfn) then
- if areallphysops args then v:= apply(y,list args)
- else
- rederr2('physopsm!*,
- list("invalid call of ",oper," with args: ",args))
- else rederr2('physopsm!*,list(oper,
- " has been flagged Physopfunction"," but is not defined"))
- % this is for fns having a physop argument and no evaluation procedure
- else if flagp(oper,'physopmapping) and !*physopp!* args then
- v := mk!*sq !*k2q (oper . args)
- % special hack for handling of PROG constructs
- else if oper = 'PROG then v := physopprog args
- else v := aeval u
- >>;
- return v
- end;
- symbolic procedure physopsubs u;
- % general substitution routine for physop expressions
- % corresponds to subs2
- % u is a !*sq
- % result is u in a.e. form with all substitutions of
- % !*MATCH and POWLIS1!* applied
- % we use a quite dirty trick here which allows to use
- % the pattern matcher of standard REDUCE by hiding the
- % PHYSOP rtype temporarily
- begin scalar ulist,kord,alglist!*;
- % step 1: convert u back to an a.e.
- % u := physopaeval u; % 1.01 this line replaced
- u := physop2sq u;
- % step 2: transform all physops on physoplist in normal ops
- for each x in physoplist!* do << remprop(x,'rtype);
- put(x,'simpfn,'simpiden)>>;
- % since we need it here as a prefix op
- remflag('(dot),'physopfn);
- put('dot,'simpfn,'simpiden);
- % step 3: call simp!* on u
- % u := simp!* u; % 1.01 this line replaced
- u := subs2 u;
- % step 4: transform u back in an a.e.
- u := !*q2a u;
- % step 5: transform ops in physoplist back to physops
- for each x in physoplist!* do <<remprop(x,'simpfn);
- put(x,'rtype,'physop)>>;
- remprop('dot,'simpfn);
- flag('(dot),'physopfn);
- % final step return u
- return u
- end;
- symbolic procedure physopaeval u;
- % transformation of physop expression in a.e.
- begin scalar x;
- return
- if physopp u then
- if (x:=get(u,'rvalue)) then
- if car x eq '!*sq then !*q2a cadr x
- else x
- else if atom u then u
- else if (x:= get(car u,'psimpfn)) then apply1(x,u)
- else if get(car u,'opmtch) and (x:= opmtch!* u) then x
- else u
- else if (not atom u) and car u eq '!*sq then !*q2a cadr u
- else u
- end;
- symbolic procedure physopcontract u;
- % procedure to contract over dead indices
- begin scalar x,x1,w,y,z,ulist,veclist,tenslist,oldmatch,oldpowers,
- alglist!*,ncmplist;
- u := physopaeval u;
- if physopp u then return mk!*sq physop2sq u
- else if not getphystype u then return aeval u;
- % now came the tricky cases
- !*contract2 := t;
- % step1 : collect all physops in u
- ulist := collectphysops u;
- veclist := for each x in ulist collect if vecopp x then x else nil;
- tenslist := for each x in ulist collect if tensopp x then x else nil;
- veclist:= deletemult!* deleteall(nil,veclist);
- tenslist:=deletemult!* deleteall(nil,tenslist);
- % step2: we now modify powlis1!* and !*match
- oldmatch := !*match; !*match := nil;
- oldpowers := powlis1!*; powlis1!* := nil;
- % step3: transform all physops on physoplist in normal ops
- for each x in physoplist!* do
- <<
- remprop(x,'rtype);
- put(x,'simpfn,'simpiden);
- if noncomp!* x then ncmplist := x . ncmplist;
- >>;
- % we have to declare the ops in the specoplist as noncom to avoid
- % spurious simplifications during contraction
- remflag('(dot opapply),'physopfn); % needed here as a normal op
- flag(specoplist!*,'noncom);
- !*ncmp := t;
- for each x in specoplist!* do
- <<
- put(x,'simpfn,'simpiden);
- put(x,'noncommutes,ncmplist)
- >>;
- % step4: put new matching for each vecop on the list
- y := getvarindex(1);
- frlis!* := nconc(frlis!*,list('!=nv));
- frasc!* := nconc(frasc!*,list('nv . '!=nv));
- for each x in veclist do <<
- let2(list('expt,insertindices(x,transformvarindex y),'nv),
- list('expt,x,'nv),nil,t);
- x1:=delete(x,veclist);
- for each w in x1 do
- << z := list(list((insertindices(x,y) . 1),
- (insertindices(w,y) . 1)),(nil . t),
- list('dot,x,w),nil);
- !*match :=append(list(z),!*match) >>
- >>;
- % step4: put new matching for each tensop on the list
- frlis!* := nconc(frlis!*,list('!=nt));
- frasc!* := nconc(frasc!*,list('nt . '!=nt));
- for each x in tenslist do
- let2(list('expt,insertfreeindices(x,t),'nt),
- list('expt,x,'nt),nil,t);
- % step 6: call simp on u
- u := simp!* u;
- % step 7: restore previous settings
- powlis1!* := oldpowers;!*match := oldmatch;
- for each x in physoplist!* do
- <<
- remprop(x,'simpfn);
- put(x,'rtype,'physop)
- >>;
- flag('(dot opapply),'physopfn);
- remflag(specoplist!*,'noncom);
- for each x in specoplist!* do
- <<
- remprop(x,'noncommutes);
- remprop(x,'simpfn)
- >>;
- !*contract2 := nil;
- return mk!*sq u
- end;
- symbolic procedure physopsimp u; % 1 line deleted 1.03
- % procedure to simplify the arguments of a physop
- % inspired from SIMPIDEN
- begin scalar opname,w,x,y,flg;
- if idp u then return u;
- opname := car u;
- x := for each j in cdr u collect
- if idp j and (isanindex j or isavarindex j) then j %added 1.01
- else physopsm!* j;
- u := opname . for each j in x collect
- if eqcar(j,'!*sq) then prepsqxx cadr J
- else j;
- if x := opmtch!* u then return x;
- % special hack introduced here to check for
- % symmetric and antisymmetric tensor operators
- if scalopp u and tensopp opname then
- << y := get(opname,'tensdimen);
- % x is the list of physopsindices
- x:= for k:=1 :y collect nth(cdr u,k);
- % y contains the remaining indices
- if length(cdr u) > y then y := pnth(cdr u,y+1)
- else y := nil;
- if flagp(opname,'symmetric) then u:= opname . ordn x
- else if flagp(opname,'antisymmetric) then
- << if repeats x then return 0
- else if not permp(w := ordn x, x) then flg := t;
- x := w;
- u := opname . x >>
- else u := opname . x;
- if y then u:= append(u,y);
- return if flg then list('minus,u) else u
- >>
- % special hack to introduce unrecognized IDXn indices
- else if vecopp u then << if listp u then putanewindex!* cadr u;
- return u >>
- else if tensopp u then << if listp u then
- for j:= 1 : length(cdr u) do
- putanewindex!* nth(cdr u,j);
- return u >>
- else return u
- end;
- % ---- different procedures for arithmetic in phsyop expressions ----
- flag('(quotient times expt difference minus plus opapply),'physoparith);
- flag('(adj recip dot commute anticommute),'physopfn);
- flag ('(sub),'physoparith);
- flag('(sin cos tan asin acos atan sqrt int df log exp sinh cosh tanh),
- 'physopmapping);
- % the following is needed for correct type checking 101290 mw
- symbolic procedure checkphysopmap u;
- % checks an expression u for unresolved physopmapping operators
- begin scalar x;
- a: if null u or domain!*p u or atom u or null cdr u then return nil;
- x:= car u; u:= cdr u;
- if listp x and flagp(car x,'physopmapping) and hasonephysop cdr x
- then return t;
- go to a;
- end;
- symbolic procedure physopfn(oper,proc);
- begin
- put(oper,'physopfunction,proc);
- end;
- physopfn('difference,'physopdiff);
- symbolic procedure physopdiff args;
- begin scalar lht,rht,lhtype,rhtype;
- lht := physopsim!* car args;
- for each v in cdr args do <<
- rht := physopsim!* v;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if (rhtype and lhtype) and not(lhtype eq rhtype) then
- rederr2('physopdiff,"type mismatch in diff");
- lht :=
- mk!*sq addsq(physop2sq lht,negsq(physop2sq rht))
- >>;
- return lht
- end;
- put('difference,'phystypefn,'getphystypeall); % changed 1.01
- physopfn('minus,'physopminus);
- symbolic procedure physopminus arg;
- begin scalar rht,rhtype;
- rht := physopsim!* car arg;
- rht :=
- mk!*sq negsq(physop2sq rht);
- return rht
- end;
- put('minus,'phystypefn,'getphystypecar);
- physopfn('plus,'physopplus);
- symbolic procedure physopplus args;
- begin scalar lht,rht,lhtype,rhtype;
- lht := physopsim!* car args;
- for each v in cdr args do <<
- rht := physopsim!* v;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if (rhtype and lhtype) and not (lhtype eq rhtype) then
- rederr2 ('physopplus,"type mismatch in plus ");
- lht :=
- mk!*sq addsq(physop2sq lht,physop2sq rht)
- >>;
- return lht
- end;
- put('plus,'phystypefn,'getphystypeall); % changed 1.01
- physopfn('times,'physoptimes);
- symbolic procedure physoptimes args;
- begin scalar lht, rht,lhtype,rhtype,x,mul;
- if (tstack!* = 0) and mul!* then << mul:= mul!*; mul!* := nil; >>;
- tstack!* := tstack!* + 1;
- lht := physopsim!* car args;
- for each v in cdr args do <<
- rht :=physopsim!* v;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if not lhtype then
- if not rhtype then lht := mk!*sq multsq(physop2sq lht,physop2sq rht)
- else if zerop lht then lht := mk!*sq (nil . 1)
- else if onep lht then lht:= mk!*sq physop2sq rht
- else lht:= mk!*sq multsq(physop2sq lht,physop2sq rht)
- else if not rhtype then lht:=
- if zerop rht then mk!*sq (nil . 1)
- else if onep rht then mk!*sq physop2sq lht
- else mk!*sq multsq(physop2sq rht,physop2sq lht)
- else if physopordchk(physopaeval lht,physopaeval rht)
- and (lhtype = rhtype) and (lhtype = 'scalar)
- then lht := mk!*sq multsq(physop2sq lht,physop2sq rht)
- else lht:= multopop!*(lht,rht)
- >>;
- b: if null mul!* or tstack!* > 1 then go to c;
- lht := apply1(car mul!*,lht);
- mul!* := cdr mul!*;
- go to b;
- c: tstack!* := tstack!* - 1;
- if tstack!* = 0 then mul!* := mul;
- return lht
- end;
- put('times,'phystypefn,'getphystypetimes);
- symbolic procedure getphystypetimes args; % modified 1.01
- begin scalar x;
- if null (x := deleteall(nil,collectphystype args)) then
- return nil
- else if null cdr x then return car x
- else rederr2('getphystypetimes,
- list("PHYSOP type mismatch in",args))
- end;
- symbolic procedure multopop!*(u,v);
- % u and v are physop exprs in a.e. form
- % value is the product of u and v + commutators if needed
- begin scalar x,y,u1,v1,stac!*,res;
- % if there is no need for additional computations of commutators
- % return the product as a standard quotient
- u1:= physopaeval u;
- v1:= physopaeval v;
- if physopp u1 and physopp v1 then res := multopop(u1,v1)
- else if physopp v1 then
- if car u1 memq '(plus difference minus) then <<
- x:= for each y in cdr u1 collect physoptimes list(y,v);
- res:= reval3 (car u1 . x) >>
- else if car u1 eq 'times then <<
- stac!*:= reverse cdr u1; % begin with the last el
- y:= v;
- while stac!* do <<
- x := car stac!*;
- y := physoptimes list(x,y);
- stac!* := cdr stac!*;
- >>;
- res:= y >>
- else if car u1 eq 'quotient then res:= mk!*sq
- quotsq(physop2sq physoptimes list(cadr u1,v),
- physop2sq caddr u1)
- else res:= physoptimes list(u1,v1)
- else if car v1 memq '(plus difference minus) then <<
- x:= for each y in cdr v1 collect physoptimes list(u,y);
- res:= reval3 (car v1 . x) >>
- else if car v1 eq 'times then <<
- stac!*:= cdr v1;
- y:= u;
- while stac!* do <<
- x := car stac!*;
- y := physoptimes list(y,x);
- stac!* := cdr stac!*;
- % write "y= ",y," stac= ",stac!*;terpri();
- >>;
- res:= y >>
- else if car v1 eq 'quotient then res:= mk!*sq
- quotsq(physop2sq physoptimes list(u,cadr v1),
- physop2sq caddr v1)
- else res:= physoptimes list(u1,v1);
- return res
- end;
- symbolic procedure multopop(u,v);
- % u and v are physops (kernels)
- % value is the product of physops + commutators if necessary
- begin scalar res,x,ltype,rtype;
- ltype := getphystype u;
- rtype := getphystype v;
- if ltype neq rtype then
- rederr2('multopop,"type conflict in TIMES")
- else if (invp u = v) then res := mk!*sq !*k2q 'unit
- else if u = 'unit then res := mk!*sq !*k2q v
- else if v = 'unit then res := mk!*sq !*k2q u
- else if ordop(u,v) then
- res := mk!*sq !*f2q multfnc(!*k2f u,!*k2f v)
- else if noncommuting(u,v) then <<x:= comm2(u,v);
- res:= if !*anticommchk then physopplus
- list(list('minus,list('times,v,u)),x)
- else physopplus
- list(list('times,v,u),x) >>
- else res := mk!*sq !*f2q multfnc(!*k2f v,!*k2f u);
- return res
- end;
- physopfn('expt,'physopexpt);
- symbolic procedure physopexpt args;
- begin scalar n1,n2,lht,rht,lhtype,rhtype,x,y,z;
- % we have to add a special bootstrap to avoid too much simplification
- % in case of dot products raise to a power
- lht := physopsm!* car args;
- rht := physopsm!* cadr args;
- lhtype := physopp lht ;
- rhtype := physopp rht;
- if rhtype then
- rederr2('physopexpt,"operators in the exponent cannot be handled");
- if not getphystype lht then lht := reval3 list('expt,lht,rht);
- if not lhtype then
- if numberp rht then <<
- n1 := car divide(rht,2);
- n2 := cdr divide(rht,2);
- lhtype := getphystype lht;
- if (lhtype and zerop rht) then lht := mk!*sq !*k2q 'unit %1.01
- else if lhtype = 'vector then <<
- x:= for k:= 1 : n1 collect physopdot list(lht,lht);
- if onep n1 then x := 1 . x;
- lht:= if zerop n2 then physoptimes x
- else physoptimes append(x,list(lht));>>
- else if lhtype = 'tensor then <<
- x:= for k:= 1 : n1 collect physoptens list(lht,lht);
- if onep n1 then x := 1 . x;
- lht:= if zerop n2 then physoptimes x
- else physoptimes append(x,list(lht));>>
- else if lhtype = 'state then
- rederr2('physopexpt,
- "expressions involving states cannot be exponentiated")
- else << lht := physopaeval lht;
- x := deletemult!* collectindices lht;
- z := lht;
- for k :=2 :rht do <<
- for each x1 in x do
- if isavarindex x1 then
- lht:= subst(makeanewvarindex(),x1,lht)
- else lht:=subst(makeanewindex(),x1,lht);
- y := append(y,list(lht));
- lht := z; >>;
- lht := physoptimes (z . y); >>;
- >>
- else lht := mk!*sq simpx1(physopaeval lht,physopaeval rht,1)
- else if lht = 'unit then lht := mk!*sq !*k2q 'unit
- else if numberp rht then lht := exptexpand(lht,rht)
- else lht := mk!*sq !*P2q (lht . physopaeval rht); %0.99c
- return lht
- end;
- put('expt,'phystypefn,'getphystypeexpt);
- symbolic procedure getphystypeexpt args; % recoeded 0.99c
- begin scalar x;
- x := getphystypecar args;
- return
- if null x then nil
- else if numberp cadr args and evenp cadr args then 'scalar
- else x;
- end;
- symbolic procedure exptexpand(u,n);
- begin scalar bool,x,y,v,n1,n2,res,flg;
- if not numberp n then
- rederr2('exptexpand,list("invalid argument ",n," to EXPT"));
- if zerop n then return mk!*sq !*k2q 'unit; %1.01
- bool := if n < 0 then t else nil;
- n := if bool then abs(n) else n;
- n1 := car divide(n,2);
- n2 := cdr divide(n,2);
- if zerop n1 then return mk!*sq !*k2q
- if bool then invp u else u;
- res := (1 . 1);
- for k := 1 : n1 do <<
- if scalopp u then
- if bool then x := multf(!*k2f invp u, !*k2f invp u) . 1
- else x := multf(!*k2f u, !*k2f u) . 1
- % if bool then x:= list(list((invp u . 1),((invp u . 1) . 1))) . 1
- % else x:= list(list((u . 1),((u . 1) . 1))) . 1
- else if vecopp u then
- if bool then x:= quotsq((1 . 1),physop2sq physopdot list(u,u))
- else x:= physop2sq physopdot list(u,u)
- else if tensopp u then <<
- if bool then x:= quotsq((1 . 1),
- physop2sq physoptens list(u,u))
- else x:= physop2sq physoptens list(u,u) >>
- else rederr2('exptexpand, "cannot raise a state to a power");
- res := multsq(res,x)
- >>;
- b:
- if zerop n2 then return mk!*sq res;
- u:= if bool then invp u else u;
- return mk!*sq multsq(res,!*k2q u)
- end;
- physopfn('quotient,'physopquotient);
- symbolic procedure physopquotient args;
- begin scalar lht, rht,y,lhtype,rhtype;
- lht := physopsim!* car args;
- rht := physopsim!* cadr args;
- lhtype := getphystype car args;
- rhtype := getphystype cadr args;
- if rhtype memq '(vector state tensor) then
- rederr2('physopquotient, "invalid quotient")
- else if not rhtype then return
- mk!*sq quotsq(physop2sq lht,physop2sq rht);
- lhtype := physopp lht;
- rht := physopaeval rht;
- rhtype := physopp rht;
- if rhtype then
- if not lhtype then lht:= mk!*sq multsq(physop2sq lht,!*k2q invp rht)
- else lht:= physoptimes list(lht,invp rht)
- else if car rht eq 'times and null deadindices rht then
- << rht := reverse cdr rht;
- rht := for each x in rht collect
- physopquotient list(1,x);
- lht := physoptimes append(list(lht),rht) >>
- else lht:= mk!*sq quotsq(physop2sq lht,physop2sq rht);
- return lht
- end;
- put('quotient,'phystypefn,'getphystypeor);
- physopfn('recip,'physoprecip);
- symbolic procedure physoprecip args;
- physopquotient list(1,args);
- put('recip,'phystypefn,'getphystypecar);
- symbolic procedure invphysop u;
- % inverse of physops
- begin scalar x,y;
- if not physopp u then rederr2('invphysop,"invalid argument to INVERSE");
- if u = 'unit then return u;
- y:= if idp u then u else car u;
- x := reversip explode y;
- x := intern compress nconc(reversip x,list('!!,'!-,'!1));
- put(y,'inverse,x); % 1.01
- put(x,'inverse,y); % 1.01
- put(x,'physopname,y); % 1.02
- if not physopp x then << put(x,'rtype,'physop);
- put(x,'phystype,get(y,'phystype));
- put(x,'psimpfn,'physopsimp);
- put(x,'tensdimen,get(y,'tensdimen));
- physoplist!* := nconc(physoplist!*,list(x));
- >>;
- if idp u then return x
- else return nconc(list(x),cdr u)
- end;
- symbolic procedure invp u; % recoded 1.01
- % special cases
- if u = 'unit then u
- else if atom u then get(u,'inverse)
- else if member(car u,'(comm anticomm)) then
- list('quotient,1,u)
- else get(car u,'inverse) . cdr u;
- physopfn('sub,'physopsub); %subcommand;
- % ********* redefinition of SUB handling is necessary in 3.4 **********
- remprop('sub,'physopfunction);
- put('sub,'physopfunction,'subeval);
- put('physop,'subfn,'physopsub);
- symbolic procedure physopsub(u,v); %redefined
- % u is a list of substitutions as an a--list
- % v is a simplified physop in prefix form
- begin scalar res;
- if null u or null v then return v;
- v := physopaeval v;
- for each x in u do v := subst(cdr x,car x,v);
- return physopsm!* V
- end;
- % *********** end of 3.4 modifications ******************
- symbolic procedure physopprog u;
- % procedure to handle prog expressions (i.e. loops) containing physops
- begin scalar x;
- % we use basically the same trick as in physopsubs
- % step 1: transform all physops on physoplist in normal ops
- for each x in physoplist!* do <<remprop(x,'rtype);
- put(x,'simpfn,'simpiden)>>;
- % step 2: call normal prog on u
- u := aeval ('prog . u);
- % step 3: transform u back in an a.e.
- u := physopaeval u;
- % step 4: transform ops in physoplist back to physops
- for each x in physoplist!* do <<remprop(x,'simpfn);
- put(x,'rtype,'physop)>>;
- % final step return u
- return physopsm!* u
- end;
- % ****** procedures for physopfns ***********
- physopfn('dot,'physopdot);
- infix dot;
- precedence dot,*;
- symbolic procedure physopdot args;
- begin scalar lht,rht,lhtype,rhtype,x,n,res;
- lht := physopaeval physopsim!* car args;
- rht := physopaeval physopsim!* cadr args;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if not( (lhtype and rhtype) and (lhtype eq 'vector) ) then
- rederr2 ('physopdot,"invalid arguments to dotproduct");
- lhtype := physopp lht;
- rhtype := physopp rht;
- if rhtype then
- if lhtype then << if !*indflg then<<
- lht := insertfreeindices(lht,nil);
- rht := insertfreeindices(rht,nil);
- indcnt!* := indcnt!* + 1; >>
- else <<x := makeanewindex();
- lht := insertindices(lht,x);
- rht := insertindices(rht,x);>>;
- res := physoptimes list(lht,rht)>>
- else <<
- if car lht eq 'minus then
- res := mk!*sq negsq(physop2sq physopdot list(cadr lht,rht))
- else if car lht eq 'difference then res := mk!*sq addsq(
- physop2sq physopdot list(cadr lht,rht),negsq(physop2sq
- physopdot list(caddr lht,rht)))
- else if car lht eq 'plus then <<
- x := for each y in cdr lht collect physopdot list(y,rht);
- res := reval3 append(list('plus),x) >>
- else if car lht eq 'quotient then <<
- if not vecopp cadr lht then
- rederr2('physopdot,"argument to DOT")
- else res := mk!*sq quotsq(physop2sq
- physopdot list(cadr lht,rht),physop2sq caddr lht) >>
- else if car lht eq 'times then <<
- for each y in cdr lht do
- if getphystype y eq 'vector then x:=y;
- lht :=delete(x,cdr lht);
- res := physoptimes
- nconc(lht,list(physopdot list(x,rht))) >>
- else rederr2('physopdot, "invalid arguments to DOT") >>;
- if not rhtype then <<
- if car rht eq 'minus then
- res := mk!*sq negsq(physop2sq physopdot list(lht,cadr rht))
- else if car rht eq 'difference then res := mk!*sq addsq(
- physop2sq physopdot list(lht,cadr rht),negsq(physop2sq
- physopdot list(lht, caddr rht)))
- else if car rht eq 'plus then <<
- x := for each y in cdr rht collect physopdot list(lht,y);
- res := reval3 append(list('plus),x) >>
- else if car rht eq 'quotient then <<
- if not vecopp cadr rht then
- rederr2 ('physopdot,"invalid argument to DOT")
- else res := mk!*sq quotsq(physop2sq physopdot
- list(lht,cadr rht),physop2sq caddr rht) >>
- else if car rht eq 'times then <<
- for each y in cdr rht do if getphystype y eq 'vector then x:=y;
- rht :=delete(x,cdr rht);
- res := physoptimes
- nconc(rht,list(physopdot list(lht,x))) >>
- else rederr2 ('physopdot,"invalid arguments to DOT") >>;
- return res
- end;
- put('dot,'phystype,'scalar);
- symbolic procedure physoptens args;
- % procedure for products of tensor expressions
- begin scalar lht,rht,lhtype,rhtype,x,n,res;
- lht := physopaeval physopsim!* car args;
- rht := physopaeval physopsim!* cadr args;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if not( (lhtype and rhtype) and (lhtype eq 'tensor) ) then
- rederr2 ('physoptens,"invalid arguments to tensproduct");
- lhtype := physopp lht;
- rhtype := physopp rht;
- if rhtype then
- if lhtype then << n:= get(lht,'tensdimen);
- if (n neq get(rht,'tensdimen)) then
- rederr2('physoptens,
- "tensors must have the same dimension to be multiplied");
- if !*indflg then<<
- lht := insertfreeindices(lht,nil);
- rht := insertfreeindices(rht,nil);
- indcnt!* := indcnt!* + n; >>
- else <<x := for k:= 1 : n collect makeanewindex();
- lht := insertindices(lht,x);
- rht := insertindices(rht,x);>>;
- res := physoptimes list(lht,rht)>>
- else <<
- if car lht eq 'minus then
- res := mk!*sq negsq(physop2sq physoptens list(cadr lht,rht))
- else if car lht eq 'difference then res := mk!*sq addsq(
- physop2sq physoptens list(cadr lht,rht),negsq(physop2sq
- physoptens list(caddr lht,rht)))
- else if car lht eq 'plus then <<
- x := for each y in cdr lht collect physoptens list(y,rht);
- res := reval3 append(list('plus),x) >>
- else if car lht eq 'quotient then <<
- if not tensopp cadr lht then
- rederr2 ('physoptens,"invalid argument to TENS")
- else res := mk!*sq quotsq(physop2sq
- physoptens list(cadr lht,rht),physop2sq caddr lht) >>
- else if car lht eq 'times then <<
- for each y in cdr lht do
- if getphystype y eq 'tensor then x:=y;
- lht :=delete(x,cdr lht);
- res := physoptimes
- nconc(lht,list(physoptens list(x,rht))) >>
- else rederr2('physoptens, "invalid arguments to TENS") >>;
- if not rhtype then <<
- if car rht eq 'minus then
- res := mk!*sq negsq(physop2sq physoptens list(lht,cadr rht))
- else if car rht eq 'difference then res := mk!*sq addsq(
- physop2sq physoptens list(lht,cadr rht),negsq(physop2sq
- physoptens list(lht, caddr rht)))
- else if car rht eq 'plus then <<
- x := for each y in cdr rht collect physoptens list(lht,y);
- res := reval3 append(list('plus),x) >>
- else if car rht eq 'quotient then <<
- if not tensopp cadr rht then
- rederr2 ('physoptens,"invalid argument to TENS")
- else res := mk!*sq quotsq(physop2sq physoptens
- list(lht,cadr rht),physop2sq caddr rht) >>
- else if car rht eq 'times then <<
- for each y in cdr rht do if getphystype y eq 'tensor then x:=y;
- rht :=delete(x,cdr rht);
- res := physoptimes
- nconc(rht,list(physoptens list(lht,x))) >>
- else rederr2('physoptens, "invalid arguments to TENS") >>;
- return res
- end;
- put('tens,'phystype,'scalar);
- % -------- procedures for commutator handling -------------
- symbolic procedure comm2(u,v);
- % general procedure for getting commutators
- begin scalar x,utype,vtype,y,z,z1,res;
- if not (physopp u and physopp v) then rederr2('comm2,
- "invalid arguments to COMM");
- utype := getphystype u;
- vtype := getphystype v;
- if not (utype eq 'scalar) and (vtype eq 'scalar) then
- rederr2('comm2, "comm2 can only handle scalar operators");
- !*anticommchk:= nil;
- if not noncommuting(u,v) then return
- if !*anticom then mk!*sq !*f2q multf(!*n2f 2,multfnc(!*k2f v,!*k2f u))
- else mk!*sq (nil . 1);
- x := list(u,v);
- z := opmtch!* ('comm . x);
- if null z then z:= if (y:= opmtch!* ('comm . reverse x)) then
- physopsim!* list('minus,y)
- else nil;
- if z and null !*anticom then res:= physopsim!* z
- else << z1 := opmtch!* ('anticomm . x);
- if null z1 then
- z1 := if (y:=opmtch!* ('anticomm . reverse x)) then y
- else nil;
- if z1 then << !*anticommchk := T;
- res:= physopsim!* z1>>
- >>;
- if null res then
- << !*hardstop:= T;
- if null !*anticom then res := mk!*sq !*k2q ('comm . x)
- else << !*anticommchk := T;
- res := mk!*sq !*k2q ('anticomm . x) >>
- >>;
- return res
- end;
- physopfn('commute,'physopcommute);
- symbolic procedure physopcommute args;
- begin scalar lht,rht,lhtype,rhtype,x,n,res,flg;
- lht := physopaeval physopsim!* car args;
- rht := physopaeval physopsim!* cadr args;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if not (lhtype and rhtype) then return mk!*sq !*d2q 0
- else if not(rhtype = lhtype) then
- rederr2('physopcommute,
- "physops of different types cannot be commuted")
- else if not(lhtype eq 'scalar) then
- rederr2 ('physopcommute,
- "commutators only implemented for scalar physop expressions");
- % flg := !*anticom; !*anticom := nil;
- lhtype := physopp lht;
- rhtype := physopp rht;
- % write "lht= ",lht," rht= ",rht;terpri();
- if rhtype then
- if lhtype then << res := comm2(lht,rht);
- if !*anticommchk then
- res := physopdiff list(res,
- physoptimes list(2,rht,lht)); >>
- else res := mk!*sq negsq(physop2sq physopcommute list(rht,lht))
- else <<
- if car rht eq 'minus then res:= mk!*sq negsq(physop2sq
- physopcommute list(lht, cadr rht));
- if car rht eq 'difference then res := mk!*sq addsq(
- physop2sq physopcommute list(lht,cadr rht),negsq(physop2sq
- physopcommute list(lht,caddr rht)));
- if car rht eq 'plus then <<
- x:= for each y in cdr rht collect
- physopcommute list(lht,y);
- res:= reval3 append(list('plus),x) >>;
- if car rht memq '(expt dot commute) then
- res := physopcommute list(lht,physopsim!* rht);
- if car rht eq 'quotient then
- if physopp caddr rht then
- res:= physopcommute list(lht,physopsim!* rht)
- else
- res := mk!*sq quotsq(physop2sq physopcommute list(lht,cadr rht),
- physop2sq caddr rht);
- if car rht eq 'times then <<
- n := length cdr rht;
- if (n = 2) then res := reval3 list('plus, physopsim!*
- list('times,cadr rht,physopcommute list(lht, caddr rht)),
- physopsim!* list('times,physopcommute list(lht, cadr rht),caddr rht))
- else res := reval3 list('plus, physopsim!*
- list('times,cadr rht,physopcommute list(lht,
- append('(times),cddr rht))), physopsim!* append(
- list('times,physopcommute list(lht, cadr rht)), cddr rht)) >>
- >>;
- % !*anticom := flg;
- return res
- end;
- put('commute,'phystype,'scalar);
- physopfn('anticommute,'physopanticommute);
- symbolic procedure physopanticommute args;
- begin scalar lht,rht,lhtype,rhtype,x,n,res,flg;
- lht := physopaeval physopsim!* car args;
- rht := physopaeval physopsim!* cadr args;
- lhtype := getphystype lht;
- rhtype := getphystype rht;
- if not (lhtype and rhtype) then
- return mk!*sq aeval list('plus,list('times,lht,rht),
- list('times,rht,lht))
- else if not(rhtype = lhtype) then
- rederr2('physopanticommute,
- "physops of different types cannot be commuted")
- else if not(lhtype eq 'scalar) then
- rederr2 ('physopanticommute,
- "commutators only implemented for scalar physop expressions");
- % flg := !*anticom;!*anticom :=t;
- lhtype := physopp lht;
- rhtype := physopp rht;
- % write "lht= ",lht," rht= ",rht;terpri();
- if rhtype then
- if lhtype then
- <<
- x := comm2(lht,rht);
- if null !*anticommchk then
- If !*hardstop then res := mk!*sq !*k2q list('anticomm,lht,rht)
- else res := reval3 list('plus,x,physoptimes list(2,rht,lht))
- else res := x;
- >>
- else res := physopsim!* physopanticommute list(rht,lht)
- else <<
- if car rht eq 'minus then res:= mk!*sq negsq(physop2sq
- physopanticommute list(lht, cadr rht));
- if car rht eq 'difference then mk!*sq addsq(physop2sq
- physopanticommute list(lht,cadr rht),negsq(physop2sq
- physopanticommute list(lht,caddr rht)));
- if car rht eq 'plus then <<
- x:= for each y in cdr rht collect
- physopanticommute list(lht,y);
- res:= reval3 append(list('plus),x) >>
- else res := physopplus list(physoptimes list(lht,rht),
- physoptimes list(rht,lht));
- >>;
- % !*anticom := flg;
- return res
- end;
- put('anticommute,'phystype,'scalar);
- symbolic procedure commsimp u;
- % procedure to simplify the arguments of COMM or ANTICOMM
- % if they are not simple physops
- begin scalar opname,x,y,flg,res;
- opname := car u;
- x := physopsim!* cadr u;
- y := physopsim!* caddr u;
- % write "op= ",opname," x= ",x," y= ",y;terpri();
- flg := !*anticom;
- if opname = 'anticomm then !*anticom := t;
- res := if physopp x and physopp y then physopaeval comm2(x,y)
- else if opname eq 'comm then list('commute,physopaeval x,
- physopaeval y)
- else list('anticommute,physopaeval x,physopaeval y);
- !*anticom := flg;
- return res
- end;
- % -------------- application of ops on states ----------------
- physopfn('opapply,'physopapply);
- infix opapply;
- precedence opapply,-;
- symbolic procedure physopapply args; % changed 0.99b
- begin scalar lhtype,rhtype,wave,op,wavefct,res,x,y,flg;
- lhtype := statep!* car args;
- rhtype := statep!* cadr args;
- if rhtype and lhtype then
- return statemult(car args,cadr args)
- else if rhtype then
- <<wave := physopaeval physopsim!* cadr args;
- op := physopaeval physopsim!* car args >>
- else if lhtype then
- <<wave := physopaeval physopadj list(car args);
- op := physopaeval physopadj cdr args >>
- % a previous application of physopapply may have annihilated the
- % state
- else if zerop car args or zerop cadr args then return mk!*sq (nil . 1)
- else rederr2('opapply, "invalid arguments to opapply");
- if null getphystype op then
- res:= mk!*sq multsq(physop2sq op,physop2sq wave)
- else if not physopp op then
- if car op eq 'minus then
- res := mk!*sq negsq(physop2sq physopapply list(cadr op,wave))
- else if car op memq '(plus difference) then <<
- for each y in cdr op do <<
- res:= nconc(res,list(physopapply list(y,wave)));
- if !*hardstop then flg:= t;
- !*hardstop := nil;>>;
- if flg then !*hardstop := t;
- res := reval3 ((car op) . res) >>
- else if car op memq '(dot commute anticommute expt) then
- res := physopapply list(physopsim!* op,wave)
- else if car op eq 'quotient then
- if physopp caddr op then
- res := physopapply list(physopsim!* op,wave)
- else res := mk!*sq quotsq(physop2sq
- physopapply list(cadr op,wave),physop2sq caddr op)
- else if car op eq 'times then
- <<op := reverse cdr op;
- while op and not !*hardstop do
- << x := car op; op := cdr op;
- wave := physopapply list(x,wave) >>;
- if !*hardstop then
- if null op then res := wave
- else << x:= physopaeval wave;
- op := 'times . reverse op;
- while x do
- << y := car x; x := cdr x;
- if listp y and
- (y := assoc('opapply,y)) then
- << wavefct := list('opapply,
- nconc(op,list(cadr y)),
- caddr y);
- wave := subst(wavefct,y,wave);
- >>;
- >>;
- res := wave;
- >>
- else res := wave;
- >>
- else rederr2('opapply, "invalid operator to opapply")
- % special hack here for unit operator 0.99c
- else if op = 'unit then res := mk!*sq physop2sq wave
- else if physopp wave or
- (flagp(car wave,'physopmapping) and statep!* cdr wave) then
- <<x := opmtch!* list('opapply,op,wave);
- if null x then x := physopadj list(
- opmtch!* list('opapply,adjp wave,adjp op));
- if null x then <<!*hardstop := t;
- res := mk!*sq !*k2q
- list('opapply,op,wave); >>
- else res := mk!*sq physop2sq x;
- >>
- else << x := wave; wave := nil;
- while x do <<
- wavefct := car x; x := cdr x;
- if statep!* wavefct then wave := nconc(wave,
- list(physopaeval physopapply list(op,wavefct)))
- else wave := nconc(wave,list(wavefct));
- if !*hardstop then flg := t;
- !*hardstop := nil >>;
- if flg then !*hardstop := t;
- res := mk!*sq physop2sq wave;
- >>;
- return res
- end;
- put('opapply,'phystypefn,'getphystypestate);
- symbolic procedure getphystypestate args;
- if statep!* car args and statep!* cadr args then nil
- else 'state;
- symbolic procedure statemult(u,v); % recoded 0.99c
- % u and v are states
- % returns product of these
- begin scalar x,y,res,flg;
- if not (statep!* u or statep!* v) then
- rederr2 ('statemult,"invalid args to statemult");
- if (not atom u and car v eq 'opapply) then
- return expectval(u,cadr v,caddr v);
- if (not atom u and car u eq 'opapply) then
- return expectval(cadr u,caddr u,v);
- u := physopaeval physopsim!* u;
- v := physopaeval physopsim!* v;
- if physopp u then
- if physopp v then
- <<
- x := opmtch!* list('opapply,u,v);
- if x then res := physop2sq aeval x
- else
- <<
- x:= opmtch!* list('opapply,v,u);
- if null x then
- <<
- !*hardstop := t;
- res:= !*k2q list('opapply,u,v)
- >>
- else res := physop2sq aeval compconj x
- >>;
- >>
- else
- <<
- x := deletemult!* !*collectphysops v;
- for each y in x do
- <<
- v := subst(physopaeval statemult(u,y),y,v);
- if !*hardstop then flg := t;
- !*hardstop := nil;
- >>;
- if flg then !*hardstop := t;
- res := physop2sq v;
- >>
- else
- <<
- x := deletemult!* !*collectphysops u;
- for each y in x do
- <<
- u := subst(physopaeval statemult(y,v),y,u);
- if !*hardstop then flg := t;
- !*hardstop := nil;
- >>;
- if flg then !*hardstop := t;
- res := physop2sq u;
- >>;
- return mk!*sq res
- end;
- symbolic procedure expectval(u,op,v);
- % u and v are states
- % calculates the expectation value < u ! op ! v >
- % tries to apply op first on v, then on u
- % PHYSOPAPPLY is used rather than STATEMULT to multiply
- % resulting states together because of more general definition
- begin scalar x,y,z,flg,res;
- op := physopaeval physopsim!* op;
- if null getphystype op then
- return mk!*sq multsq(physop2sq op,physop2sq physopapply list(u,v));
- if physopp op then
- <<x := physopapply list(op,v);
- if !*hardstop then
- << !*hardstop := nil;
- x:= physopapply list(u,op);
- res := if !*hardstop then mk!*sq
- !*k2q list('opapply,list('opapply,u,op),v)
- else physopapply list(x,v) >>
- else res:= physopapply list(u,x)
- >>
- else if car op eq 'minus then
- res := mk!*sq negsq(physop2sq expectval(u,cadr op,v))
- else if car op eq 'quotient then
- if physopp caddr op then res := expectval(u,physopsm!* op,v)
- else res := mk!*sq quotsq(physop2sq expectval(u,cadr op,v),
- physop2sq caddr op)
- else if car op memq '(dot commute anticommute expt) then
- res := expectval (u,physopsm!* op,v)
- else if car op memq '(plus difference) then
- << for each y in cdr op do
- << x:=nconc(x,list(expectval(u,y,v)));
- if !*hardstop then flg:= !*hardstop ;
- !*hardstop := nil >>;
- if flg then !*hardstop := t;
- res := reval3 ((car op) . x);
- >>
- else if car op eq 'times then
- << x := physopapply list(op,v);
- if not !*hardstop then return physopapply list(u,x);
- x := cdr op;
- while (x and !*hardstop and not flg) do
- << y:=car x; x := cdr x;
- if not getphystype y then << v:= physopapply list(y,v);
- y := v;>>
- else << !*hardstop := nil;
- z:= physopapply list(u,y);
- if !*hardstop then
- << flg := T; x := y . x;
- y := if null cdr x then list('opapply,car x,
- physopaeval v)
- else list('opapply,('times . x),
- physopaeval v); >>
- else << u:= z;
- y:= if null x then v
- else if null cdr x then
- physopapply list(car x, physopaeval v)
- else physopapply
- list(('times . x),physopaeval v) >>
- >>
- >>;
- res := if !*hardstop then mk!*sq !*k2q list('opapply,
- physopaeval u,physopaeval y)
- else physopapply list(u,y);
- >>
- else rederr2('expectval, "invalid args to expectval");
- return res
- end;
- symbolic procedure compconj u;
- % dirty and trivial implementation of
- % complex conjugation of everything (hopefully);
- % not yet tested for arrays
- begin scalar x;
- if null u or numberp u then return u
- else if idp u and (x:=get(u,'rvalue)) then <<
- x:=subst(list('minus,'I),'I,x);
- put(u,'rvalue,x); return u >>
- else return subst(list('minus,'I),'I,u)
- end;
- % -------------- adjoint of operators ---------------------
- physopfn('adj, 'physopadj);
- symbolic procedure physopadj arg;
- begin scalar rht,rhtype,x,n,res;
- rht := physopaeval physopsim!* car arg;
- rhtype := physopp rht;
- if rhtype then return mk!*sq !*k2q physopsm!* adjp rht
- else <<
- if not getphystype rht then res := aeval compconj rht
- else if car rht eq 'minus then
- res := mk!*sq negsq(physop2sq physopadj list(cadr rht))
- else if car rht eq 'difference then res := mk!*sq addsq(
- physop2sq physopadj list(cadr rht),negsq(physop2sq
- physopadj list(caddr rht)))
- else if car rht eq 'plus then <<
- x := for each y in cdr rht collect physopadj list(y);
- res := reval3 ('plus . x) >>
- else if car rht eq 'quotient then <<
- if not getphystype cadr rht then
- rederr2('physopadj, "invalid argument to ADJ")
- else res := mk!*sq quotsq(physop2sq
- physopadj list(cadr rht),physop2sq caddr rht) >>
- else if car rht eq 'times then <<
- x:= for each y in cdr rht collect physopadj list(y);
- res := physoptimes reverse x >>
- else if flagp(car rht,'physopmapping) then
- res := mk!*sq !*k2q list(car rht, physopaeval physopadj cdr rht)
- else res :=physopadj list(physopsim!* rht) >>;
- return res
- end;
- Put('adj,'phystypefn,'getphystypecar);
- symbolic procedure adj2 u;
- begin scalar x,y;
- if not physopp u then rederr2('adj2, "invalid argument to adj2");
- if u = 'unit then return u;
- y:= if idp u then u else car u;
- x := reverse explode y;
- x := intern compress nconc(reverse x,list('!!,'!+));
- put(y,'adjoint,x); %1.01
- put(x,'adjoint,y); %1.01
- put(x,'physopname,x); % 1.02
- if not physopp x then << put(x,'rtype,'physop);
- put(x,'phystype,get(y,'phystype));
- put(x,'psimpfn,'physopsimp);
- put(x,'tensdimen,get(y,'tensdimen));
- defoporder!* := nconc(defoporder!*,list(x));
- oporder!* := nconc(oporder!*,list(x));
- physoplist!* := nconc(physoplist!*,list(x));
- >>;
- if idp u then return x
- else return x . cdr u
- end;
- symbolic procedure invadj u; %new 1.01
- % create the inverse adjoint op
- begin scalar x,y;
- if not physopp u then rederr2('invadj, "invalid argument to invadj");
- if u = 'unit then return u;
- y:= if idp u then u else car u;
- x := reverse explode y;
- x := intern compress nconc(reverse x,list('!!,'!+,'!!,'!-,'!1));
- put(x,'adjoint,get(y,'inverse));
- put(x,'inverse,get(y,'adjoint));
- put(get(y,'inverse),'adjoint,x);
- put(get(y,'adjoint),'inverse,x);
- put(x,'physopname,get(y,'adjoint)); % 1.02
- if not physopp x then << put(x,'rtype,'physop);
- put(x,'phystype,get(y,'phystype));
- put(x,'psimpfn,'physopsimp);
- put(x,'tensdimen,get(y,'tensdimen));
- physoplist!* := nconc(physoplist!*,list(x));
- >>;
- if idp u then return x
- else return x . cdr u
- end;
- symbolic procedure adjp u; %recoded 1.01
- % special cases
- if u = 'unit then u
- else if atom u then get(u,'adjoint)
- else if (car u = 'comm) then
- list('comm,adjp caddr u,adjp cadr u)
- else if (car u = 'anticomm) then
- list('anticomm,adjp cadr u,adjp caddr u)
- else get(car u,'adjoint) . cdr u;
- % --- end of arithmetic routines ---------------------
- % ---- procedure for handling let assignements ------
- symbolic procedure physoptypelet(u,v,ltype,b,rtype);
- % modified version of original typelet
- % General function for setting up rules for PHYSOP expressions.
- % LTYPE is the type of the left hand side U, RTYPE, that of RHS V.
- % B is a flag that is true if this is an update, nil for a removal.
- % updated 101290 mw
- %do not check physop type in prog exprs on the rhs
- begin scalar x,y,n,u1,v1,z,contract;
- if not physopp u and getphystype u then goto c; % physop expr
- u1 := if atom u then u else car u;
- if ltype then
- if rtype = ltype then go to a
- ELSE IF NULL B OR ZEROP V OR (LISTP V AND ((CAR V = 'PROG)
- OR (CAR V = 'COND))) %1.01
- or ((not atom u) and (car u = 'opapply)) then
- return physopset(u,v,b)
- else rederr2('physoptypelet,
- list("physop type mismatch in assignement ",
- u," := ",v))
- else if null (x:= getphystype v) then return physopset(u,v,b)
- else << if x = 'scalar then scalop u1;
- if x = 'vector then vecop u1;
- if x = 'state then state u1;
- if x = 'tensor then tensop list(u1,get(v,'tensdimen));
- ltype := rtype >>;
- A: if b and (not atom u or flagp(u,'used!*)) then rmsubs();
- % perform the assignement
- physopset(u,v,b);
- % phystype checking added 1.01
- if b and (getphystype u neq getphystype v) then
- rederr2('physoptypelet,
- list("physop type mismatch in assignement ",
- u," <=> ",v));
- % special hack for commutators here
- if (not atom u) and (car u = 'comm) then
- physopset(list('comm,adjp caddr u,adjp cadr u),list('adj,v),b);
- if (not atom u) and (car u = 'anticomm) then
- physopset(list(car u,adjp cadr u,adjp caddr u),list('adj,v),b);
- if null (x := getphystype u) or (x = 'state) or (x = 'scalar)
- then return;
- % we have here to add additional scalar let rules for vector
- % and tensor operators with arbitrary indices
- u1:=u;v1:=v;
- if (x eq 'vector) or (x eq 'tensor) then
- << x := collectphysops u;
- for each z in x do
- u1:= subst(insertfreeindices(z,nil),z,u1);
- x := collectphysops v;
- for each z in x do
- v1:= subst(insertfreeindices(z,nil),z,v1) >>;
- physoptypelet(u1,v1,ltype,b,rtype);
- return;
- C:
- % this is for more complicated let rules involving more than
- % one term on the lhs
- % special hack here to handle let rules involving elementary
- % OPAPPLY relations
- if car u = 'opapply then return physopset(u,v,b);
- % step 1: do all physop simplifications on lhs
- % we set indflg!* for dot product simplifications on the lhs
- !*indflg:= T; indcnt!* := 0;
- contract := !*contract2; !*contract2 := T;
- u := physopsm!* u;
- !*indflg := nil; indcnt!* := 0; !*contract2 := contract;
- % check correct phystype
- x := getphystype u;
- y := getphystype v;
- if b and ((not (y or zerop v)) or (y and (x neq y))) then
- rederr2 ('physoptypelet,"phystype mismatch in LET");
- % step 2 : transform back in ae
- u := physopaeval u;
- % write "u= ",u; terpri();
- % ab hier neu
- % step3 : do some modifications in case of a sum or difference on the lh
- if car u = 'PLUS then
- <<
- u1 := cddr u;
- u := cadr u;
- v := list('plus,v);
- for each x in u1 do
- <<
- x := list('minus,x);
- v := append(v,list(x));
- >>;
- >>;
- if car u = 'DIFFERENCE then
- <<
- u1:= cddr u;
- u:= cadr u;
- v := append(list('plus,v),list(u1));
- >>;
- if car U = 'MINUS then
- <<
- u := cadr u;
- v := list('minus,v);
- >>;
- % step 4: add the rule to the corresponding list
- % expression may still contain quotients and expt
- if car u ='EXPT then
- <<
- u := cadr u . caddr u;
- powlis1!* := xadd!*(u .
- list(nil . (if mcond!* then mcond!* else t),
- v,nil), powlis1!*,b)
- >>
- else if car u = 'quotient then
- <<
- v:= list('times,v,caddr u);
- physoptypelet(cadr u,v,ltype,b,rtype);
- >>
- else % car u = times
- <<
- u1 := nil;
- for each x in cdr u do
- <<
- if car x= 'expt then
- u1 := append(u1,list(cadr x . caddr x))
- else if car x = 'quotient then
- <<
- v:= list('times,v,caddr x);
- u1 := append(u1,
- list(if cadr x = 'expt then
- (caddr x . cadddr x)
- else (cadr x . 1)));
- >>
- else u1 := append(u1,list(x . 1));
- >>;
- !*match := xadd!*(u1 . list(nil .
- (if mcond!* then mcond!* else t),
- v,nil), !*match,b);
- >>;
- return;
- end;
- symbolic procedure physopset(u,v,b);
- % assignement procedure for physops
- % special hack for assignement of unresolved physop expressions
- begin
- if not atom u then put(car u,'opmtch,xadd!*(cdr u .
- list(nil . (if mcond!* then mcond!* else t),
- v,nil), get(car u,'opmtch),b))
- else if b then
- if physopp u then put(u,'rvalue,physopsim!* v)
- else put(u,'avalue,list('scalar,
- list('!*sq,cadr physopsim!* v,not !*hardstop)))
- else if not member(u,specoplist!*) then
- << remprop(u,'rvalue);
- remprop(u,'opmtch);
- >>;
- !*hardstop := nil;
- end;
- symbolic procedure clearphysop u;
- % to remove physop type from an id
- begin scalar y;
- for each x in u do <<
- if not (physopp x and idp x) then rederr2('clearphysop,
- list("invalid argument ",x," to CLEARPHYSOP"));
- y := invp x;
- remprop(y,'rtype);
- remprop(y,'tensdimen);
- remprop(y,'phystype);
- remprop(y,'psimpfn);
- remprop(y,'inverse); %1.01
- remprop(y,'adjoint); %1.01
- remprop(y,'rvalue); % 1.01
- oporder!* := delete(y,oporder!*);
- defoporder!* := delete(y,defoporder!*);
- physoplist!* := delete(y,physoplist!*);
- y:= adjp x;
- remprop(y,'rtype);
- remprop(y,'tensdimen);
- remprop(y,'phystype);
- remprop(y,'psimpfn);
- remprop(y,'inverse); %1.01
- remprop(y,'adjoint); %1.01
- remprop(y,'rvalue); % 1.01
- oporder!* := delete(y,oporder!*);
- defoporder!* := delete(y,defoporder!*);
- physoplist!* := delete(y,physoplist!*);
- remprop(x,'rtype);
- remprop(x,'tensdimen);
- remprop(x,'phystype);
- remprop(x,'psimpfn);
- remprop(x,'inverse); %1.01
- remprop(x,'adjoint); %1.01
- remprop(x,'rvalue); % 1.01
- oporder!* := delete(x,oporder!*);
- defoporder!* := delete(x,defoporder!*);
- physoplist!* := delete(x,physoplist!*);
- >>;
- return nil
- end;
- Rlistat '(clearphysop);
- %------ procedures for printing out physops correctly ---------
- % we modify the standard MAPRINT routine to get control
- % over the printing of PHYSOPs
- %**** This section had to be modified for 3.4 **********************
- symbolic procedure physoppri u; % modified 3.4
- begin scalar x,y,z,x1;
- x := if idp u then u else car u;
- y := if idp u then nil else cdr u;
- trwrite(physoppri,"x= ",x," y= ",y,"nat= ",!*nat," contract= ",
- !*contract);
- if !*nat and not !*contract then go to a;
- % transform the physop name in a string in order not to loose the
- % special characters
- x:= compress append('!" . explode x,list('!"));
- prin2!* x;
- if y then << prin2!* "(";
- obrkp!* := nil;
- inprint('!*comma!*,0,y);
- obrkp!* := t;
- prin2!* ")" >>;
- return u;
- a:
- x := reverse explode x;
- if length(x) > 2 then
- if cadr x = '!- then <<z := compress list('!-,'!1);
- x := compress reverse pnth(x,4); >>
- else if car x = '!+ then << z:='!+;
- x:= compress reverse pnth(x,3); >>
- else x := compress reverse x
- else x := compress reverse x;
- x:= compress append('!" . explode x,list('!"));
- x1 := if y then x . y else x;
- trwrite(physoppri,"x= ",x," z= ",z," x1= ",x1);
- % if z then exptpri(get('expt,'infix),list(x1,z))
- % the following is 3.4
- if z then exptpri(list('expt,x1,z),get('expt,'infix))
- else << prin2!* x;
- if y then << prin2!* "(";
- obrkp!* := nil;
- inprint('!*comma!*,0,y);
- obrkp!* := t;
- prin2!* ")" >>
- >>;
- return u
- end;
- symbolic procedure maprint(l,p!*!*); %3.4 version
- begin scalar p,x,y;
- p := p!*!*; % p!*!* needed for (expt a (quotient ...)) case.
- if null l then return nil
- else if physopp l then return apply1('physoppri,l)
- else if atom l
- then <<if not numberp l or (not(l<0) or p<=get('minus,'infix))
- then prin2!* l
- else <<prin2!* "("; prin2!* l; prin2!* ")">>;
- return l >>
- else if stringp l then return prin2!* l
- else if not atom car l then maprint(car l,p)
- else if ((x := get(car l,'pprifn)) and
- not(apply2(x,l,p) eq 'failed)) or
- ((x := get(car l,'prifn)) and
- not(apply1(x,l) eq 'failed))
- then return l
- else if x := get(car l,'infix) then <<
- p := not(x>p);
- if p then <<
- y := orig!*;
- prin2!* "(";
- orig!* := if posn!*<18 then posn!* else orig!*+3 >>;
- % (expt a b) was dealt with using a pprifn sometime earlier than this
- inprint(car l,x,cdr l);
- if p then <<
- prin2!* ")";
- orig!* := y >>;
- return l >>
- else prin2!* car l;
- prin2!* "(";
- obrkp!* := nil;
- y := orig!*;
- orig!* := if posn!*<18 then posn!* else orig!*+3;
- if cdr l then inprint('!*comma!*,0,cdr l);
- obrkp!* := t;
- orig!* := y;
- prin2!* ")";
- return l
- end;
- % ******* end of 3.4 modifications ********************
- % ------- end of module printout -------------------------
- % ------------- some default declarations -------------------
- % this list contains operators which when appearing in expressions
- % have unknown properties (unresolved expressions)
- specoplist!* := list('dot,'comm,'anticomm,'opapply);
- % unit,comm and anticomm operators
- put('comm,'rtype,'physop);
- put('comm,'phystype,'scalar);
- put('comm,'psimpfn,'commsimp);
- put('anticomm,'rtype,'physop);
- put('anticomm,'phystype,'scalar);
- put('anticomm,'psimpfn,'commsimp);
- physoplist!* := list('comm,'anticomm);
- scalop 'unit;
- flag ('(unit comm anticomm opapply),'reserved);
- endmodule;
- end;
|