Julia: Create AbstractArray with Constraints on Values - struct

I'm working on a Julia project which requires matrices to satisfy a trace-one constraint. To avoid checking if matrices are trace-one at inputs and outputs of numerous functions, I'd like to create a new data structure which implicitly contains this constraint.
In my working example, I've defined a struct TraceOne which throws an error if the trace is not equal to one.
struct TraceOne
M :: Matrix{Complex{Float64}}
TraceOne(M) = (tr(M) == 1) ? new(M) : throw(DomainError(M, "Matrix M is not trace-one."))
end
A = TraceOne([0.1 0.5;0.3 0.9])
However, I would like to avoid accessing the trace-one matrix with a key, A.M returns [0.1 0.5;0.3 0.9].
Alternatively, I've tried to create a struct which is a SubType of an AbstractMatrix, but I can't get the values of the AbstractMatrix to initialize properly.
struct TraceOne2 <: AbstractMatrix{Complex{Float64}}
M :: Matrix{Complex{Float64}}
Base.size(T::TraceOne2) = size(T.M)
Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, size(T.M)...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I] = v)
TraceOne2(M) = (tr(M) == 1) ? new(M) : throw(DomainError(M, "Matrix M is not trace-one."))
end
B = TraceOne2([0.1 0.5;0.3 0.9])
When I run this code, I find that B is [0.9 0.9;0.9 0.9]. All elements of B are initialized to the value of the (2,2), the index of the input array.
How should I modify struct TraceOne2 ... end such that the resulting matrix B is initialized as [0.1 0.5;0.3 0.9]?

Change this functions from:
Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, size(T.M)...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I] = v)
to:
Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, I...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I...] = v)

Related

Can't evaluate at compile time - NIM

Hi I'm starting to play around with NIM
I get a "can't evaluate at compile time" error on this code:
import strutils
type
Matrix[x, y: static[int], T] = object
data: array[x * y, T]
var n,m: int = 0
proc readFile() =
let f = open("matrix.txt")
defer: f.close()
var graph_size = parseInt(f.readline)
var whole_graph: Matrix[graph_size, graph_size, int]
for line in f.lines:
for field in line.splitWhitespace:
var cell = parseInt(field)
whole_graph[n][m] = cell
m = m + 1
n = n + 1
readFile()
Any help appreciated.
Unless you absolutely positively need array in this scenario while not knowing its size at compile-time, you may want to rather swap to the seq type, whose size does not need to be known at compile-time.
Together with std/enumerate you can even save yourself the hassle of tracking the index with n and m:
import std/[strutils, enumerate]
type Matrix[T] = seq[seq[T]]
proc newZeroIntMatrix(x: int, y: int): Matrix[int] =
result = newSeqOfCap[seq[int]](x)
for i in 0..x-1:
result.add(newSeqOfCap[int](y))
for j in 0..y-1:
result[i].add(0)
proc readFile(): Matrix[int] =
let f = open("matrix.txt")
defer: f.close()
let graph_size = parseInt(f.readline)
var whole_graph = newZeroIntMatrix(graph_size, graph_size)
for rowIndex, line in enumerate(f.lines):
for columnIndex, field in enumerate(line.split):
let cell = parseInt(field)
whole_graph[rowIndex][columnIndex] = cell
result = whole_graph
let myMatrix = readFile()
echo myMatrix.repr
Further things I'd like to point out though are:
array[x * y, T] will not give you a 2D array, but a single array of length x*y. If you want a 2D array, you would most likely want to store this as array[x, array[y, T]]. That is assuming that you know x and y at compile-time, so your variable declaration would look roughly like this: var myMatrix: array[4, array[5, int]]
Your Matrix type has the array in its data field, so trying to access the array with that Matrix type needs to be done accordingly (myMatrix.data[n][m]). That is, unless you define proper []and []= procs for the Matrix type that do exactly that under the hood.

How to structure the state in activityOf() in CodeWorld?

