Problem with for loops over user-defined structures - julia

I have structures defined as:
struct CLocation{T<:Real}
x::Array{T,1}
y::Array{T,1}
z::Array{T,1}
end
struct CSize{T<:Real}
x::Array{T,1}
y::Array{T,1}
z::Array{T,1}
end
struct FLocation{T<:Real}
x::Array{T,1}
y::Array{T,1}
z::Array{T,1}
end
struct MStructure
dimension::Real
dims::Array{Int,1}
csize::CSize
ccenters::CLocation
fcenters::FLocation
corner::Array{Int,1}
edge::Array{Int,1}
end
struct CValue # {T<:Real}
domain::MStructure
value::Union{Array{<:Real}, DenseArray{Bool}} #Union{Array{T}, BitArray{}}
end
With operators for these structures:
for f in [:+, :-, :*, :/, :^, :(==), :>, :(>=), :<, :(<=)]
#eval function $f(a::CValue, b::CValue)
return CValue(a.domain, $f.(a.value, b.value))
end
end
for f in [:+, :-, :*, :/, :^, :(==), :>, :(>=), :<, :(<=)]
#eval function $f(a::CValue, b::Real)
return CValue(a.domain, $f.(a.value, b))
end
end
for f in [:+, :-, :*, :/, :^, :(==), :>, :(>=), :<, :(<=)]
#eval function $f(a::Real, b::CValue)
return CValue(b.domain, $f.(a, b.value))
end
end
I have two types of variables: val::Cvalue and vec::Vector{Cvalue}(undef,N)
I am trying to loop over them to perform summations, and I have success when implemeting:
function calc_sum(N,vec,val)
for i in 1:N
val = val + vec[i]
end
return val
end
Where I have initialized val as 0
Is there a more succinct way to perform this loop? Preferably in the format of: val = [val + vec[i] for i in 1:N]
which returns a vector of type Cvalue, when my intention is that val is simply of type Cvalue
I have tried val = (val + vec[i] for i in 1:N) with no success.

In Julia 1.6 and later you can use sum(vec; init = val).
In older versions you can use reduce(+, vec; init = val) or foldl(+, vec; init = val) if + is non associative.
If you want to keep enumeration, then you can do something like foldl((acc, i) -> vec[i] + acc, 1:length(vec); init = val) or equivalently
foldl(1:length(vec); init = val) do acc, i
acc + vec[i]
end

Related

No iterate method on Ordering

I'm implementing the Ordering type according to the docs but I'm getting a missing method error. The docs don't say anything about needing to define iterate?
https://juliacollections.github.io/DataStructures.jl/v0.9/sorted_containers.html#Constructors-for-Sorted-Containers-1
ERROR: LoadError: MethodError: no method matching iterate(::Type{BidOrdering})
using DataStructures
import Base.Ordering
import Base.lt
import DataStructures.eq
struct MBOBookEntity
orderid::Int64
price::String
orderPriority::Int64
displayQty::Int64
end
mutable struct MBOBook
bidBook::SortedSet{MBOBookEntity}
askBook::SortedSet{MBOBookEntity}
function MBOBook()
bidBook = SortedSet{MBOBookEntity}(BidOrdering)
askBook = SortedSet{MBOBookEntity}(AskOrdering)
new(bidBook, askBook)
end
end
struct BidOrdering <: Ordering end
struct AskOrdering <: Ordering end
lt(::BidOrdering, o1::MBOBookEntity, o2::MBOBookEntity) = begin
if o1.price == o2.price
return o1.orderPriority < o2.orderPriority
else
return o2.price < o1.price
end
end
eq(::BidOrdering, o1::MBOBookEntity, o2::MBOBookEntity) = isequal(o1.orderid, o2.orderid)
lt(::AskOrdering, o1::MBOBookEntity, o2::MBOBookEntity) = begin
if o1.price == o2.price
return o1.orderPriority < o2.orderPriority
else
return o1.price < o2.price
end
end
eq(::AskOrdering, o1::MBOBookEntity, o2::MBOBookEntity) = isequal(o1.orderid, o2.orderid)
I think that you provide a type instead of a value :
mutable struct MBOBook
bidBook::SortedSet{MBOBookEntity}
askBook::SortedSet{MBOBookEntity}
function MBOBook()
bidBook = SortedSet{MBOBookEntity}(BidOrdering()) # <- here, forgotten ()
askBook = SortedSet{MBOBookEntity}(AskOrdering()) # <- here, forgotten ()
new(bidBook, askBook)
end
end

How to print in if statement in SML

