Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.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 在erlang中生成幻方时内存消耗过多-需要帮助进行优化_Memory_Optimization_Erlang_Magic Square - Fatal编程技术网

Memory 在erlang中生成幻方时内存消耗过多-需要帮助进行优化

Memory 在erlang中生成幻方时内存消耗过多-需要帮助进行优化,memory,optimization,erlang,magic-square,Memory,Optimization,Erlang,Magic Square,对于大学,我必须实现一个算法,为给定的边长度和特定的和创建所有可能的幻方。对于n=3,算法按预期工作。但是,当生成n=4的所有幻方时,过了一会儿,我的内存就用完了。任务描述中已提到此问题。我已经尝试过优化a代码,但它仍然不能正常工作。所以我希望有人能给我一些建议 我的基本想法是:首先,我生成所有可能的行,这些行可以与给定的数字一起使用,然后我试图以一种完全满足幻方限制的方式组合这些行。这是通过回溯实现的。我认为问题在于函数makeRows在存储所有行时会消耗太多内存 如果你需要更多的代码解释,我

对于大学,我必须实现一个算法,为给定的边长度和特定的和创建所有可能的幻方。对于n=3,算法按预期工作。但是,当生成n=4的所有幻方时,过了一会儿,我的内存就用完了。任务描述中已提到此问题。我已经尝试过优化a代码,但它仍然不能正常工作。所以我希望有人能给我一些建议

我的基本想法是:首先,我生成所有可能的行,这些行可以与给定的数字一起使用,然后我试图以一种完全满足幻方限制的方式组合这些行。这是通过回溯实现的。我认为问题在于函数
makeRows
在存储所有行时会消耗太多内存

如果你需要更多的代码解释,我可以给你

magicSquare(N, Value) ->
    Squares = buildSquare(N, makeRows(N, N*N, Value, N)),
    io:fwrite("Squares ready"), io:fwrite("~n"),
    Result = lists:filter(fun(X) -> testsquare(X, N, Value) end, Squares),
    io:write(length(Result)),
    Result.

buildSquare(0, _) -> [[]];
buildSquare(Rows, AvailableRows) ->
    [ [X|L] || L <- buildSquare(Rows-1, AvailableRows), X <- AvailableRows, onlyUniqueNumbers(lists:flatten([X|L]))].

onlyUniqueNumbers(List) -> erlang:length(List) == sets:size(sets:from_list(List)).

%produces all possible rows with a dimension of Fields and the Numbers from 1 to Numbers and the right sum for each row
makeRows(0,_,_,_) -> [[]];
makeRows(Fields, Numbers, Value, TargetLength) ->
    [ [X|L] || X <- makeRows(Fields-1, Numbers, Value, TargetLength), L <- lists:seq(1,Numbers), checkRow([X|L], TargetLength, Value)].

checkRow(Row, Length, Value) when length(Row) < Length -> true;
checkRow(Row, Length, Value) ->
    Sum = lists:sum(Row),
    if Sum == Value -> true;
    true -> false
    end.

testsquare(Square, N, Value) -> checkAllDiagonal(Square, Value) andalso checkAllHorizontal(Square, Value) andalso checkAllVertical(Square, N, Value).

checkAllHorizontal([H|T], Value) ->
    case checkHorizontal(H, Value, 0) of
        true -> checkHorizontal(lists:nth(1, T), Value, 0);
        false -> false
    end;
checkAllHorizontal([], Value) -> true.

checkHorizontal([H|T], Value, Summe) -> checkHorizontal(T, Value, Summe + H);
checkHorizontal([], Value, Summe) when Summe == Value -> true;
checkHorizontal([], Value, Summe) -> false.

checkAllVertical(Square, N, Value) -> checkAllVertical(Square, N, Value, 1).
checkAllVertical(Square, N, Value, Column) ->
    if
        Column > N -> true;
        true ->
            case checkVertical(Square, Value, 0, Column) of
                true -> checkAllVertical(Square, N, Value, Column + 1);
                false -> false
            end
    end.

checkVertical([], Value, Summe, Column) when Summe == Value -> true;
checkVertical([], Value, Summe, Column) -> false;
checkVertical([H|T], Value, Summe, Column) -> checkVertical(T, Value, Summe + lists:nth(Column, H), Column).

checkAllDiagonal(Square, Value) ->
    case checkDiagonal(Square, Value, 0, 1,1) of
        true -> case checkDiagonal(Square, Value, 0, length(lists:nth(1, Square)),-1) of
                            true -> true;
                            false -> false
                        end;
        false -> false
    end.

