Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory 旅行推销员在F#_Memory_F#_Mono_Garbage Collection_Xamarin Studio - Fatal编程技术网

Memory 旅行推销员在F#

Memory 旅行推销员在F#,memory,f#,mono,garbage-collection,xamarin-studio,Memory,F#,Mono,Garbage Collection,Xamarin Studio,我的问题不在于算法本身,而在于F#达到极限时的性能。在这个例子中是一个程序,我试图用蛮力解决25个城市的问题(动态规划) (对于一个小例子来说,该算法似乎工作得很好,我相信它能完成任务) 我正在控制台输出窗口中打印一个count变量以监视进度。 正如预期的那样,在第一次迭代到m=12时,运行时间呈指数增长 m=2 1887ms; m=3 1870ms; m=4 1902ms; m=5 2074ms; m=6 2954ms; m=7 6261ms; m=8 16746ms; m=9 38442ms

我的问题不在于算法本身,而在于F#达到极限时的性能。在这个例子中是一个程序,我试图用蛮力解决25个城市的问题(动态规划)

(对于一个小例子来说,该算法似乎工作得很好,我相信它能完成任务)

我正在控制台输出窗口中打印一个count变量以监视进度。 正如预期的那样,在第一次迭代到
m=12
时,运行时间呈指数增长

m=2
1887ms;
m=3
1870ms;
m=4
1902ms;
m=5
2074ms;
m=6
2954ms;
m=7
6261ms;
m=8
16746ms;
m=9
38442ms;
m=10
80396ms;
m=11
140985ms;
m=12
207950ms;
因此,尽管迭代13之前的性能并不出色,但至少它看起来是“可管理的”。事实上,如果我的理解是正确的,迭代12和13是CPU最重的。尽管如此,我还是希望从执行模式来看,该迭代的执行时间大约为300000毫秒,但事实并非如此

在MacOS X 10.11.3 El Capitan上运行的我的(新)iMAC视网膜的控制监视器上缩放,配备3.3Ghz i7四核、16 GB RAM和在Xamarin.Studio 6.0内运行的SSD。我看到程序的内存使用量是一个很大的3 GB。它根本没有经过优化,但它应该在机器的能力范围内,不应该成为负担

m=13
进展非常非常缓慢,以这样的速度计算似乎需要几个小时。在这个阶段,在监视器的CPU端,它表示进程使用了105%的CPU(左边第一列)。1小时后(完成迭代的2/3),它崩溃了,并显示以下消息:

错误:垃圾收集器无法为分配16384字节的内存 主堆部分

我有点惊讶我需要做垃圾收集,因为内存看起来不是主要问题

我正在定义一个巨大的
Array2D
,其中有2^24个条目和24列=17M*24个条目(float32*sbyte),每个条目使用32+8=40位=5字节,因此为2GB

也许这就是问题所在,我在\u size\u m循环的子集\u中为S做了一个

这必须在迭代13时完成2700000次(在1860000时停止),在这个循环中,我对列表进行了一些赋值。也许那里需要垃圾收集

我以前从未在F#中这样做过(仅在R中,它足以不时编写命令
GC()
remove(object)
。在控制监视器中进行监视,与可用RAM相比,内存似乎从来都不是问题?发生了什么

我知道我也许应该找到一个更好的算法,它的内存占用更少,但无论如何,这是了解这个问题的好机会,与其他解决问题的人相比,如果一切按计划进行,执行时间对于第一次(残酷的)尝试来说并不是完全荒谬的

这是源代码

//////// Travelling Salesman problem ////////


open System
open System.Collections
open System.Collections.Generic
open System.IO

open System.Windows

open FSharp.Charting

exception InnerError of string


let stopWatch = System.Diagnostics.Stopwatch.StartNew()

///////////////// preparing the data /////////////////

// format of the files
//[number_of_cities]
//[x_1] [y_1] // coordinate

let x = File.ReadAllLines "/Users/francois-guillaume.rideau/Documents/MOOC/TSP.txt"

let split (text:string)=
    text.Split [|'\t';' '|]

let splitInto2Values (A: string []) =  
    (float A.[0],float A.[1])

let parseLine (line:string) = 
    line
    |> split 
    |> splitInto2Values



let num_cities = int x.[0] // 25

let cities = x |> Array.tail |> Array.map parseLine //  [x_1][y_1] 

let dist_matrix = Array2D.create num_cities num_cities 0.0f
for i in 0..(num_cities-1)do
    for j in 0..(num_cities-1) do
        dist_matrix.[i,j]<- float32 (sqrt  ( (fst cities.[i] - fst cities.[j])*(fst cities.[i] - fst cities.[j]) + (snd cities.[i] - snd cities.[j])*(snd cities.[i] - snd cities.[j]) ))

