Subversion Repositories wimsdev

Compare Revisions

Ignore whitespace Rev 18202 → Rev 18203

/trunk/wims/public_html/scripts/oef/analyse/factorpolynome
1,108 → 1,402
!! this file is an annexe for anstype litexp (or other)
!! it look if wims_read_parm is a factorised polynome of Z[X]
!! each factor as to be simplified as describe in file expandpolynome of this directory
!!
!! error checked (for factor):
!! - notcomplete : a factor is not completely factorised
!! - multifactor : a factor is repeated instead of using power
!! - twofactorcst : the constant factor is not calculated (in case of non use of optionword factorcontent)
!! - factorcontent : content of the polynome is not factorised (in case of use of optionword factorcontent)
!! - notfactorised : expression is not a product
!! - usedivide : use of symbol /
!! this file is an annex for anstype litexp (or other)
!! some debugging information is stored in variable debuginfo, may be erased in a few months after 2024.05.01
!! see documentation at end of file
 
debuginfo=Analyse de $wims_read_parm
!if factorcontent notwordof $(replyoption$i)
debuginfo=$debuginfo sans factorcontent
!else
debuginfo=$debuginfo avec factorcontent
!endif
allowedchar=!text mark (,),*,^,-,+,0,1,2,3,4,5,6,7,8,9,a,b,c,d,f,g,h,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,F,G,H,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z in $wims_read_parm
!! due to rawmath, only x,y,z are accepted letters
!!allowedchar=!text mark (,),*,^,-,+,0,1,2,3,4,5,6,7,8,9,x,y,z,X,Y,Z in $wims_read_parm
badpositions=!positionof char 0 in $allowedchar
!if $badpositions!=$empty
badposition=!item 1 of $badpositions
badchar=!char $badposition of $wims_read_parm
wrong=badform usebadchar $badchar
!endif
debuginfo=$debuginfo $wrong
pg=!char 1 of ()
pd=!char 2 of ()
!!********** wims_read_parm is rawmath-formated user's answer
nb=!charcnt $wims_read_parm
!distribute item 0,1,0 into par,flag,par2
!reset factor lfactors notfactor exp content
!reset factor lfactors exp content lcontent flagpard
operand=!exec maxima op($wims_read_parm)
wrp=!replace - by +2* in $wims_read_parm
!!********** partly avoid maxima's evaluation before op (^^ not simplified)
wrp=!replace internal * by ^^ in $wrp
operand=!exec maxima op($wrp)
operand=!replace internal ^^ by * in $operand
debuginfo=$debuginfo operande=$operand
k=1
!while ($k<=$nb and $wrong=$empty) or $factor!=$empty
!!********** read string until end or error
!while ($k<=$nb and $wrong=$empty) or $factor!=$empty
c=!char $k of $wims_read_parm
!if ($c=* and $par=0) or $k>$nb
cc=!char $[$k+1] of $wims_read_parm
debuginfo=$debuginfo\
$c
!!********* condition to decide that the end of the factor is attained
!if $k>$nb or ($c=* and $par=0 and ($pg isin $wims_read_parm or $operand!="+"))
debuginfo=$debuginfo factor=$factor, exp=$exp
!if $factor!=$empty
!if $mpar2>0
wrong=badform fparenthesis $factor
!break
!else
!!********* test to decide if factor contains a variable (NaN), then factorize it via pari (gets only polynomial factors, not the content, ex : 2x^2-2 --> factor= x+1,1 ; x-1,1 )
!if $[$factor*1]=NaN
tmp=!exec pari factor($factor)\
content($factor)
!distribute line $tmp into t1,t2
t1=!replace internal -1,1; by $empty in $t1
debuginfo=$debuginfo il contient une variable,
!!********* The old line about content is now useless because we test below that factor is irreducible (hence without content)
!!********* if factor is a power, remove the power (use maxima op, hence first remove - sign, replace temporarily by unused letter e)
Nfactor=!replace - by +e in $factor
foperand=!exec maxima op($Nfactor)
!if $foperand="^"
factor=!exec maxima part($Nfactor,1)
factor=!replace +e by - in $factor
factor=!replace e by - in $factor
exp=!exec maxima part($Nfactor,2)
exp=!replace +e by - in $exp
exp=!replace e by - in $exp
debuginfo=$debuginfo (factor=$factor, exp=$exp)
!endif
t1=!exec pari factor($factor)
debuginfo=$debuginfo pari donne la factorisation $t1
!!********* The old line "!replace internal -1,1; by $empty" is removed, because useless (since pari gives only non constant factors, hence never (-1)^1), and even inappropriate if factorization is x-1,1.
tt1=!rowcnt $t1
!if $tt1!=1 or $t2!=1
!!********* Check that current factor is irreducible (equal up to sign to unique factor of its pari-factorization). Content check is useless.
prime=!item 1 of $t1
exp=!item 2 of $t1
isirred=!exec maxima expand((($prime)-($factor))*(($prime)+$factor))
debuginfo=$debuginfo $factor prime=$prime isirred=$isirred
!if $tt1!=1 or $isirred!=0
wrong=badform notcomplete $factor
!endif
!if $wrong=$empty
debuginfo=$debuginfo notcomplete
!else
!!********* If current factor not correctly expanded, this is reported in variable wrong by file expandpolynome.
!read oef/analyse/expandpolynome $factor
debuginfo=$debuginfo on teste via expandpolynome
!endif
tmp1=!item 1 of $t1
!if $tmp1 isitemof $lfactors
wrong=badform multifactor $tmp1
!!********* send error if current factor is already in list, add it otherwise
!if $prime isitemof $lfactors
wrong=badform multifactor $prime
!else
lfactors=!append item $tmp1 to $lfactors
lfactors=!append item $prime to $lfactors
!endif
!else
debuginfo=$debuginfo il est numérique
!if factorcontent notwordof $(replyoption$i)
!!********* When no option factorcontent, check that the current numerical factor is the first one (only one is allowed), and not equal to 1
!if $content!=$empty
wrong=badform twofactorcst $content $factor
!endif
!default exp=1
!if $[($factor)^$exp]=1 and $[$$wims_read_parm]!=1
wrong=badform uselessfactor
!break
!endif
content=$factor
!else
!!********* When option factorcontent, we check that the current numerical factor has only one prime factor (apart sign)
tmp=!exec pari factor($factor)
tmp=!replace internal -1,1; by $empty in $tmp
tt1=!rowcnt $tmp
!if $tt1!=1
wrong=badform factorcontent $factor
!else
!default exp=1
debuginfo=$debuginfo factor^exp= $factor^$exp=$[($factor)^$exp]
!if $[($factor)^$exp]=1 and $[$$wims_read_parm]!=1
wrong=badform uselessfactor
!break
!endif
premier=!item 1 of $tmp
!if $premier=matrix(0,2)
premier=1
!endif
premierf=!replace \^.* by in $factor
!if ($premier!=$premierf) and (-$premier!=$premierf)
debuginfo=$debuginfo premier=$premier, premierf=$premierf
wrong=badform factorcontent $factor
!endif
!if $premier isitemof $lcontent
wrong=badform multifactor $premier
!else
lcontent=!append item $premier to $lcontent
!endif
debuginfo=$debuginfo tmp=$tmp lcontent=$lcontent
!endif
!endif
!endif
!reset factor exp
!reset factor exp flagpard
mpar2=0
!endif
!endif
flag=1
!else
!if $c isin +- and $par=0 and $factor!=$empty
debuginfo=$debuginfo factor=$factor exp=$exp par=$par par2=$par2 mpar2=$mpar2 wrong=$wrong c=$c
!!********** condition on pg because x-1 or 2x-1 alone is a correct factorization.
!if $c isin +- and $par=0 and $factor!=$empty and $pg isin $wims_read_parm
debuginfo=$debuginfo notfactorised $k
wrong=badform notfactorised $k
factor=
!else
!if $c=/
wrong=badform usedivide
!else
!if $c notin ()
!if $c=^
exp=0
!if $c notin ()
!if $c=^
exp=0
flagexp=1
!if $flagpard=$empty
factor=$factor$c
!endif
!else
!if $exp=$empty
debuginfo=$debuginfo ajout de $c
factor=$factor$c
!else
!if $exp=$empty
!if ($c isin 0123456789)
!if ($flagexp=1)
exp=$exp$c
!endif
!else
flagexp=0
!endif
!!********** we continue the construction of current factor
!if $flagpard=$empty or $operand="+"
debuginfo=$debuginfo encore ajout de $c
factor=$factor$c
!else
exp=$exp$c
!endif
!endif
!endif
!else
!if $c=$pg
!if $flag=0 or $par>0
!increase par2
mpar2=$par2
!endif
!if (($par>0 or $par2>0) and $exp=$empty) or $operand="+"
debuginfo=$debuginfo on ajoute $c
factor=$factor$c
!endif
!increase par
flag=1
!else
!if $c=$pg
!if $flag=0 or $par>0
!increase par2
mpar2=$par2
!endif
!if ($par>0 or $par2>0) and $exp=$empty
factor=$factor$c
!endif
!increase par
flag=1
!else
par=$[$par-1]
!if ($par>0 or $par2>0) and $exp=$empty
factor=$factor$c
!endif
!if $par2>0
par2=$[$par2-1]
!endif
flag=0
debuginfo=$debuginfo pardroite
flagpard=1
!if $mpar2>0
mpar2=$[$mpar2-1]
par2=$[$par2-1]
!endif
par=$[$par-1]
!if (($par>0 or $par2>0) and $exp=$empty) or $operand="+"
factor=$factor$c
!endif
debuginfo=$debuginfo envoi pour test de $factor
!if $par2>0
par2=$[$par2-1]
!endif
flag=0
!endif
!endif
!endif
!endif
!increase k
debuginfo=$debuginfo\
endwhile $c $k/$nb, wrong=$wrong, factor=$factor
!endwhile
 
