Heute ist es endlich soweit – Dynamics NAV 2009 steht offiziell zum Download (1.2GB) auf PartnerSource bereit. Der Download ist zwar bereits seit Samstag verfügbar, aber aus unbekannten strategischen Gründen war diese Information mal wieder "Partner Confidential" und es wurde darum gebeten nicht vor dem 19.11.2009 darüber zu bloggen. Da die Katze jetzt aber offiziell aus dem Sack ist: "Happy Downloading!" 😉
Weitere Information sind im Launch Portal zu finden.
Tags:
Dynamics NAV 2009,
Navision
Last time I showed how the immutable set implementation in F# can be used to get a immutable sorted list. As a result of using sets, the shown version doesn’t support repeated items. This lack can be wiped out by using an additional dictionary (immutable "Map" in F#) which stores the count of each item.
At first I define two basic helper functions for the dictionary:
module MapHelper =
let addToMap map idx =
let value = Map.tryfind idx map
match value with
| Some(x) -> Map.add idx (x+1) map
| None -> Map.add idx 1 map
let removeFromMap map idx =
let value = Map.tryfind idx map
match value with
| Some(x) ->
if x > 1 then
Map.add idx (x-1) map
else
Map.remove idx map
| None -> map
open MapHelper
Now I can adjust my sorted list implementation:
// a immutable sorted list - based on F# set
type 'a SortedFList =
{items: Tagged.Set<'a,Collections.Generic.IComparer<'a>>;
numbers: Map<'a,int>;
count: int}
member x.Min = x.items.MinimumElement
member x.Items =
seq {
for item in x.items do
for number in [1..x.GetCount item] do
yield item}
member x.Length = x.count
member x.IsEmpty = x.items.IsEmpty
member x.GetCount item =
match Map.tryfind item x.numbers with
| None -> 0
| Some(y) -> y
static member FromList(list, sortFunction) =
let comparer = FComparer<'a>.Create(sortFunction)
let m = list |> List.fold_left addToMap Map.empty
{new 'a SortedFList with
items = Tagged.Set<'a>.Create(comparer,list) and
numbers = m and
count = list.Length}
static member FromListWithDefaultComparer(list) =
SortedFList<'a>.FromList(list,compare)
static member Empty(sortFunction) =
SortedFList<'a>.FromList([],sortFunction)
static member EmptyWithDefaultComparer() =
SortedFList<'a>.Empty(compare)
member x.Add(y) =
{x with
items = x.items.Add(y);
numbers = addToMap x.numbers y;
count = x.count + 1}
member x.Remove(y) =
if x.GetCount y > 0 then
{x with
items = x.items.Remove(y);
numbers = removeFromMap x.numbers y;
count = x.count - 1}
else
x
Tags:
F#,
immutable map vs. dictionary,
immutable set,
immutable sorted list,
red-black trees
F# supports a powerful implementation of immutable lists (see Dustin’s introduction). But for my current work I needed a sorted list and of course I wanted it the F#-way, which means immutable. I didn’t want to reinvent the wheel so I asked my question in the hubFS forum.
It turned out (thanks to Robert) that F# uses red-black trees to give a fast implementation for the immutable set. This means that a set in F# stores all elements in a balanced binary tree and searching for an element costs only O(log n). As a side effect all elements can be visited in the underlying order, which means the set implementation gives a possibility for implementing a sorted list. The only limitation is that a set usually don’t store objects more than once.
The next problem I got, was that my sorted list needs a specific ordering function. The standard F# set implementation uses structural comparison to give an order, which is not the order I need. But Laurent mentioned the Set.Make function in the F# PowerPack. This function creates a new set type for the given ordering function. The only problem with Set.Make is that it was only designed for OCaml compatibility. But with this hint I was able to put all information together and got a nice immutable sorted list implementation for F#:
// wrap orderingFunction as Collections.Generic.IComparer
type 'a FComparer =
{compareF: 'a -> 'a -> int}
static member Create(compareF) =
{new 'a FComparer with compareF = compareF}
interface Collections.Generic.IComparer<'a> with
member x.Compare(a, b) = x.compareF a b
// a immutable sorted list - based on F# set
type 'a SortedFList =
{items: Tagged.Set<'a,Collections.Generic.IComparer<'a>> }
member x.Min = x.items.MinimumElement
member x.Items = seq {for item in x.items do yield item}
member x.Length = x.items.Count
member x.IsEmpty = x.items.IsEmpty
static member FromList(list, sortFunction) =
let comparer = FComparer<'a>.Create(sortFunction)
{new 'a SortedFList with
items = Tagged.Set<'a>.Create(comparer,list)}
static member FromListWithDefaultComparer(list) =
SortedFList<'a>.FromList(list,compare)
static member Empty(sortFunction) =
SortedFList<'a>.FromList([],sortFunction)
static member EmptyWithDefaultComparer() =
SortedFList<'a>.Empty(compare)
member x.Add(y) =
{x with items = x.items.Add(y)}
member x.Remove(y) =
{x with items = x.items.Remove(y)}
Please note that this implementation stores every item only once. Next time I will show a version which allows to store repeated items.
Tags:
F#,
immutable set,
immutable sorted list,
red-black trees
In the first part of this series I showed a naïve algorithm for the Damerau-Levenshtein distance which needs O(m*n) space. In the last post I improved the algorithm to use only O(m+n) space. This time I will show a more functional implementation which uses only immutable F#-Lists and works still in O(m+n) space. This version doesn’t need any mutable data.
/// Calcs the damerau levenshtein distance.
let calcDL (a:'a array) (b: 'a array) =
let n = a.Length + 1
let m = b.Length + 1
let processCell i j act l1 l2 ll1 =
let cost =
if a.[i-1] = b.[j-1] then 0 else 1
let deletion = l2 + 1
let insertion = act + 1
let substitution = l1 + cost
let min1 =
deletion
|> min insertion
|> min substitution
if i > 1 && j > 1 &&
a.[i-1] = b.[j-2] && a.[i-2] = b.[j-1] then
min min1 <| ll1 + cost
else
min1
let processLine i lastL lastLastL =
let processNext (actL,lastL,lastLastL) j =
match actL with
| act::actRest ->
match lastL with
| l1::l2::lastRest ->
if i > 1 && j > 1 then
match lastLastL with
| ll1::lastLastRest ->
(processCell i j act l1 l2 ll1 :: actL,
l2::lastRest,
lastLastRest)
| _ -> failwith "can't be"
else
(processCell i j act l1 l2 0 :: actL,
l2::lastRest,
lastLastL)
| _ -> failwith "can't be"
| [] -> failwith "can't be"
let (act,last,lastLast) =
[1..b.Length]
|> List.fold_left processNext ([i],lastL,lastLastL)
act |> List.rev
let (lastLine,lastLastLine) =
[1..a.Length]
|> List.fold_left
(fun (lastL,lastLastL) i ->
(processLine i lastL lastLastL,lastL))
([0..m-1],[])
lastLine.[b.Length]
let damerauLevenshtein(a:'a array) (b:'a array) =
if a.Length > b.Length then
calcDL a b
else
calcDL b a
I admit the code is still a little messy but it works fine. Maybe I will find the time to cleanup a bit and post a final version.
Tags:
alignment,
Damerau,
damerau-levenshtein,
dna,
dynamic programming,
edit distance,
F#,
Levenshtein algorithm,
Levenshtein distance
Last time I showed a naïve implementation of the Damerau-Levenshtein-Distance in F# that needs O(m*n) space. This is really bad if we want to compute the edit distance of large sequences (e.g. DNA sequences). If we look at the algorithm we can easily see that only the last two lines of the (n*m)-matrix are used. This observation leads to a improvement where we compute the distance with only 3 additional arrays of size min(n,m).
/// Calcs the damerau levenshtein distance.
let calcDL (a:'a array) (b: 'a array) =
let n = a.Length + 1
let m = b.Length + 1
let lastLine = ref (Array.init m (fun i -> i))
let lastLastLine = ref (Array.create m 0)
let actLine = ref (Array.create m 0)
for i in [1..a.Length] do
(!actLine).[0] <- i
for j in [1..b.Length] do
let cost =
if a.[i-1] = b.[j-1] then 0 else 1
let deletion = (!lastLine).[j] + 1
let insertion = (!actLine).[j-1] + 1
let substitution = (!lastLine).[j-1] + cost
(!actLine).[j] <-
deletion
|> min insertion
|> min substitution
if i > 1 && j > 1 then
if a.[i-1] = b.[j-2] && a.[i-2] = b.[j-1] then
let transposition = (!lastLastLine).[j-2] + cost
(!actLine).[j] <- min (!actLine).[j] transposition
// swap lines
let temp = !lastLastLine
lastLastLine := !lastLine
lastLine := !actLine
actLine := temp
(!lastLine).[b.Length]
let damerauLevenshtein(a:'a array) (b:'a array) =
if a.Length > b.Length then
calcDL a b
else
calcDL b a
This version of the algorithm needs only O(n+m) space but is not really "functional" style. I will show a more "F#-stylish" version in part III.
Tags:
alignment,
Damerau,
damerau-levenshtein,
dna,
dynamic programming,
edit distance,
F#,
Levenshtein algorithm,
Levenshtein distance