let arrayOfArrays = [| [| 0.0f; 2.0f;1.0f;4.0f |]; [|2.0f;0.0f; 3.0f;5.0f |]; [|1.0f;3.0f; 0.0f;6.0f |]; [|4.0f;5.0f; 6.0f;0.0f |] |]
let example = Array2D.init 4 4 (fun i j -> arrayOfArrays.[i].[j]) 

// Dynamic programming algorithm

// Subproblems: 
// For every destination j in {1,2,......n} every subset S in {1,2,....n} that contains 1 and j, let
// A(S,j) = minimum length of a path of a path from 1 to j that visits precisely the vertices of S [exactly once each]

// create A = Array2D indexed by subsets S that contain 1 and destinations j
// Base Case A[S,1] = 0 if S = {1} , +infinity otherwise
// for m = 2,3,4,.... n (m = subproblem size)
//     for each Set S in {1,2,...n} of size m that contains 1
//         for each j in S, j different from 1:
//             A[S,j] = min (k in S, k <> j) {A[S-{j},k]+Ckj}
// Return min (j=2 to n) A[{1,2,3,....,n},j]+Cj1

let limit = 100000000.0f

//// the first city is city 0 in array D. we put it apart, 
//// then we represents S as integers. 
//// we take the binary representation of integer, and the pth bit indicates whether city p+1 belongs to S
//// for example S =11 = 1+2+8 contains cities 2,3 and 9 (members 11 will return [(0, 1); (1, 2); (3, 8)])

/////////////////////////////// with path ///////////////////////////////////////////