!exit
 
 
!if $wrong!=$empty
!!debug $debuginfo\
sortie avec wrong=$wrong
!endif
 
 
 
Nothing is read by wims after this point, it is just here for information
To debug this file, put the !exit command 5 lines below.
 
Documentation
-------------
 
This file checks whether wims_read_parm is a factorized polynomial of Z[X] (or any variable except e,E,i,I),
each factor being simplified as described in file expandpolynome of this directory.
It assumes that wims_read_parm has been formated by the rawmath function (as is done in the file litexp),
so is presented with * between factors and without spaces.
 
errors checked (for factor):
- notcomplete : a factor is not completely factorised
- multifactor : a factor is repeated instead of using power
- twofactorcst : the constant factor is not unique (when no option factorcontent)
- factorcontent : content of the polynome is not factorized (when option factorcontent)
- notfactorised : expression is not a product
- usebadchar : forbidden characters used in polynomial (like /.eEiI) the letters e,E,i,I have a numerical value when wims calls pari
- uselessfactor : factor has value 1 (not always checked)
- fparenthesis : factor contains a parenthesis
 
some variables :
par is number of not yet closed left parenthesis when scanning the expression
mpar2 is maximal number of parentheses attained in the factor (should be 0 if simplified)
lfactors is current list of non constant irreducible factors
content is empty until some constant factor is found (used when no option factorcontent)
lcontent is current list of constant prime factors (used when option factorcontent)
exp is the exponent (number following ^)
flagpard used to decide whether exp is part of factor itself.
allowedchar is the list of allowed characters in the expression.
e,E,i,I should be forbidden because they have numerical value in pari factorization.
Letters other than x,y,z are considered as function names by rawmath when in front of a left parenthesis. Hence x(x+1) and (u-1)(u+1) are ok as polynomials, but not u(u+1).
Since some exercises (H2/algebra/OEFevalwimslitt.fr) already use letter b, all letters except e,i are allowed, but the documentation should mention this behavior :
it is not safe to use letters other than x,y,z in the good answer if it is not given in machine-understandable format.
We could change this behavior via a new option (strictvar, to limit variable names to x,y,z).
Users might be tempted t use / or . because they are common (ex : 15.0/3*x^2) but fthey are forbidden because too difficult to treat in this file.
 
