This code is a part of a code which sort nondominated points. F is a cell array that keeps the pareto fronts. but Julia gives this error:
BoundsError: attempt to access 0-element Array{Any,1} at index [1]
setindex!(::Array{Any,1}, ::Any, ::Int64) at essentials.jl:183
macro expansion at Nondominated sorting.juliarc.jl:41 [inlined]
would you please help me. How can I fix it?
#=pop is a structure including
struct individual
position
cost
Rank
Dominationset
Dominatedcount
Crowdingdostance
end
this pop is used for this code as input
5-element Array{individual,1}:
individual(Any[-3, 4, -2], Any[1.0, 1.0], Any[], Any[], Any[], Any[])
individual(Any[4, 4, 1], Any[1.0, 1.0], Any[], Any[], Any[], Any[])
individual(Any[1, 4, 4], Any[1.0, 1.0], Any[], Any[], Any[], Any[])
individual(Any[4, 4, -2], Any[1.0, 1.0], Any[], Any[], Any[], Any[])
individual(Any[1, 4, 2], Any[0.999999, 1.0], Any[], Any[], Any[], Any[])=#
using JuMP,DataStructures
npop=length(pop);
l=0;
F=[]; # F{1}=[] in matlab it is correct
for i=1:npop
for j=i+1:npop
p=pop[i];
q=pop[j];
if (dominates(p.cost,q.cost))
append!(p.Dominationset,j);
append!(q.Dominatedcount,l+1)
end
if (dominates(q.cost,p.cost))
append!(q.Dominationset,i);
append!(p.Dominatedcount,l+1)
end
pop[i]=p;
pop[j]=q;
end
if pop[i].Dominatedcount==[]
F[1]=[F;i]; #F{1}=[F{1} i] in matlab is used
append!(pop[i].Rank,1);
end
end
the dominates function is as following:
function dominates(x,y)
b=all(x.<=y) && any(x.<y);
return(b);
end
Your problem is here:
F[1]=[F;i]
F is an empty vector, so you cannot assign anything to element 1. This is different from Matlab, which automatically (and imho, dangerously) dynamically extends your array. Instead use: push!:
push!(F, ??)
I put in the questionmarks because I don't understand what you are actually trying to put into F here. Putting F itself inside a vector, and then assigning that to the first element of F? This makes noe sense to me, sorry to say. (Edit: Your Matlab code, F{1}=[F{1} i], makes no sense here, either. Did you by any chance mean to write F = [F, i]?)
Also, are you sure you need to use Any everywhere? Untyped structs and Any vectors will make your code extremely slow.
Related
I want to iterate over positions (x, y) in a 2-dimensional grid and call a function for each position (providing x and y as parameters). I know how this can be done using for loops, but I'd like to write this using functional programming methods such that I can later take advantage of libraries like Rayon. I've managed to build a functional version, but it seems complicated and I wanted to ask whether there's a cleaner way to achieve this.
Here's a small example of computing the maximum sum of all 2x2 patches in a grid:
use std::cmp::max;
const WIDTH: usize = 4;
const HEIGHT: usize = 3;
type Grid = [[u32; WIDTH]; HEIGHT];
fn main() {
let grid: Grid = [
[1, 3, 5, 8],
[3, 9, 4, 2],
[3, 4, 5, 0],
];
let coords = (0..WIDTH - 1).flat_map(|x| (0..HEIGHT - 1).map(move |y| (x, y)));
let max_sum = coords.map(|(x, y)| sum_2x2(x, y, &grid)).max().unwrap();
println!("Max 2x2 patch: {}", max_sum);
}
fn sum_2x2(x: usize, y: usize, grid: &Grid) -> u32 {
[
grid[y][x],
grid[y][x + 1],
grid[y + 1][x],
grid[y + 1][x + 1],
]
.iter()
.sum()
}
The line let coords = (0..WIDTH - 1).flat_map(|x| (0..HEIGHT - 1).map(move |y| (x, y))); seems pretty complex for such a simple task. In Python, I'd do the following to get the positions (which I think is much cleaner):
>>> from itertools import product
>>> product(range(HEIGHT-1), range(WIDTH-1))
Is there a better way to write this or do I just need to get used to it?
You can possibly simplify the code with one of the loop comprehension crates like map_for or mdo.
For example with map_for:
let max_sum = map_for!(
move;
x <- 0..WIDTH-1;
y <- 0..HEIGHT-1;
=> sum_2x2(x, y, &grid)
).max().unwrap();
I haven't tried it with Rayon, but since map_for is simply syntax sugar for a sequence of calls to map and flat_map and works with any type that implements those functions, it should work with Rayon as well.
Full disclosure: I am the author of the map_for crate.
Another option is to use cartesian_product from the Itertools crate, which has many convenient methods involving iterators.
use itertools::Itertools;
(0..WIDTH-1).cartesian_product(0..HEIGHT-1).map(|(x, y)| sum_2x2(x, y, &grid)).max()
As #hellow pointed out in the comments, there's an iproduct macro in the itertools crate that does what I want. Using it, my code can be rewritten like this:
use itertools::iproduct;
...
let coords = iproduct!(0..WIDTH - 1, 0..HEIGHT - 1);
...
That's exactly what I was looking for. Thanks to everyone who commented / posted answers here.
PS: If you want to use an itertools iterator with rayon, you can do this by using the par_bridge method, e.g. iproduct!(0..WIDTH - 1, 0..HEIGHT - 1).par_iter();. Took me a while to figure that out since par_iter and into_par_iter don't work.
I'm sure I missed something obvious here, but I couldn't get Map.update to work with an externally defined unary function, which I thought should work. Elixir complains:
** (UndefinedFunctionError) function xxx/0 is undefined or private. Did you mean one of:
* xxx/1
Isn't the point of Map.update exactly to have a function that takes in the value being updated and returns a new value? Why would it want a zero-arity function? That doesn't seem to make much sense. I guess I'm just a bit fatigued but I just couldn't wrap my head around this.
Assume we have the following code.
defmodule Foo do
def add_one(x), do: x + 1
end
We can use Map.update/4 as follows.
Map.update(my_map, :a, 3, &Foo.add_one/1)
You can see this in an iex session
iex(1)> my_map = %{b: 3}
%{b: 3}
iex(2)> Map.update(my_map, :a, 3, &Foo.add_one/1)
%{a: 3, b: 3}
iex(4)> my_map = %{a: 12}
%{a: 12}
iex(5)> Map.update(my_map, :a, 3, &Foo.add_one/1)
%{a: 13}
I assume you are trying to use Map.update(my_map, :a, 3, Foo.add_one). When you do that, the compiler will try to call a function named Foo.add_one and pass the resulting value into the function. In your case, that function does not exist so it is giving you an error. Also note the & before the function name and the /1 at the end of it.
The & essentially tells the program to pass the function as an argument instead of calling it and passing in the resulting value.
The /1 says that the program should look for a function with that name with an arity (the number of arguments the function takes) of 1.
I came away from Professor Frisby's Mostly Adequate Guide to Functional Programming with what seems to be a misconception about Maybe.
I believe:
map(add1, Just [1, 2, 3])
// => Just [2, 3, 4]
My feeling coming away from the aforementioned guide is that Maybe.map should try to call Array.map on the array, essentially returning Just(map(add1, [1, 2, 3]).
When I tried this using Sanctuary's Maybe type, and more recently Elm's Maybe type, I was disappointed to discover that neither of them support this (or, perhaps, I don't understand how they support this).
In Sanctuary,
> S.map(S.add(1), S.Just([1, 2, 3]))
! Invalid value
add :: FiniteNumber -> FiniteNumber -> FiniteNumber
^^^^^^^^^^^^
1
1) [1, 2, 3] :: Array Number, Array FiniteNumber, Array NonZeroFiniteNumber, Array Integer, Array ValidNumber
The value at position 1 is not a member of ‘FiniteNumber’.
In Elm,
> Maybe.map sqrt (Just [1, 2, 3])
-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm
The 2nd argument to function `map` is causing a mismatch.
4| Maybe.map sqrt (Just [1, 2, 3])
^^^^^^^^^^^^^^
Function `map` is expecting the 2nd argument to be:
Maybe Float
But it is:
Maybe (List number)
Similarly, I feel like I should be able to treat a Just(Just(1)) as a Just(1). On the other hand, my intuition about [[1]] is completely the opposite. Clearly, map(add1, [[1]]) should return [NaN] and not [[2]] or any other thing.
In Elm I was able to do the following:
> Maybe.map (List.map (add 1)) (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
Which is what I want to do, but not how I want to do it.
How should one map over Maybe List?
You have two functors to deal with: Maybe and List. What you're looking for is some way to combine them. You can simplify the Elm example you've posted by function composition:
> (Maybe.map << List.map) add1 (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
This is really just a short-hand of the example you posted which you said was not how you wanted to do it.
Sanctuary has a compose function, so the above would be represented as:
> S.compose(S.map, S.map)(S.add(1))(S.Just([1, 2, 3]))
Just([2, 3, 4])
Similarly, I feel like I should be able to treat a Just(Just(1)) as a Just(1)
This can be done using the join from the elm-community/maybe-extra package.
join (Just (Just 1)) == Just 1
join (Just Nothing) == Nothing
join Nothing == Nothing
Sanctuary has a join function as well, so you can do the following:
S.join(S.Just(S.Just(1))) == Just(1)
S.join(S.Just(S.Nothing)) == Nothing
S.join(S.Nothing) == Nothing
As Chad mentioned, you want to transform values nested within two functors.
Let's start by mapping over each individually to get comfortable:
> S.map(S.toUpper, ['foo', 'bar', 'baz'])
['FOO', 'BAR', 'BAZ']
> S.map(Math.sqrt, S.Just(64))
Just(8)
Let's consider the general type of map:
map :: Functor f => (a -> b) -> f a -> f b
Now, let's specialize this type for the two uses above:
map :: (String -> String) -> Array String -> Array String
map :: (Number -> Number) -> Maybe Number -> Maybe Number
So far so good. But in your case we want to map over a value of type Maybe (Array Number). We need a function with this type:
:: Maybe (Array Number) -> Maybe (Array Number)
If we map over S.Just([1, 2, 3]) we'll need to provide a function which takes [1, 2, 3]—the inner value—as an argument. So the function we provide to S.map must be a function of type Array (Number) -> Array (Number). S.map(S.add(1)) is such a function. Bringing this all together we arrive at:
> S.map(S.map(S.add(1)), S.Just([1, 2, 3]))
Just([2, 3, 4])
I'm trying to convert the following to pointfree style: a function that partially applies a value to the transformer function add before passing in the collection to be iterated over. (Using Ramda.js)
R.compose(
R.map,
R.add
)(1, [1,2,3])
The problem is that R.add is arity 2, as is R.map. I want the application order to be as follows:
add(1)
map(add(1))
map(add(1), [1,2,3])
[add(1,1), add(1,2), add(1,3)]
But what happens instead is this:
add(1, [1,2,3])
map(add(1, [1,2,3]))
<partially applied map, waiting for collection>
Anyone know of a way to specify this behavior?
A plain compose or pipe won't do this because either will absorb all the arguments supplied into the first function. Ramda includes two additional functions that help with this, converge and useWith. In this case useWith is the one that will help:
useWith(map, [add, identity])(1, [1, 2, 3]); //=> [2, 3, 4]
While identity is not absolutely required here, it gives the generated function the correct arity.
Figured it out. If anyone's curious, here's the gist. (You can try it in the console on RamdaJS.com.)
0) For a baseline, here's the pointed version.
func0 = x => R.map(R.add(x))
addOne = func0(1)
addOne([1,2,3]) // [2,3,4]
1) Here's the pointfree core, but it has the ordering problem from the question above.
func1 = R.compose(R.map, R.add)
addOne = func1(1)
addOne([1,2,3]) // [2,3,4])
func1(1, [1,2,3]) // function
2) If the composition is unary (arity 1) 2 invocations are needed apply all params.
func2 = R.unary(R.compose(R.map, R.add))
addOne = func2(1)
addOne([1,2,3]) // [2,3,4])
3) We want one invocation to apply both params, so we uncurry 2.
func3 = R.uncurryN(2, func2)
func3(1, [1,2,3]) // [2,3,4])
4) To prove func2 is composable, let's double the results.
func4 = R.compose(
R.map(R.multiply(2)),
R.uncurryN(2, func2)
)
func4(1, [1,2,3]) // [4,6,8])
5) Substitution gives us a completely pointfree function.
func5 = R.compose(
R.map(R.multiply(2)),
R.uncurryN(2, R.unary(R.compose(
R.map,
R.add
)))
)
func5(1, [1,2,3]) // [4,6,8])
I have a list A, and a function f which takes an item of A and returns a list. I can use a list comprehension to convert everything in A like [f(a) for a in A], but this returns a list of lists. Suppose my input is [a1,a2,a3], resulting in [[b11,b12],[b21,b22],[b31,b32]].
How can I get the flattened list [b11,b12,b21,b22,b31,b32] instead? In other words, in Python, how can I get what is traditionally called flatmap in functional programming languages, or SelectMany in .NET?
(In the actual code, A is a list of directories, and f is os.listdir. I want to build a flat list of subdirectories.)
See also: How do I make a flat list out of a list of lists? for the more general problem of flattening a list of lists after it's been created.
You can have nested iterations in a single list comprehension:
[filename for path in dirs for filename in os.listdir(path)]
which is equivalent (at least functionally) to:
filenames = []
for path in dirs:
for filename in os.listdir(path):
filenames.append(filename)
>>> from functools import reduce # not needed on Python 2
>>> list_of_lists = [[1, 2],[3, 4, 5], [6]]
>>> reduce(list.__add__, list_of_lists)
[1, 2, 3, 4, 5, 6]
The itertools solution is more efficient, but this feels very pythonic.
You can find a good answer in the itertools recipes:
import itertools
def flatten(list_of_lists):
return list(itertools.chain.from_iterable(list_of_lists))
The question proposed flatmap. Some implementations are proposed but they may unnecessary creating intermediate lists. Here is one implementation that's based on iterators.
def flatmap(func, *iterable):
return itertools.chain.from_iterable(map(func, *iterable))
In [148]: list(flatmap(os.listdir, ['c:/mfg','c:/Intel']))
Out[148]: ['SPEC.pdf', 'W7ADD64EN006.cdr', 'W7ADD64EN006.pdf', 'ExtremeGraphics', 'Logs']
In Python 2.x, use itertools.map in place of map.
You could just do the straightforward:
subs = []
for d in dirs:
subs.extend(os.listdir(d))
You can concatenate lists using the normal addition operator:
>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
The built-in function sum will add the numbers in a sequence and can optionally start from a specific value:
>>> sum(xrange(10), 100)
145
Combine the above to flatten a list of lists:
>>> sum([[1, 2], [3, 4]], [])
[1, 2, 3, 4]
You can now define your flatmap:
>>> def flatmap(f, seq):
... return sum([f(s) for s in seq], [])
...
>>> flatmap(range, [1,2,3])
[0, 0, 1, 0, 1, 2]
Edit: I just saw the critique in the comments for another answer and I guess it is correct that Python will needlessly build and garbage collect lots of smaller lists with this solution. So the best thing that can be said about it is that it is very simple and concise if you're used to functional programming :-)
subs = []
map(subs.extend, (os.listdir(d) for d in dirs))
(but Ants's answer is better; +1 for him)
import itertools
x=[['b11','b12'],['b21','b22'],['b31']]
y=list(itertools.chain(*x))
print y
itertools will work from python2.3 and greater
You could try itertools.chain(), like this:
import itertools
import os
dirs = ["c:\\usr", "c:\\temp"]
subs = list(itertools.chain(*[os.listdir(d) for d in dirs]))
print subs
itertools.chain() returns an iterator, hence the passing to list().
This is the most simple way to do it:
def flatMap(array):
return reduce(lambda a,b: a+b, array)
The 'a+b' refers to concatenation of two lists
You can use pyxtension:
from pyxtension.streams import stream
stream([ [1,2,3], [4,5], [], [6] ]).flatMap() == range(7)
Google brought me next solution:
def flatten(l):
if isinstance(l,list):
return sum(map(flatten,l))
else:
return l
If listA=[list1,list2,list3]
flattened_list=reduce(lambda x,y:x+y,listA)
This will do.