This is the code I tried
fun printsl([], k) = true
| printsl(h::t) = if k > h then print(h) andalso printsl(t);
But when I run the code, i get the following error
= stdIn:4.68-7.8 Error: syntax error: deleting SEMICOLON ID
stdIn:8.1 Error: syntax error found at EOF
The goal of the function is to print any number in the list that is less than the value k
A few things wrong here. Let's start with your function signature.
On the first line, your function takes 2 parameters, an empty list and whatever the type of k is (it is not important yet). Then on the second line, the function takes just one parameter, a non-empty list.
The two lines should match to look like:
fun printsl([], k) = ...
| printsl(h::t, k) = ...
Now let's think about the use of andalso. andalso is an operator which takes two booleans and returns a bool. It can be considered to have the signature bool * bool -> bool.
Your usage print(h) andalso printsl(t) does not match this signature.
The type of print is string -> unit, so the type of print(h) is unit (assuming h to be a string). As such, the usage of andalso is incorrect as the types on each side are not bools.
Instead of using andalso, we can simply execute both statements (print(h); printsl(t, k)). Sequences like this are expressions which return the last value. That is to say (x; y; z) returns z.
fun printsl([], k) = true
| printsl(h::t, k) = if h < k then (print(h); printsl(t, k));
However, this is still broken as the if-else construct in SML is an expression and must have a matching else, so you could use either of the following:
fun printsl([], k) = true
| printsl(h::t, k) =
if h < k then (print(h); printsl(t))
else printsl(t, k);
fun printsl([], k) = true
| printsl(h::t, k) = (
if h < k then print(h) else ();
printsl(t, k)
);
I personally prefer the latter as it prevents repetition of printsl.
This code will compile, but the signature is wrong. As we use h directly as a parameter of print, its type is inferred to be a string. This means that the compiler determines printsl to have type string list * string -> bool, whereas we are aiming for int list * int -> bool.
This can be corrected by changing the call print(h) to print(Int.toString h), giving us:
fun printsl([], k) = true
| printsl(h::t, k) = (
if h < k then print(Int.toString h) else ();
printsl(t, k)
);
This is now a function which will print all values in the given list which are less than k, but it always returns true. This provides no extra information so I would be inclined to change the signature to int list * int -> unit, giving us (finally):
fun printsl([], k) = ()
| printsl(h::t, k) = (
if h < k then print(Int.toString h) else ();
printsl(t, k)
);
This entire program could also be written in a more functional manner using List.app and List.filter.
fun printsl (xs, k) =
List.app
(fn y => print (Int.toString y))
(List.filter
(fn x => x < k)
xs);

localize memoization inside a function in Julia

Is there a way I can localize memoization (via Memoize.jl) inside a function? or at least delete the dictionaries created by memoization?
Clarification: suppose I define a define a function f(x, y). I want to start with a fresh table for every new value of y. That is, given y = y0, f( . , y0) iterates on itself for x, x-1, etc but given a new y = y1, I don't need to store the old table for y0, so that memory can be freed up. How can I do that?
Solution:
cachedfib() = begin
global dict = Dict()
global dict2 = Dict()
function _fib(n::Int, a::Int)
if !haskey(dict2, a)
dict2[a] = true
dict = Dict()
end
if haskey(dict, (n, a))
return dict[(n, a)]
elseif n < 2
dict[(0, a)] = 0
dict[(1, a)] = 1
return dict[(n, a)]
else
dict[(n, a)] = a*(_fib(n - 1, a) + _fib(n - 2, a))
return dict[(n, a)]
end
end
end
fib = cachedfib()
fib(10, 1)
fib(10, 2)
now call dict and dict2 and check that the dictionaries are refreshed every time the second argument changes. You can get even better performance when the parameters to store are integers and you use Array instead of Dict
To use memoization technique you can do it with let or closures. Have a look at my rapid implementation of factorial (with closure).
with_cached_factorial() = begin
local _cache = [1] #cache factorial(0)=1
function _factorial(n)
if n < length(_cache)
println("pull out from the cache factorial($n)=$(_cache[n+1])")
_cache[n+1]
else
fres = n * _factorial(n-1)
push!(_cache, fres)
println("put factorial($n)=$fres into the cache of the size=$(sizeof(_cache))") #a
fres
end
end
end
Now, just use it:
julia> myf = with_cached_factorial()
_factorial (generic function with 1 method)
julia> myf(3)
pull out from the cache factorial(0)=1
put factorial(1)=1 into the cache of the size=16
put factorial(2)=2 into the cache of the size=24
put factorial(3)=6 into the cache of the size=32
6
julia> myf(5)
pull out from the cache factorial(3)=6
put factorial(4)=24 into the cache of the size=40
put factorial(5)=120 into the cache of the size=48
120
julia> myf(10)
pull out from the cache factorial(5)=120
put factorial(6)=720 into the cache of the size=56
put factorial(7)=5040 into the cache of the size=64
put factorial(8)=40320 into the cache of the size=72
put factorial(9)=362880 into the cache of the size=80
put factorial(10)=3628800 into the cache of the size=88
3628800
let Aold = nothing
global foo
function foo(A::AbstractArray)
if A == Aold
println("Same as last array")
else
Aold = A
end
nothing
end
end
Results:
julia> A = rand(2,2)
2x2 Array{Float64,2}:
0.272936 0.153311
0.299549 0.703668
julia> B = rand(2,2)
2x2 Array{Float64,2}:
0.6762 0.377428
0.493344 0.240194
julia> foo(A)
julia> foo(A)
Same as last array
julia> foo(B)
julia> foo(A)
julia> foo(A)
Same as last array
julia> Aold
ERROR: UndefVarError: Aold not defined