How does it work?
- We first check there are only allowed characters in the expression
- Then we read the string character by character, to find the factors. Because the input comes from rawmath, the factors are separated by a *.
Hence the general idea is that a factor ends when it is followed by a *, except if we are inside a pair of parentheses : 2 is a factor in 2*(x+1) but not in 3*(2*x+1)
But this is not always correct : 2 is not a factor in 2*x+1 or 2*(x+1)*(x+2)-1. In general it is not possible to be sure that a factor ends before we read the entire expression (and write it as a tree).
This is why we use the maxima "op" operator (which does the tree job), to know if the entire expression is a sum or a product. If it is a sum, the only factor is the entire expression.
We have to cheat to use op because maxima evaluate op's argument : (-1)*(x-1) is a sum.
If it is a product, we apply the general idea above.
- Once we have found a factor, we treat separately the cases of a nonconstant or constant factor :
- for nonconstant factor (NaN), check that it is irreducible (equal up to sign to unique factor of its pari-factorization), correctly expanded (using file expandpolynome) and new (not in lfactors).
- for constant factor, separate in 2 cases depending on option factorcontent :
- without option factorcontent check that it is new and not of value 1.
- with option factorcontent check that it is primary, power of a new prime, and not of value 1.
- As soon as some error is found, it is stored in the variable wrong and we exit
 
 
 
 
To check this file, try the following exercise, with 6*(x-1)*(x+1) replaced by any other polynomial in machine understandable format.
You may try natural format (like 6(x-1)(x+1)) for user's answer
 
