On Tue, Mar 13, 2012 at 11:24:02AM +0100, Ralf Hemmecke wrote:
> Hi Sergei,
>
> last night I was thinking a bit of a good design for a generic interface
> to any external program not only Haskell.
> [..]
> For the input I see two approaches.
>
> 1) FriCAS basically already gets a collection of strings that contains
> the expression already in a tree form. Then the task would be to turn
> the tree form into an element of the requested type.
>
> 2) FriCAS gets a big string of input, with enough information about
> types. Then the respective type is asked to parse the string where for
> subparts this parsing procedure might (actually should) delegate parts
> of the parsing to "subtypes" of the corresponding type. ("Subtype" is
> somewhat wrong, what I mean is that for example Fraction(Integer)
> delegates part of the parsing to Integer).
>
> I believe that (2) is more flexible, but I somehow get headaches, when I
> think about where to implement the parsing of
>
> gcd(2,3)
>
> if it is known that 2 and 3 are of type Integer? For gcd it might be
> easy to have this implemented in Integer. But what about such functions
> as
>
> zero?(3)
>
> does it belong to Integer or to Boolean or to none of both?
I was going to add to DoCon the class (category) like
class ForAxiom a where forAxiom :: a -> (DomainDescription, String)
Only those data can be transmittedd to Axiom which type has an instance
of ForAxiom.
And its instances are declared in DoCon recursively. For example,
(a contrived code, a draft):
instance ForAxiom Integer where forAxiom n = ("Z", show n)
instance ForAxiom a => ForAxiom (Fraction a)
where
forAxiom (n :/ m) = let (domDescr, nStr) = forAxiom n
(_, mStr) = forAxiom m
in
( "(Fr " ++ domDescr ++ ")",
nStr ++ " " ++ show m )
When a call is passed to Axiom, everything is converted into
a single String.
But this String has full information about the needed concrete Spad
types. DoCon sets this info there only at the run time.
> zero?(3)
>
> does it belong to Integer or to Boolean or to none of both?
If DoCon needs to pass some (isZero x) to Axiom, it will first apply
forAxiom x
This returns (domainDescriptionForAxiom, stringForAxiom).
In particular, if it has 3 :: Integer, the result will be
("Z", "3").
If 3 :: UPol Integer, then the result occurs
( "(UP x Z)", "[0] [3]" ).
This is done automatically, due to the above particular `instance'
declarations added to DoCon.
For a _call_, DoCon needs to add the result domain description.
It is "Boolean".
It needs to add the function name. It is "zero?".
It also needs to add possible package description.
As it already has ( "(UP x Z)", "[0] [3]" ) (for a polynomial),
will ["zero?", "(UP x Z)"] do ?
I mean that parseCall in Spad will parse this to
(zero? $ UP(x, INT)).
Will this do?
For each particular difficult (for DoCon) function
(factor, gcd, primaryDecomposition, integrate ... -- about 50 of them)
and for each particular signature made by forAxiom,
DoCon needs to decide individually (for possible 50 function names):
which package to call it from, or may be to skip a package, or may
be, to rewrite application differently.
For example, instead of "zero?(f)", it could send to Axiom
"f = (0 :: (UP x Z))."
> And "groebner"? That usually lives in a package and is not attached
> to any domain.
But how do you call it from a package without specifying a domain?
I expected that to call it, one writes a thing like, for example,
groebner(fs) $Groebner( POLY(..., Fraction INT, ...) )
-- correct this line, if needed, please.
Is this so?
If yes, then my forAxiom and parseCall are going to do the string
forming and it parsing and its applying like this.
> If one doesn't want to write another Interpreter for all expressions
> then the really simplest way is to embellish the input string with all
> type information and let the FriCAS interpreter do the parsing work.
>
> (1) -> Z := Integer
> [..]
> (5) -> x: P := monomial(1$Q,1$N)$P
>
> (5) ?
> Type:
> SparseUnivariatePolynomial(Fraction(Integer))
> (11) -> p:P := ((3::Q*x^(4@NP))$P + (((-7::Z)/(4::Z))$Q*x)$P)$P
> 4 7
> (11) 3? - - ?
> 4
> Type:
> SparseUnivariatePolynomial(Fraction(Integer))
>
> Actually, I would have been more happy if the interpreter understood the
> following
>
> p:P := ((3@Q*x^(4@NP))$P + (((-7@Z)/(4@Z))$Q*x)$P)$P
> [..]
I knew of this possibility to apply Interpreter to an easy input.
But consider an average polynomial f : Rational[x,y,z] consisting of 20
monomials.
I think that its parsing - computation by interpreter is much slower
than by my intended parseCall. Because it is an interpreted loop,
while parseCall is a pre-compiled Spad function.
I need to finish parseCall -- a draft version, and then to see its
performance.
May be, it will occur better with using Interpeter. So far, I somehow do
not like to use Interpretr for this.
> program to FriCAS means to *construct* the FriCAS internal datastructure
> again and again. So unless you don't keep the fricas session open and
> refer to previously computed data, that is probably a big waste of time,
> in particular if the function you want to compute with FriCAS takes only
> milliseconds.
Of course, I thought of this.
I always had a gretat doubt about the String Interface of Haskell to Axiom.
The thing is half-dead from the very start.
But consider the following approach.
1.
Suppose that one needs to call
Q := Fraction INT; P := POLY([x,y,z], Q)
f_1 : P := ...
...
f_6 : P := ...
groebner([f1, ..., f6]) $Groebner(P)
In this example, parseCall will parse
* once -- the domain INT,
* once -- the domain Q,
* once -- the domain P.
And these 3 domains are re-used as ready in parsing each f_i and each
coefficient in f_i.
It is good when there are few domains and many elements.
2.
parseCall is applied in the interpreted loop in fifoFromA.input.
I think of adding an argument domainTable
label -> (domain, domain description)
to parseCall.
parseCall will accumulate this table, and return it as a part of the
result.
This domainTable part may not be sent to DoCon. It will be used in the
next call of parseCall.
Any DoCon function which uses the interface will need an additional
argument for the table of these domain descriptions.
`forAxiom' also needs to have this additional argument.
And it will set to the sent string the labels for known domains insted
of their full descriptions.
By such a label, parseCall will extract a domain from the table
accumulated by previous calls (binary search or, may be, an array).
I kept this in mind, but I do not know, may be this will brake when
considered closely for implementation.
The thing looks problematic and messy.
> So one should really think what the actual goal of a Haskell-FriCAS
> connection is. Is it
>
> (a) Let the user only see Haskell (DoCon) and do FriCAS computations in
> the background, or
>
> (b) give a Haskell user a way to drive a fricas session with a Haskell
> "look & feel"?
>
> I think both these options have been tried in Sage already. I have the
> feeling they are not a big success there.
I doubt whether DoCon can do any better.
So far, I just do a certain attempt.
Currently I think -- it is (a).
And (b) can be partially expressed by the above approach with the domain
table.
Thank you for your notes,
------
Sergei
[email protected]
--
You received this message because you are subscribed to the Google Groups
"FriCAS - computer algebra system" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/fricas-devel?hl=en.