checkDiagonal([H|T], Value, Summe, Position, Richtung) -> checkDiagonal(T, Value, Summe + lists:nth(Position, H), Position + Richtung, Richtung);
checkDiagonal([], Value, Summe, Position, Richtung) when Summe == Value -> true;
checkDiagonal([], Value, Summe, Position, Richtung) -> false.
magicSquare(N,值)->
Squares=buildSquare(N,makeRows(N,N*N,Value,N)),
io:fwrite(“方块就绪”),io:fwrite(“n”),
结果=列表:过滤器(fun(X)->测试平方(X,N,值)结束,平方),
io:写入(长度(结果)),
结果。
buildSquare(0,)->[[]];
buildSquare(行,可用窗口)->
[X | L]| L[[];
生成行(字段、数字、值、目标长度)->
[X | L]| X
总和=列表:总和(行),
如果总和==值->真;
正确->错误
结束。
testsquare(正方形,N,值)->选中所有对角线(正方形,值)并同时选中所有水平(正方形,值)和所有垂直(正方形,N,值)。
选中所有水平([H | T],值)->
案例检查水平(H,值,0)的
true->checkHorizontal(列表:n(1,T),值,0);
假->假
结束;
选中所有水平([],值)->true。
检查水平面([H | T],值,总和)->检查水平面(T,值,总和+H);
当Summe==Value->true时选中水平([],Value,Summe);
检查水平([],值,总和)->false。
checkAllVertical(正方形,N,值)->checkAllVertical(正方形,N,值,1)。
选中所有垂直(正方形、N、值、列)->
如果
列>N->true;
正确->
大小写检查垂直(正方形、值、0、列)
true->checkAllVertical(正方形、N、值、列+1);
假->假
结束
结束。
当Summe==Value->true时,选中垂直([],值,Summe,列);
checkVertical([],Value,Summe,Column)->false;
checkVertical([H | T],Value,Summe,Column)->checkVertical(T,Value,Summe+列表:第n(Column,H),Column)。
选中所有对角线(正方形,值)->
大小写检查对角线(正方形,值,0,1,1)
true->大小写检查对角线(平方,值,0,长度(列表:第n(1,平方)),-1)
真->真;
假->假
结束;
假->假
结束。
检查对角线([H | T],值,总和,位置,里奇东)->检查对角线(T,值,总和+列表:第n(位置,H),位置+里奇东,里奇东);
当Summe==值->真时,检查对角线([],值,总和,位置,位置);
检查对角线([],值,求和,位置)->false。
好的,我已经尝试在计算过程的前面添加了对行和正方形的检查

buildSquare(0, _, _, _) -> [[]];
buildSquare(Rows, AvailableRows, RowLength, Value) ->
    [ [X|L] || L <- buildSquare(Rows-1, AvailableRows, RowLength, Value), X <- AvailableRows, validateSquare([X|L], RowLength, Value)].

checkOnlyUniqueNumbers(List) -> erlang:length(lists:flatten(List)) == sets:size(sets:from_list(lists:flatten(List))).

validateSquare(List, RowLength, Value) when length(List) == RowLength -> testsquare(List, RowLength, Value) andalso checkOnlyUniqueNumbers(List);
validateSquare(List, _,_) -> checkOnlyUniqueNumbers(List).

%produces all possible rows with a dimension of Fields and the Numbers from 1 to Numbers
makeRows(0,_,_,_) -> [[]];
makeRows(Fields, Numbers, Value, TargetLength) ->
    [ [X|L] || L <- makeRows(Fields-1, Numbers, Value, TargetLength), X <- lists:seq(1,Numbers), checkRow([X|L], TargetLength, Value)].

%Checks if the sum of the row is Value when the row has the needed length Length
checkRow(Row, Length, _) when length(Row) < Length -> checkOnlyUniqueNumbers(Row);
checkRow(Row, _, Value) ->
    Sum = lists:sum(Row),
    Sum == Value andalso checkOnlyUniqueNumbers(Row).
buildSquare(0,,,,->[[]];
buildSquare(行、可用行、行长度、值)->
[[X | L]| L testsquare(列表、行长、值)并仅选中唯一的整数(列表);
validateSquare(列表,,)->checkOnlyUniqueNumbers(列表)。
%生成所有可能的行,其维度为字段,数字范围为1到1
makeRows(0,,,,)->[[]];
生成行(字段、数字、值、目标长度)->
[X | L]| L
总和=列表:总和(行),
Sum==值,并同时检查唯一的IQueNumbers(行)。

嗯,erlang并不懒惰,所以

magicSquare(N, Value) ->
    Squares = buildSquare(N, makeRows(N, N*N, Value, N)),
当使用参数4和34调用时,尝试使用它们之间从1到16(包括)的所有数字,构建所有3121348608个可能的四行组合的列表,每个行的总和为34

即使每个方块只占用16个字节(每个单元一个字节),也需要大约48GB的内存,不包括列表开销

在惰性语言中,您的算法可以工作,尽管速度很慢。但在非惰性语言中,您需要更早地进行修剪,或者选择完全不同的算法

您可以测试垂直线和对角线是否有机会与
buildSquare
中已有的目标值求和,这可能会将内存需求降低到足以容纳4×4幻方的内存中(但我不太相信)。如果您只构建
(N-1)x N
网格化并从垂直和计算最后一行,这将使
正方形的大小减少另一个
N!
,这与早期修剪一起有更好的机会拟合到内存中(对于
N==4
,对于较大的
N
),而不是更大的
N

但是您应该尽早重新构造算法以使用约束。假设您检查第一行
1 2 15 16
。然后您知道左栏
1
下面的三个数字以及主对角线上剩余的三个数字的总和必须为33。因此,您需要从
{3,4,5,6,7,8,9,10,11,12,13,14}
求和到66。这六个数字没有太多选择,因为其中最大的六个数字加起来只有69,所以你有

6, 10, 11, 12, 13, 14
7,  9, 11, 12, 13, 14
8,  9, 10, 12, 13, 14
只有三种可能。下角的两个数字也受右列和主东北对角线的约束。将这些约束一起考虑会进一步限制搜索空间

如果你依次考虑一个可能的方块,一个接着一个行,不要存储候选者[你可以存储魔法4×4个方块,它们不是太多],你可以在小内存中找到所有的幻方,如果你愿意的话。