\text{P=6*(x-1)*(x+1)}
\statement{Factorize P=\P}
\answer{without option factorcontent }{\P}{type= litexp}{option=polfactor}
\answer{with option factorcontent}{\P}{type= litexp}{option=polfactor,factorcontent}
 
 
We comment here some examples for P, depending on option factorcontent (yes,no,any)
 
 
Correctly accepted :
 
P factorcontent remarks
1 any
-2 any
-x any
-2x any
8x no
2^3x yes
-8x no
-2^3x yes
x^3 any
-x^3 any
x^(3) any
2(x-1) any
(x-1)2 any
(x-1)^2 any
-(x-1)^2 any
x^2+1 any bug in original : blocked
x^2+x+1 any bug in original : blocked
2x(1-x)(x+1) any
y(y+1) any
a-1 any bug in original : blocked
-1(1-a) any
-(1-a) any
-(x-1) any
 
 
 
Correctly blocked :
 
P factorcontent reason remarks
4-2 yes factorcontent 4-2
8x yes factorcontent 8 bug in original : accepted
2*2*2*x no twofactorcst 2 2
2*2*2*x yes multifactor 2 bug in original : accepted
-2*2 no twofactorcst -2 2
-2*2 yes multifactor 2 bug in original : accepted
2^3 2^2x no twofactorcst 2^3 2^2
2^3 2^2x yes multifactor 2 bug in original : accepted
(-1)(x-1)(x+1)(-1) no twofactorcst -1 -1
(-1)(x-1)(x+1)(-1) yes multifactor -1 bug in original : accepted
(-1)(x-1)(x+1)((-1)) no twofactorcst -1 (-1)
(-1)(x-1)(x+1)((-1)) yes multifactor -1
(x^2-1) any notcomplete (x^2-1) bug in original : accepted
x^2-1, -2x(x^2-1) any notcomplete x^2-1 bug in original : bad reasons
2.0*x any usebadchar . different reason in original (accepted if no)
2?0*x any usebadchar ? exercise error in original
2/1*x any usebadchar / usedivide in original
2*x-1*1 any notreduced termenumsimp -1*1
2x(1-x)2(x+1) no twofactorcst 2 2
2x(1-x)2(x+1) yes multifactor 2 bug in original : accepted
2x(1-x)1(x+1) any uselessfactor
(-1)^2(x-1)(x+1) any uselessfactor accepted in original
2*x*3^0 any uselessfactor
x^2+2x+1 any notcomplete x^2+2*x+1 bad reason in original
x(x^2+2x+1) any notcomplete x^2+2*x+1 bad reason in original
2(x+1)-1 any notfactorised 8
(x+1)x(x+1) any multifactor x+1
(x+1)(-1-x) any multifactor x+1
-2(1-x)(x^2+x+1-x^2)x any notreduced termesamepower x^2,-x^2 bad reason in original
(x+1)^3*(x+1)^(-1) any multifactor x+1 different reason in original
-14y(-11y+15)+2y(-11y+15) no notfactorised 17
6x(x-1)+1 no notfactorised 10
6x(x-1)+1 yes factorcontent 6
2*(1+(x+1)) any notreduced parenthesis
 
 
Correctly blocked, but for bad reason (bug) :
P factorcontent reason remarks
(x-1)*1 any notreduced parenthesis
x^(2x+1) any notcomplete x^2*x+1 P is not a polynomial, factor is wrong
x^2*x+1 any notcomplete x^2*x+1 bad reason in original
3^(2+1) yes factorcontent 3^2+1 factor is wrong. Accepted in original
-14y(-11y+15)+2y(-11y+15) yes factorcontent -14
 
 
 
Wrongly accepted (bug):
 
P factorcontent
 
 
Wrongly blocked (bug):
 
P factorcontent reason remarks
 
 
 
Accepted, but not sure it is what we want
 
P factorcontent remarks
2^3x no the constant factor is not computed, but still accepted.
(-1)^3x any correct but not simplest form
3^(2+1) no constant not completely computed
4-2 no constant not completely computed. Blocked in original
2^(1+0) any
3^(7+7)x no clearly not simplest form
(2) any compare with (x+1) which is blocked
(x) any compare with (x+1) which is blocked
b^(3-3)*(a-1) any the letter b is not in the good answer.
(b-1)^(3-3)*(a-1) any blocked in original
 
Blocked, but not sure it is what we want
 
P factorcontent reason remarks
(x+1) any notreduced parenthesis accepted in original (better?)
 
 
 
Yet to be tested
P factorcontent reason remarks
 
 
known bugs :