I explore the usage of activityOf(state_0, change, picture) in CodeWorld framework.
The state is described as a tuple. I test the possibility to let one of the elements in the tuple to be a list, since I think that would be very useful and make coding more compact.
In the example below I show that it seems to work if I just print out the first element u1 in the u_list. I can control the value by keys for up and down and time t goes on. The second element u2 in the u_list is simply there and not changed.
program = activityOf(state_0, change, picture)
state_0(rs) = (t0, u_list_0)
u_list_0 = [u10,u20]
t0 = 0
u10 = 0
u20 = 7
t_of((t_value,_)) = t_value
u1_of((_, ulist)) = ulist#1
u2_of((_, ulist)) = ulist#2
change((t, u_list), KeyPress("Up")) = (t_of((t,u_list)), [u1_of((t, u_list))+1])
change((t, u_list), KeyPress("Down")) = (t_of((t,u_list)), [u1_of((t, u_list))-1])
change((t, u_list), TimePassing(dt)) = (t_of((t,u_list))+dt, u_list)
change((t, u_list), other) = (t, u_list)
picture((t, u_list)) = pictures [translated(lettering(printed(t_of((t, u_list)))),0,1),
lettering(printed(u1_of((t, u_list))))]
However, if I change the example on the last row to just print out u2, i.e. change u1_of (..) to u2_of(..) then I get get no compilation error and the program runs. But if I press any of the keys up and down then I get a runtime error for the line 11 of the code where u2_of() is defined.
Error message:
List index is too large.
When evaluating: error, called in the standard library idxErrorTooLarge, called
in the standard library #, used at Line 11, Column 21 in your code
What is going on here?
Is it at all possible to use a list as one element in the state tuple?
Link to run https://code.world/#PBKh1Aucqqxg48ePyxxAuUg
In your up and down key handlers, you are changing the list to have only one element:
change((t, u_list), KeyPress("Up")) = (t_of((t,u_list)), [u1_of((t, u_list))+1])
change((t, u_list), KeyPress("Down")) = (t_of((t,u_list)), [u1_of((t, u_list))-1])
^^^^^^^^^^^^^^^^^^^^^^
If you ask for the second element of the list (as picture does) after pressing one of those keys, there won't be one to access. You might want something like:
[u1_of((t, u_list))-1, u2_of(t, u_list)]
As a stylistic comment: it's fairly unusual to use accessor functions like this in Haskell if pattern matching gets you where you want to go. For example, this would be a bit more idiomatic:
change ((t, [r, c]), KeyPress "Up" ) = (t, [r+1, c])
change ((t, [r, c]), KeyPress "Down") = (t, [r-1, c])
This would be much more idiomatic:
data GameState = GameState
{ t :: Int
, r :: Int
, c :: Int
}
change (s, KeyPress "Up" ) = s { r = r s + 1 }
change (s, KeyPress "Down") = s { r = r s - 1 }
One benefit of this final style is that it's not possible to accidentally create a "list" with the wrong number of elements.

How can one represent distinct non-numeric symbols in sympy?

