2
$\begingroup$

I have an assignment in Mathematica, which I've already solved using Python and it's a bit hard to convert the code. Here's what I have done so far:

def sigmoid(x): # define the sigmoid function
    return 1/(1+np.exp(-x))

def pos_list(node): # returns the neighborhood of node, A is a matrix of adjacency
    return np.nonzero(A[node])[1]  

def neg_list(node): # returns nodes that are not neighbors
    return np.where(A[node]==0)[1]

I have these in Mathematica:

sigmoid[x_] := 1 / (1 + Exp[-x])
M := AdjacencyMatrix[undirectedEdges] (* this is A from above*)
posList[n_] := M[[n]]["NonzeroPositions"]
negList[n_] := Flatten[Position[Normal[M[[n]]], x_Integer /; x = 0]]

Now there is a longer function:

def next_choice(v,t,p,q):
    positive = pos_list(v)
    li = np.array([])
    for pos in positive:
        if pos==t:
            li = np.append(li,1/p)
        elif pos in pos_list(t):
            li = np.append(li,1)
        else :
            li = np.append(li,1/q)
    prob = li/li.sum()
    return np.random.choice(positive,1,p=prob)[0]

So I am stuck here. This is what I've written:

nextChoice[v_, t_, p_, q_] := 
 Module[{li, vpositive, tpositive, len, i, prob},
  li = List[];
  vpositive = posList[v];
  tpositive = posList[t];
  len = Length[vpositive];
  For[i = 1, i <= len, i++,
   If[vpositive[[i]][[1]] == t, AppendTo[li, 1/p], 
     If[Length[AnyTrue[tpositive, # == vpositive[[i]][[1]] &] > 0], 
      AppendTo[li, 1], AppendTo[li, 1/q]]];
   ];
  prob = li/Total[li];
  Return[RandomChoice[prob -> vpositive, 1][[1]]]
  ]

This list li only has one element and I cannot figure out why it doesn't go through all the if statements. any ideas?

Edit: an example

mat = {{0, 1, 0, 0, 0}, {1, 0, 1, 0, 0}, {0, 1, 0, 1, 1}, {0, 0, 1, 0, 0} , {0, 0, 1, 0, 0}};
M = SparseArray[mat]

If we call nextChoice[1, 3, 0.5, 0.5], it should return a random node from the positive list.

$\endgroup$
2
  • 4
    $\begingroup$ Without any example input, it will be hard to tell what exactly is going on. That being said: Position[...,x_Integer/;x==0] can be Position[...,0], List[] can be {}. I'd write your for loop using Map, or using Table (as Table[...,{pos, vpositive}] You don't need Return, the last expression will always be returned. It looks like the issue is in If[Length[AnyTrue[...]>0],...]. The result will always be If[2,...] (because Length[True>0] is 2), which will stay unevaluated because 2 is not a boolean. I'd also suggest to replace the entire condition with MemberQ[...] $\endgroup$
    – Lukas Lang
    May 5, 2021 at 11:26
  • 1
    $\begingroup$ Thank you so much for the suggestions. I did correct the negativeList,[] and rewrote the condition to If[MemberQ[tpositive,vpositive[[i]][[1]]]. There is still something wrong. I am not sure how to use Map or Table, since the if statement is not a function that I can define before? $\endgroup$
    – mandella
    May 5, 2021 at 14:22

1 Answer 1

2
$\begingroup$

Here's my attempt at fixing your code:

mat = {{0, 1, 0, 0, 0}, {1, 0, 1, 0, 0}, {0, 1, 0, 1, 1}, {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0}};
M = SparseArray[mat]

sigmoid[x_] := 1/(1 + Exp[-x])
posList[n_] := Flatten[M[[n]]["NonzeroPositions"]]
negList[n_] := Flatten[Position[Normal[M[[n]]], 0]]

nextChoice[v_, t_, p_, q_] :=
 Module[
  {vpositive, tpositive, prob},
  vpositive = posList[v];
  tpositive = posList[t];
  prob = Table[
    Which[pos == t,
     1/p,
     MemberQ[tpositive, pos],
     1,
     True,
     1/q
     ],
    {pos, vpositive}
    ];
  RandomChoice[prob -> vpositive]
  ]

nextChoice[1, 3, 0.5, 0.5]
(* 2 *)

I won't go over all the changes (feel free to ask in the comments if something is unclear), but here are some of them:

  • I changed posList to return a list of indices with the same format as negList
  • I switched from the For loop to a Table
  • Rather than appending one element to li per loop iteration, I simply use the list returned by Table
  • I swapped the nested If to Which
  • You don't need to normalize the weights given to RandomChoice
  • If you don't specify 1 sample for RandomChoice, it will give you a single sample without a list by default
  • I switched the broken condition to use MemberQ
$\endgroup$
4
  • $\begingroup$ Thank you very much for your help, I really appreciate it! I understand all the changes that you have made, it looks very neat. $\endgroup$
    – mandella
    May 7, 2021 at 7:22
  • $\begingroup$ @chris I have to do a lot of other parts for this assignment, but I needed an extra push towards the right direction. I hope you didn't mean it in a sarcastic way :) $\endgroup$
    – mandella
    May 7, 2021 at 7:24
  • 1
    $\begingroup$ @mandella Good luck with your assignment! One other thing to note: Take a look at Echo, it's an amazing tool to help you debug functions, since you can easily monitor steps of a calculation $\endgroup$
    – Lukas Lang
    May 7, 2021 at 7:33
  • $\begingroup$ Thank you very much! :) Great I will check Echo I think I will need that tool a lot in order to finish this task successfully :) Thank you also for this note! $\endgroup$
    – mandella
    May 7, 2021 at 8:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.