let TSP_all_c_Dynamic_Programming_with_path_main(D:float32 [,]) = // solves the TSP problem when ALL cities are connected together with an exhaustive search in exponential time O(n^2 2^n)
                                                   // the input is a distance matrix in float32
                                                   // memory usage is not optimized at all....   

    let num_cities = Array2D.length1 D
    let l2 = Array2D.length2 D
    if (l2<>num_cities) then failwith "Distance matrix is not a squared matrix"
    let powers_of_2 = [|1;2;4;8;16;32;64;128;256;512;1024;2048;4096;8192;16384;32768;65536;131072;262144;524288;1048576;2097152;4194304;8388608;16777216|]
    let power2 k =    
       if ((k >= 25) || (k<0)) then raise (InnerError("power exponent not allowed"))
           else powers_of_2.[k]  

    let num_subsets = power2 (num_cities-1)
    let S_full = num_subsets-1 

    let A = Array2D.create num_subsets (num_cities-1)  (limit,-1y)

    A.[0,0]<-(-0.0f,-2y)

    let rec sumbits (n:int):int=
      let rec helper acc m =
         match m with
            | 0 -> acc
            | 1 -> acc+1 // remove this ?
            | _ -> let r = m%2
                   helper (acc+r) (m>>>1)
      helper 0 n

    let hashtable = Array2D.create (num_cities-1) num_subsets false // hashtable.[i-1,n]=true if (sumbits n) = i
    for k in 1..(num_subsets-1) do hashtable.[(sumbits k)-1,k]<-true
    // member returns [(p,2^p);....] if the p+1th city is in S
    let members S = [for j in 0..(num_cities-2) do let a= powers_of_2.[j] &&& S
                                                   if (a<>0) then yield (j,a)] // list length = num_cities-1


    for m in 2..num_cities do // S size m
        printfn "m=%A" m
        let stopWatch = System.Diagnostics.Stopwatch.StartNew()

        let mutable count = 1

        let Subset_of_size_m = hashtable.[m-2,0..] |> Seq.mapi (fun i x -> (i,x)) |> Seq.filter (fun (a,b)-> (b=true)) |> Seq.map fst |> Seq.toList
        for S in Subset_of_size_m do         
            if m = 2 then let (i,S') = (members S).Head
                          A.[S',i]<- (D.[0,i+1],-1y) // distance from 0 to city i+1
                     else
                          let S'_list = List.fold (fun acc x -> let a = (((snd x)^^^S_full)&&&S)             // list of subsets of size m-1
                                                                if a = S then acc else (fst x,a)::acc ) [] (members S)
                          for (j,S') in S'_list do
                              A.[S,j] <- ([for (k,expk) in (members S') do
                                                yield (fst A.[S',k]+D.[j+1,k+1],k) ]|> List.min |> fun (a,b)->(a,sbyte b))// can do faster than that if we remember from above ?
                          count <- count + 1 // to check progress in the console
                          if count%10000 =0 then printfn "count=%A" count

        printfn "%f" stopWatch.Elapsed.TotalMilliseconds

    // printfn "%A" A
    // A.[num_subsets-1,0..]
    A

let calculate_path_TSP_all_c_Dynamic_Programming_with_path (D:float32 [,]) =
    // calls the core subroutine defined above
    let A' = TSP_all_c_Dynamic_Programming_with_path_main D
                                                    // memory usage is not optimized at all....  

    // from here its smooth sailing, just analyzing the results.

    let num_cities = Array2D.length1 D
    let l2 = Array2D.length2 D
    if (l2<>num_cities) then failwith "Distance matrix is not a squared matrix"

    let powers_of_2 = [|1;2;4;8;16;32;64;128;256;512;1024;2048;4096;8192;16384;32768;65536;131072;262144;524288;1048576;2097152;4194304;8388608;16777216|]
    let power2 k =    
       if ((k >= 25) || (k<0)) then raise (InnerError("power exponent not allowed"))
           else powers_of_2.[k]  

    let num_subsets = power2 (num_cities-1)
    let S_full = num_subsets-1 

    let A'' = A'.[S_full,0..]

    let res' = [for i in 0..num_cities-2 do yield (fst A''.[i]+ example.[0,i+1]) ]  |> Seq.mapi (fun i x -> (i, x)) |> Seq.minBy snd
    printfn "TSP answer = %A" res'

    let path = Array.create (num_cities+1) -1y

    let mutable current_city = sbyte (fst res')
    path.[num_cities-1]<- current_city// the last city 

    let mutable current_S = S_full
    let mutable next_S = -2
    let mutable next_city = -2y

    for k in num_cities-2..-1..1 do 
        next_city <- snd A'.[current_S,int current_city]
        next_S <- (S_full^^^powers_of_2.[int current_city]) &&& current_S
        //printfn "k=%A current_S=%A next_city=%A" k current_S next_city
        path.[k]<-next_city
        current_S<-next_S
        current_city<-next_city

    for i in 0..num_cities do path.[i]<-path.[i]+1y
    printfn "path=%A" path  


////// main program /////

calculate_path_TSP_all_c_Dynamic_Programming_with_path dist_matrix
旅行推销员问题//////// 开放系统 开放系统。集合 open System.Collections.Generic 开放系统 开放系统 打开FSharp.Charting 字符串的内部错误异常 让stopWatch=System.Diagnostics.stopWatch.StartNew() /////////////////准备数据///////////////// //文件格式 //[城市数量] //[x_1][y_1]//坐标 设x=File.ReadAllLines“/Users/francois guillaume.rideau/Documents/MOOC/TSP.txt” 让拆分(文本:字符串)= text.Split[|'\t''''.''分割 让splitInto2Values(A:string[])= (浮点A[0],浮点A[1]) 让parseLine(line:string)= 线 |>分裂 |>拆分为2个值 设num_cities=int x[0]//25 让cities=x |>Array.tail |>Array.map parseLine/[x|u 1][y|u 1] 让dist_matrix=Array2D.create num_cities num_cities 0.0f 对于0中的i…(num_cities-1)do 对于0中的j…(num_cities-1)do 距离矩阵[i,j]阵列法拉利[i].[j]) //动态规划算法 //子问题: //对于{1,2,….n}中的每个目标j,{1,2,….n}中包含1和j的每个子集S,让 //A(S,j)=从1到j的路径的最小路径长度,该路径精确访问S的顶点[每个顶点精确访问一次] //创建A=Array2D,由包含1和目标j的子集S索引 //基本情况A[S,1]=0,如果S={1},否则为+无穷大 //对于m=2,3,4,。。。。n(m=子问题大小) //对于大小为m的{1,2,…n}中包含1的每个集合S //对于S中的每个j,j不同于1: //A[S,j]=min(S中的k,kj){A[S-{j},k]+Ckj} //返回min(j=2到n)A[{1,2,3,…,n},j]+Cj1 让限值=100000000.0f ////第一个城市是数组D中的城市0。我们把它分开, ////然后我们将S表示为整数。 ////我们采用整数的二进制表示,第pth位表示城市p+1是否属于S ////例如,S=11=1+2+8包含城市2、3和9(成员11将返回[(0,1);(1,2);(3,8)]) ///////////////////////////////带路径/////////////////////////////////////////// 让TSP_all_c_Dynamic_Programming_与_path_main(D:float32[,])=//解决所有城市在指数时间O(n^2^n)内通过穷举搜索连接在一起时的TSP问题 //输入是float32中的距离矩阵 //内存使用根本没有优化。。。。 设num_cities=Array2D.length1d 设l2=Array2D.length2 D 如果是(l2num_城市),则“距离矩阵不是平方矩阵” 让| 1;2;4;8;16;32;64;128;256;512;1024;2048;4096;8192;16384;32768;65536;131072;262144;524288;1048576;2097152;4194304;8388608;16777216 |] 设power2 k= 如果((k>=25)| |(k acc+1//删除此项? |_u->设r=m%2 助手(acc+r)(m>>>1) 助手0 n 设hashtable=Array2D.create(num_cities-1)num_subsets false//hashtable。[i-1,n]=true如果(sumbits n)=i 对于k in 1..(num_subsets-1)执行哈希表。[(sumbits k)-1,k]Seq.mapi(fun i x->(i,x))|>Seq.filter(fun(a,b)->(b=true))|>Seq.map fst |>Seq.toList