I am experimenting with the representation of a trivial statistics problem in Sympy:
For a sample space S, there are 6 possible distinct outcomes
a,b,c,d,e,f. We can define event A as having occurred if any of
a,b,c have, and event B as having ocurred if any of b,c,d have.
Given a probability mass function pmf defined over S, what is the
probability of event A?
When attempting to implement this symbolically, I receive the following error:
~/project/.envs/dev/lib/python3.6/site-packages/sympy/stats/frv.py in _test(self, elem)
164 elif val.is_Equality:
165 return val.lhs == val.rhs
--> 166 raise ValueError("Undecidable if %s" % str(val))
167
168 def __contains__(self, other):
ValueError: Undecidable if Eq(d, a) | Eq(d, b) | Eq(d, c)
The problem is implemented as follows with comments on the failing lines of code:
from sympy import Eq, Function, symbols
from sympy.logic import Or
from sympy.sets import FiniteSet, Union
from sympy.stats import FiniteRV, P
# 1. Define a sample space S with outcomes: a,b,c,d,e,f; Define events A, B
A = FiniteSet(*symbols('a b c'))
B = FiniteSet(*symbols('b c d'))
S = Union(A, B, FiniteSet(*symbols('e f')))
display("Sample Space", S)
pmfFunc = Function("pmf")
pmfDict = {v: pmfFunc(v) for v in S}
X = FiniteRV('X', pmfDict)
a,b = symbols('a b')
# 2. P(X = a) = pmf(a)
display(P(Eq(X,a)))
# 3. A.as_relational(X) yields `(X=a) \lor (X=b) \lor (X=c)`
display(A.as_relational(X))
# 4. P(X = a \lor X = b) = pmf(a) + pmf(b)
# - Actual Output: ValueError: Undecidable if Eq(c, a) | Eq(c, b)
display(P(Or(Eq(X,a), Eq(X,b)))) # [FAILS]
# 5. P(A) = pmf(a) + pmf(b) + pmf(c)
# - Actual Output: ValueError: Undecidable if Eq(d, a) | Eq(d, b) | Eq(d, c)
display(P(A.as_relational(X))) # [FAILS]
I obtain expected output up to display(A.as_relational(X)):
Interpreting the failure message suggests that Sympy is unable to tell that the set members are distinct. Replacing the symbols with integers resolves the error and I get output similar to what I desire.
A = FiniteSet(1, 2, 3)
B = FiniteSet(2, 3, 4)
S = Union(A, B, FiniteSet(5, 6))
If I am not misunderstanding the error or the fundamental use of the library, is there a way to tell Sympy that a collection of symbols is entirely distinct? I have attempted to replace the symbols with Dummy instances without success, and I have also attempted to leverage the assumptions module without success:
facts = [Eq(a,b) if a is b else Not(Eq(a,b)) for a, b in itertools.product(S, S)]
with assuming(*facts):
I would like to avoid confusing mappings between integers and symbolic forms, as user error may not be apparent when the results are printed as latex. I am willing to adopt some burden in a workaround (e.g., as it would have been maintaining a collection of Dummy instances), but I have yet to find an acceptable workaround.
Interesting question. Maybe it can be done with with assuming(Ne(a,b), ...): context but I take a more pragmatic approach: replace symbols with cos(non-zero integer) which SymPy can easily distinguish as equal or not:
>>> reps = dict(zip(var('a:f'),(cos(i) for i in range(1,7))))
>>> ireps = {v:k for k,v in reps.items()}
>>> a,b,c,d,e,f = [reps[i] for i in var('a:f')]
Then remove your a, b = symbols... line and replace display(x) with display(x.subs(ireps) to get
('Sample Space', FiniteSet(a, b, c, d, e, f))
(pmf(a),)
(Eq(X, a) | Eq(X, b) | Eq(X, c),)
(pmf(a) + pmf(b),)
(I use cos(int) instead of int because I am not sure whether any computation would result in addition of two elements and I want to make sure they stay distinct.)
Another approach would be to define a constant class that derives from Symbol:
class con(Symbol):
def __hash__(self):
return id(self)
def __eq__(a,b):
if isinstance(b, con):
return a.name == b.name
_eval_Eq = __eq__
a,b,c,d,e,f=map(con,'abcdef')
display=lambda*x:print(x)
from sympy import Eq, Function, symbols
from sympy.logic import Or
from sympy.sets import FiniteSet, Union
from sympy.stats import FiniteRV, P
A = FiniteSet(a,b,c)
B = FiniteSet(b,c,d)
S = Union(A, B, FiniteSet(e,f))
pmfFunc = Function("pmf")
pmfDict = {v: pmfFunc(v) for v in S}
X = FiniteRV('X', pmfDict)
display("Sample Space", S)
display(P(Eq(X,a)))
display(A.as_relational(X))
display(P(Or(Eq(X,a), Eq(X,b))))
display(P(A.as_relational(X)))
gives
('Sample Space', FiniteSet(a, b, c, d, e, f))
(pmf(a),)
(Eq(X, a) | Eq(X, b) | Eq(X, c),)
(pmf(a) + pmf(b),)
(pmf(a) + pmf(b) + pmf(c),)

Assigning multiple expressions for Symbolic variable in theano

a = T.iscalar()
b = T.iscalar()
c = a
d = c+b
f = theano.function(
inputs=[a,b],
outputs=d
)
print(f(2,3))
This piece of code is executing properly and is printing 5. But if I change the code as below,
a = T.iscalar()
b = T.iscalar()
e = T.iscalar()
c = a
d = c+b
c = e
f = theano.function(
inputs=[e,b],
outputs=d
)
print(f(2,3))
I'm getting the following error:
theano.compile.function_module.UnusedInputError: theano.function was asked to create a function computing outputs given certain inputs, but the provided input variable at index 0 is not part of the computational graph needed to compute the outputs:
It seems that c is depending only on a and not on e.
My question is, Does theano allows only one expression for the assignment of a symbolic variable?

Python construction of value set dictionary

.I've been dealing with list comprehension recently, I came across a problem I can't seem to solve>
let's say I have pairs in the form of:
A,B,C,X="ABCX"
init = {(A,B),(B,C),(C,X)}
I am trying to construct a dictionary, where each key would be an individual letter, and each value all connections this letter has with other, so>
{A:{B},B:{A,C},C:{B,X},X:{C}}
Things I tried>
final_dict = {k : {j for p,j in init if p==k} for k,v in init}
but this returns me ony if the partner is located in the second place,
Trying to add the first place>
final_dict = {k : {j for p,j in init if p==k or p if j == k} for k,v in init}
An error occurs.
Here is the solution without dict comp
init = {('A','B'),('B','C'),('C','X')}
d = {}
for k, v in init:
d.setdefault(k, set()).add(v)
d.setdefault(v, set()).add(k)
The problem is that with your current format for the data you can't properly specify the key, values. Ideally it should be.
init = {('A','B'),('B','A'),('B','C'),('C','B'),('C','X'),('X','C')}
Which you can obtain by doing the following if you don't want to / can't adjust your current method for getting the pairs.
init2 = {(y, x) for x, y in init}.union(init)
So you can then do
d = { key : { v for k, v in init2 if k == key } for key, _ in init2 }
There is also this, but it doesn't include X, and again it would probably become much larger to make work due to the current format.
d = { k : {v1 if k == v2 else v for v1, v2 in init } for k, v in init }

Resources