Domain Transformations

Post on 26-Jun-2015

181 views 0 download

Tags:

Transcript of Domain Transformations

Dmitri Nesterukdmitrinesteruk@gmail.com

@dnesteruk

DOMAIN TRANSFORMATIONS

Programming tasks can be

Challenging – unique problems and algorithmsDistinctly average – typical ‘working to spec’ Mind-numbingly boring – obvious stuff , manual

translation

1-to-1 translation from one domain/format to another is boring, wasteful and should (where possible) be automated.

In my case:Math in Word/MathTypeCalculations in Excel

LEVELS OF CHALLENGE

XML-like notation Tags denote mathematical

constructs Special HTML entities used

for mathematical symbolsTwo varieties

Content (uncommon, easier to interpret, constrained)

Presentation (harder to interpret, noisy, much more common)

Supported by Word, MathType, Mathematica, Maple, etc.

<mml:math> <mml:mi>a</mml:mi> <mml:msup> <mml:mi>x</mml:mi> <mml:mn>2</mml:mn> </mml:msup> <mml:mo>+</mml:mo> <mml:mn>2</mml:mn> <mml:mi>x</mml:mi></mml:math>

MATHEMATICAL MARK-UP LANGUAGE

Discriminated union Mutually recursive No tag attributes

Union case contains Constant

Mn(42) String literal

Mi("sin") Expression tuple

e.g. Mfrac(Mn(1),Mn(2))

Expression liste.g. Mtd([…])

type Expression = | Math of Expression list | Menclose of Expression list | Mrow of Expression list | Mi of string | MiNormal of string | Mo of string | Mtd of Expression list | Mtr of Expression list | Mn of string | Mroot of Expression * Expression | Mfrac of Expression * Expression | Msub of Expression * Expression | Msup of Expression * Expression

(etc.)

PARSING MATHML

1. Precompute each union case constructor into a maplet cases = Refl ection.FSharpType.GetUnionCases (typeof<Expression>) |> Array.map(fun f -> (f.Name, Refl ection.FSharpValue.PreComputeUnionConstructor(f))) |> Map.ofArray

2. Parse text as XML Use a preamble to wire up MathML DTDs

3. Try to recursively create each case let ctor = cases.Item name (ctor parameters) :?> Expression For 1..3 parameters, we

Try it as a tuple first; and If failed, try as a list

4. If failed, substitute a 0 (zero) with a comment0 (* sorry, supporting integrals is just too hard *)

PARSING ALGORITHM

42Depends on user

type42.0f (single)42.0 (double)42.0M (decimal)

Attempt to parse eng. notationE.g.

CONSTANT

Mn(42)

𝜋User has to hint if

π is a variable or 3.14Math.PI

Constant calculations not precomputed Math.PI/2.0

User can avoid Greek identifiers rho

SYMBOLS

Mi(“π”)

e, E or &ExponentialE;

Different representationsSome apps use ⅇ

Again, user has to hint if it’s constant

Also, Math.Exp(x)

MORE SYMBOLS!

Mi(<any ‘e’>)

abc No perfect solution

User can hint if vars are all single-letter

May need to inject multiplicationsa*b*c

IMPLIED MULTIPLICATION

Mi(“a”) :: Mi(“b”) :: Mi(“c”)

Mi(“abc”)

𝑥2 , 𝑥𝑛 , 𝑥32We use

_ for subscript__ for superscript

Outputx*xMath.Pow(x, n)x_3__2

SUBSCRIPTS AND SUPERSCRIPTS

Use <msub> and <msup>

𝑎𝑥6+𝑏𝑥3Math.Pow

ineffi cient for integral powers

If power is integralUser can inline up to some threshold x*x*x

Custom function with multiplications My.IntPow(x,8)

POWER INLINING

Msup(Mi(x),Mn(6))

cheaper than pow

reduced by a pow

POWER INLINING IDEAS

sin 2 𝑥MiNormal is

synthetic <mi

mathvariant=normal>

Function tablesMath.Sin

Magic function application operator

Some functions will be missingLeave as-is

FUNCTIONS

Mrow( MiNormal(“sin”) :: Mo() :: Mn(2) :: Mi(“x”))

faster but confusing

speed of div ≈ sqrt

where

Precalculation

Const caches E.g., etc.

Subexpression extraction

POSSIBLE OPTIMIZATIONS

Add, Sub Mul Div,

Sqrt Pow

Discriminated union Much easier code structuring

Pattern matching More concise, constrained switch statement

| "E" | " " | "e" when settings.EIsConstantⅇ Identify complex patterns

| Mo(op) :: (UnitOfMeasureBraces(units) as uu) :: t

Partial/recursive patterns Help us get rid of ‘noise’, e.g. <mrow> let rec (|Simple|_|) = function | SimpleAndPhysical x -> Some x | Mrow(content) -> match content with | Simple h :: [] -> Some h | _ -> None | _ -> None

Custom operators let (<@>) (dictName:Map<_,_>) keyName = if dictName.ContainsKey keyName then dictName.[keyName] else keyName

WHY F#?

The Good

Drastically saves time

Reduces programmer error

Performs optimizations!

The Bad

Easy to break, lots of special cases

Doesn’t support some common constructs, e.g.

RESULTS

Same idea butGot an existing

parser (C#)Better structuredAnalysis in C# (ugly)

More scope>1 available calculation

Web ServicesUI abstraction

Excel

C#, F#NMath

Code Web Svc

C++Boost

iPadapps

AND WHAT OF EXCEL?

THE END

ASK QUESTIONS OR I’LL LEAVE

My domain transformers: MathSharp: http://activemesa.com/mathsharp X2C (Excel to Code) : http://activemesa.com/x2c

Contacts dmitrinesteruk@gmail.com @dnesteruk Skype: dmitri.nesteruk