How to return values from recursive function to array

function nestedLoop(depth::Integer, n::Integer, symbArr, len::Integer, k::Integer, num_arr)
for i = k:len
num_arr[depth-n+1] = symbArr[i]
n == 1 && println(num_arr)
(n > 1) && nestedLoop(depth, n-1, symbArr, len, i, num_arr)
end
end
function combwithrep(symbArr, n::Integer)
len = length(symbArr)
num_arr = Array(eltype(symbArr),n)
nestedLoop(n, n, symbArr, len, 1, num_arr)
end
#time combwithrep(["+","-","*","/"], 3)
I have some troubles with returning values from elementary recursive function, that computes combinations with repetitions. I can't realize how to commit replacement of println with some return to array in combwithrep() function. I have failed to use tasks for this also. The best result is to obtain iterator over this values, but it is not possible in recursion, isn't it?
I feel that the answer is simple, and i don't understand something about recursion.
This is certainly not optimal, but it's functional.
julia> function nested_loop{T <: Integer, V <: AbstractVector}(depth::T, n::T, symb_arr::V, len::T, k::T, num_arr::V, result::Array{V,1})
for i = k:len
num_arr[depth-n+1] = symb_arr[i]
n == 1 ? push!(result, deepcopy(num_arr)) : nested_loop(depth, n-1, symb_arr, len, i, num_arr, result)
end
end
nested_loop (generic function with 1 method)
julia> function combwithrep(symb_arr::AbstractVector, n::Integer)
len = length(symb_arr)
num_arr = Array(eltype(symb_arr),n)
result = Array{typeof(num_arr)}(0)
nested_loop(n, n, symb_arr, len, 1, num_arr, result)
return result
end
combwithrep (generic function with 1 method)
julia> combwithrep(['+', '-', '*', '/'], 3)
20-element Array{Array{Char,1},1}:
['+','+','+']
['+','+','-']
['+','+','*']
['+','+','/']
['+','-','-']
['+','-','*']
['+','-','/']
['+','*','*']
['+','*','/']
['+','/','/']
['-','-','-']
['-','-','*']
['-','-','/']
['-','*','*']
['-','*','/']
['-','/','/']
['*','*','*']
['*','*','/']
['*','/','/']
['/','/','/']

Fortran: pointer to various array-valued functions

I am starting this thread because I want to learn how to successfully use the same pointer to serve as the aliases of different array-valued functions, say, f1 and f2, sequentially.
Here is an unsuccessful code to illustrate what I want. Thanks. Lee
PROGRAM main
...
REAL(WP), POINTER, DIMENSION(:) :: p
p=>f1
print*,p(1.0_wp) ! the outcome should be 3
p=>f2
print*,p(2.0_wp) ! the outcome should be 3 1
CONTAINS
FUNCTION f1(x)
IMPLICIT NONE
REAL(WP), TARGET :: f1
REAL(WP), INTENT(IN) :: x
f1=x+2
END FUNCTION f1
FUNCTION f2(x)
IMPLICIT NONE
REAL(WP), TARGET :: f2(2)
REAL(WP), INTENT(IN) :: x
f2(1) = x+1
f2(2) = x-1
END FUNCTION f2
END PROGRAM main
For a pointer to a function that returns an array, you want to have an interface to describe a pointer to a function that returns an array.
Here is an example of how to setup function pointers that might set you in the right direction:
How to alias a function name in Fortran
Edit: OK, here is some example source code:
module ExampleFuncs
implicit none
contains
function f1 (x)
real, dimension (:), allocatable :: f1
real, intent (in) :: x
allocate (f1 (1:2))
f1 (1) = 2.0 * x
f1 (2) = -2.0 * x
return
end function f1
function f2 (x)
real, dimension (:), allocatable :: f2
real, intent (in) :: x
allocate (f2 (1:3))
f2 (1) = x
f2 (2) = x**2
f2 (3) = x**3
return
end function f2
end module ExampleFuncs
program test_func_ptrs
use ExampleFuncs
implicit none
abstract interface
function func (z)
real, dimension (:), allocatable :: func
real, intent (in) :: z
end function func
end interface
procedure (func), pointer :: f_ptr
real :: input
do
write (*, '( // "Input test value: ")', advance="no" )
read (*, *) input
if ( input < 0.0 ) then
f_ptr => f1
else
f_ptr => f2
end if
write (*, '( "evaluate function: ", *(ES14.4) )' ) f_ptr (input)
end do
end program test_func_ptrs

Resources