1
$\begingroup$

I created a random directed acyclic graph using Mathematica. I need to compute a specific function from its adjacency matrix.

$f(G)=\mathbb{1}^\top\boldsymbol{d}^{+}-\mathbb{1}^\top(diag(\boldsymbol{d}^{-})-A)\boldsymbol{w} $

where $\boldsymbol{d}^+$ is the vector of out-degrees, $\boldsymbol{d}^-$ is the vector of in-degrees, $A$ is the adjacency matrix, and $w$ is a vector such that $w_i=\log(1-\frac{d_i^+}{d_i^-})$.

I have tried to code this below. I have added 25 to all in-degrees so that I do not have $\infty$ from the log.

     s = DirectedGraph[RandomGraph[{10, 15}], "Acyclic"];
     <del>M = Array[AdjacencyMatrix[s], {10, 10}];</del>
     M=AdjacencyMatrix[s];
     id = VertexInDegree[s];
     od = VertexOutDegree[s];
     <del> wd = MatrixForm[-Log[1 - od/(25+id)]] </del>
     wd = MatrixForm[-Log[1 - od/(25+id)]]
     x=M.wd // MatrixFormA
     Total[x,{1}]

Here I run into trouble as my M.wd is not a vector of length 10. Can someone help me complete the code and get $f(G)$?

Edited: I have obtained a vector for x=M.wd, but using Total[x,{1}] gives me a vector instead of a number. How do I sum up the elements of x?

$\endgroup$
  • 1
    $\begingroup$ Change (1) M=AdjacencyMatrix[s] and (2) ` wd=-Log[1 - od/(25+id)` . $\endgroup$ – kglr Apr 16 '15 at 23:27
  • $\begingroup$ Don't use MatrixForm in the calculation of wd. It's for display only and adds an invisible wrapper which makes the result unusable in further processing. The MatrixFormA used in the last line is not a standard function. Did you define it yourself? $\endgroup$ – Sjoerd C. de Vries Apr 17 '15 at 5:43
1
$\begingroup$

Here is working code:

s = DirectedGraph[RandomGraph[{10, 15}], "Acyclic"];
M = AdjacencyMatrix[s];
id = VertexInDegree[s];
od = VertexOutDegree[s];
wd = Log[1 - od/(25 + id)];
x = M.wd;
Total@x

What makes this work:

  1. Do not use MatrixForm in calculations, only for final display, since it wraps the expression and leads to a different internal representation.
  2. Just use Total without a level specification.
| improve this answer | |
$\endgroup$
1
$\begingroup$

As others have pointed out, using MatrixForm when assigning values will result in something that's no longer treated as a matrix for many functions. You can see the difference directly with the following example.

a = IdentityMatrix[2];
b = MatrixForm[a];

FullForm[a]
(* List[List[1, 0], List[0, 1]] *)

FullForm[b]
(* MatrixForm[List[List[1, 0], List[0, 1]]] *)

FullForm[a.b]
(* Dot[List[List[1, 0], List[0, 1]], MatrixForm[List[List[1, 0], List[0, 1]]]] *)

In this case, the function Dot simply doesn't have a definition for handling inputs with the pattern MatrixForm[_]. However, it's often the case that you still want to view the results of intermediate calculations in a readable format. Here are a couple of ways to get around this:

Change the way you make assignments

You could make your assignments like so:

MatrixForm[wd = -Log[1 - od/(25 + id)]]

enter image description here

That way, the correct value is assigned, but the output will still display the way you want to, since MatrixForm is only being placed on the output of the assignment, not the assigned value itself.

wd

enter image description here

Change the default behavior of Dot

Another option is to directly add the rule to Dot to accept MatrixForm inputs like so:

Unprotect[Dot]
Dot[MatrixForm[m1_], m2_] := Dot[m1, m2]
Dot[m1_, MatrixForm[m2_]] := Dot[m1, m2]
Protect[Dot]

This way, when you attempt to multiply matrices that have a MatrixForm wrapper, Dot will automatically use the contents of the wrapper instead. This behavior will remain for the current session.

However, you need to be careful with using Unprotect to change the behavior of built-in functions. It's often the case that you'll just keep running into similar issues down the road and you'll need to keep modifying built-in functions to the point where you'll have a giant unpredictable mess on your hands.

Other functions

As a relevant example, note that the Total function also has different behaviors for the following:

u = {x, y, z};
v = MatrixForm[u];

Total[u]
(* x + y + z *)

Total[v]
(* {x, y, z} *)

This is because MatrixForm will assume a row vector when its input is a 1-dimensional list. So Total[v] is like

Total[{{x, y, z}}]

(notice the extra braces)

This behavior for Total is why your last line isn't working properly, because you're trying to compute

Total[MatrixForm[M.wd], {1}]

To fix this, you could also use Unprotect for Total and add a rule in, but I wouldn't recommend that route. Instead, the first option is probably safest, even if it means you have to type things a bit differently.

MatrixForm[x = M.wd]
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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