Generate adjacency matrix in graphviz - graphviz

I would like to know if I could use graphviz to generate an image of an adjacency matrix. For example from this file:
digraph {
A -> B;
B -> C;
A -> C;
D -> C;
E -> C;
E -> A;
}
The result should be something like this:
If it is not possible, is there any other software I could use?

Here are some ideas:
I'm not aware of a functionality that allows graphviz to print the matrix, however, if the input graphviz code is relatively clean (free of attributes or weird nodes), I don't see how it would be hard to write a simple parser to produce the desired output.
you may do something simple, like the following example (python):
import pprint
# Example input file with "digraph g {" elided for simplicity:
s = """A -> B;
B -> C;
A -> C;
D -> C;
E -> C;
E -> A; """
lines = s.split("\n")
all_edges = []
pairs = []
for line in lines:
edge = line.replace(";", "").replace(" ", "").split("->")
if len(edge) == 2:
all_edges.append(edge[0])
all_edges.append(edge[1])
pairs.append(edge)
unique_edges = set(all_edges)
matrix = {origin: {dest: 0 for dest in all_edges} for origin in all_edges}
for p in pairs:
matrix[p[0]][p[1]] += 1
pprint.pprint(matrix)
Once all is done, this is what the output looks like, you may write a bit more code to output html or any tabular format of your choosing:
"""
Output:
{'A': {'A': 0, 'B': 1, 'C': 1, 'D': 0, 'E': 0},
'B': {'A': 0, 'B': 0, 'C': 1, 'D': 0, 'E': 0},
'C': {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0},
'D': {'A': 0, 'B': 0, 'C': 1, 'D': 0, 'E': 0},
'E': {'A': 1, 'B': 0, 'C': 1, 'D': 0, 'E': 0}}
"""
I hope this helps!

Related

How to write a function that count each character in a string?

I am trying to write a function that counts the number of times each character appears in a string s. First, I want to use a for loop
for i in range(len(s)):
char = s[i]
Here, I am stuck. How would I proceed from here? Maybe I need to count how many times char appear in the string s.
Then, the output should be...
count_char("practice")
{'p' : 1, 'r' : 1, 'a' : 1, 'c' : 2, 't' : 1, 'i' : 1, 'e' : 1}
Simple Code:
def count_char(s):
result = {}
for i in range(len(s)):
result[s[i]] = s.count(s[i])
return result
print(count_char("practice"))
List comprehension code:
def count_char(s):
return {s[i]:s.count(s[i]) for i in range(len(s))}
print(count_char("practice"))
Result:
{'p': 1, 'r': 1, 'a': 1, 'c': 2, 't': 1, 'i': 1, 'e': 1}

Sort a list of dictionaries by a common key and moving unknown values to end

I have a function that returns a key function for sorted(), for which the target is a list of dicts. A working example is:
def sort2key(sortKey, **kwargs):
def attrgetter(obj):
try:
theItem = obj[sortKey]
except:
theItem = None
finally:
return theItem
return attrgetter
input = [
{'id':0, 'x': 2, 'y': 2},
{'id':1, 'x': 1, 'y': 0},
{'id':2, 'x': 0, 'y': 1}
]
theSort = {'sortKey': 'x'}
output = sorted(input, key=sort2key(**theSort))
print(input)
print(output)
>>> [{'x': 2, 'id': 0, 'y': 2}, {'x': 1, 'id': 1, 'y': 0}, {'x': 0, 'id': 2, 'y': 1}]
>>> [{'x': 0, 'id': 2, 'y': 1}, {'x': 1, 'id': 1, 'y': 0}, {'x': 2, 'id': 0, 'y': 2}]
However I want the function to be able to handle missing values:
[
{'id':0, 'x': 2, 'y': 2},
{'id':1, 'x': 1, 'y': 0},
{'id':2, 'y': 1}
]
But the previous code would force the dict with the missing x to the start - it needs to be either start or end depending on the sort setting:
{'sortKey': 'x', 'unknowns': 'toEnd'} or
{'sortKey': 'x', 'unknowns': 'toStart'}
Furthermore, the value of x in this case are numbers, but they could be strings or other types.
Is there a way to force unknown values to the end?
You can use a lambda function and the get method of dict type. Here is your code :
Input = [
{'id':0, 'x': 2, 'y': 2},
{'id':1, 'x': 1, 'y': 0},
{'id':2, 'x': 0, 'y': 1} ]
sortKey = 'id' # Use max for ToEnd setting
unknown = max( [ elt[sortKey] for elt in Input if sortKey in elt ] )
Output = sorted(Input, key=lambda X: X.get(sortKey, unknown))
for elt in Output:
print(elt)
dict.get(a, b) returns the value associated to key a if it exists or the default value b.
For mixed data you can use : max( [ str(elt[sortKey]) for elt in Input if sortKey in elt ] ) so it will be possible to compare different types values.
You can switch between ToEnd and ToStart settings just by using min/max functions.
Here is a working example using #nino_701's comment
def sort2key(sortKey, minVal, maxVal, unknowns='toEnd', **kwargs):
def attrgetter(obj):
try:
theItem = obj[sortKey]
except:
theItem = minVal if unknowns == 'toStart' else maxVal
finally:
return theItem
return attrgetter
input = [
{'id':0, 'x': 2, 'y': 2},
{'id':1, 'y': 0},
{'id':2, 'x': 0, 'y': 1}
]
theSort = {'sortKey': 'x'}
minVal = min((x[theSort['sortKey']] for x in input if theSort['sortKey'] in x))
maxVal = max((x[theSort['sortKey']] for x in input if theSort['sortKey'] in x))
output = sorted(input, key=sort2key(minVal = minVal, maxVal = maxVal, unknowns='toStart', **theSort))
output2 = sorted(input, key=sort2key(minVal = minVal, maxVal = maxVal, unknowns='toEnd', **theSort))
print(input)
print(output)
print(output2)
>>> [{'id': 0, 'y': 2, 'x': 2}, {'id': 1, 'y': 0}, {'id': 2, 'y': 1, 'x': 0}]
>>> [{'id': 1, 'y': 0}, {'id': 2, 'y': 1, 'x': 0}, {'id': 0, 'y': 2, 'x': 2}]
>>> [{'id': 2, 'y': 1, 'x': 0}, {'id': 0, 'y': 2, 'x': 2}, {'id': 1, 'y': 0}]

Mathematica Generate Binary Numbers with Locked Bits

I have a very specific Mathematica question. I am trying to generate all the binary numbers around certain 'locked' bits. I am using a list of string values to denote which bits are locked e.g. {"U","U,"L","U"}, where U is an "unlocked" mutable bit and L is a "locked" immutable bit. I start with a temporary list of random binary numbers that have been formatted to the previous list e.g. {0, 1, 1, 0}, where the 1 is the locked bit. I need to find all the remaining binary numbers where the 1 bit is constant. I've approached this problem recursively, iteratively, and with a combination of both with no results. This is for research I am doing at my university.
I am building a list of base 10 forms of the binary numbers. I realize that this code is completely wrong. This is just one attempt.
Do[
If[bits[[pos]] == "U",
AppendTo[returnList, myFunction[bits, temp, pos, returnList]]; ],
{pos, 8, 1}]
myFunction[bits_, bin_, pos_, rList_] :=
Module[{binary = bin, current = Length[bin], returnList = rList},
If[pos == current,
Return[returnList],
If[bits[[current]] == "U",
(*If true*)
If[! MemberQ[returnList, FromDigits[binary, 2]],
(*If true*)
AppendTo[returnList, FromDigits[binary, 2]];
binary[[current]] = Abs[binary[[current]] - 1],
(*If false*)
binary[[current]] = 0;
current = current - 1]; ,
(*If false*)
current = current - 1];
returnList = myFunction[bits, binary, pos, returnList];
Return[returnList]]]
You can use Tuples and Fold to generate only bit sets that you are interested in.
bits = {"U", "U", "L", "U"};
Fold[
Function[{running, next},
Insert[running, 1, next]], #, Position[bits, "L"]] & /# Tuples[{0, 1}, Count["U"]#bits]
(*
{{0, 0, 1, 0}, {0, 0, 1, 1}, {0, 1, 1, 0}, {0, 1, 1, 1},
{1, 0, 1, 0}, {1, 0, 1, 1}, {1, 1, 1, 0}, {1, 1, 1, 1}}
*)
Hope this helps.
in = IntegerDigits[Round[ Pi 10^9 ], 2];
mask = RandomSample[ConstantArray["L", 28]~Join~ConstantArray["U", 4],32];
subs[in_, mask_] := Module[ {p = Position[mask, "U"]} ,
ReplacePart[in, Rule ### Transpose[{p, #}]] & /#
Tuples[{0, 1}, Length#p]]
subs[in, mask]
{{1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1,
0, 0, 1, 0, 0, 1, 0, 1, 0}, {1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0}, {1, 0, 1,
1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0,
1, 0, 0, 1, 0, 1, 0}, {1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0}, ...
FromDigits[#, 2] & /# %
{3108030026, 3108030030, 3108038218, 3108038222, 3108095562,
3108095566, 3108103754, 3108103758, 3141584458, 3141584462,
3141592650, 3141592654, 3141649994, 3141649998, 3141658186,
3141658190}
myFunction[bits_] := Module[{length, num, range, all, pattern},
length = Length[bits];
num = 2^length;
range = Range[0, num - 1];
all = PadLeft[IntegerDigits[#, 2], length] & /# range;
pattern = bits /. {"U" -> _, "L" -> 1};
Cases[all, pattern]]
bits = {"U", "U", "L", "U"};
myFunction[bits]
{{0, 0, 1, 0}, {0, 0, 1, 1}, {0, 1, 1, 0}, {0, 1, 1, 1},
{1, 0, 1, 0}, {1, 0, 1, 1}, {1, 1, 1, 0}, {1, 1, 1, 1}}

How to draw three-dimensional image: Plot3D NDSolve

m = 10; c = 2; k = 5; F = 12;
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}]
{f, 0, 5} ( 0=< f <= 5 )
How to draw three-dimensional image:
x = u(t,f)
............
If f = 0.1,0.2,... 5,
We can solve the equation:
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}]
x is a function of t and f
...............
m = 10; c = 2; k = 5; F = 12;
f = 0.1
s = NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}]
Plot[Evaluate[x[t] /. s], {t, 0, 30}, PlotRange -> All]
f = 0.1
f = 0.2
f = 0.3
f = 5
How to draw three-dimensional image:
x = u(t,f)
Here goes a solution.
m = 10; c = 2; k = 5; F = 12;
NumberOfDiscrit$f = 20;(* Number of points you want to divide 0<=f<=5*)
NumberOfDiscrit$t = 100;(* Number of points you want to divide 0<=t<=30 *)
fValues = Range[0., 5., 5./(NumberOfDiscrit$f - 1)];
tValues = Range[0., 30., 30./(NumberOfDiscrit$t - 1)];
res = Map[(x /.
First#First#
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*#*t])*x[t] ==
F*Sin[2*Pi*#*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]) &,
fValues];
AllDat = Map[(##tValues) &, res];
InterpolationDat =
Flatten[Table[
Transpose#{tValues,
Table[fValues[[j]], {i, 1, NumberOfDiscrit$t}],
AllDat[[j]]}, {j, 1, NumberOfDiscrit$f}], 1];
Final3DFunction = Interpolation[InterpolationDat];
Plot3D[Final3DFunction[t, f], {t, 0, 30}, {f, 0, 5}, PlotRange -> All,
PlotPoints -> 60, MaxRecursion -> 3, Mesh -> None]
You can use Manipulate to dynamically change some of the parameters. By the way the above 3D picture may be misleading if one takes f as a continuous variable in u(t,f). You should note that the numerical solution seems to blow up for asymptotic values of t>>30. See the picture below.
Hope this helps you out.
You could also do something like this
Clear[f]
m = 10; c = 2; k = 5; F = 12;
s = NDSolve[{m*Derivative[2, 0][x][t, f] +
c*Derivative[1, 0][x][t, f] + (k*Sin[2*Pi*f*t])*x[t, f] == F*Sin[2*Pi*f*t],
x[0, f] == 0,
Derivative[1, 0][x][0, f] == 0}, x, {t, 0, 30}, {f, 0, .2}]
Plot3D[Evaluate[x[t, f] /. s[[1]]], {t, 0, 30}, {f, 0, .2}, PlotRange -> All]
This should do it.
m = 10; c = 2; k = 5; F = 12;
fun[f_?NumericQ] :=
Module[
{x, t},
First[x /.
NDSolve[
{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0},
x, {t, 0, 30}
]
]
]
ContourPlot[fun[f][t], {f, 0, 5}, {t, 0, 30}]
Important points:
The pattern _?NumericQ prevents fun from being evaluated for symbolc arguments (think fun[a]), and causing NDSolve::nlnum errors.
Since NDSolve doesn't appear to localize its function variable (t), we needed to do this manually using Module to prevent conflict between the t used in NDSolve and the one used in ContourPlot. (You could use a differently named variable in ContourPlot, but I think it was important to point out this caveat.)
For a significant speedup in plotting, you can use memoization, as pointed out by Mr. Wizard.
Clear[funMemo] (* very important!! *)
funMemo[f_?NumericQ] :=
funMemo[f] = Module[{x, t},
First[x /.
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] ==
F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]]]
ContourPlot[funMemo[f][t], {f, 0, 5}, {t, 0, 30}] (* much faster than with fun *)
If you're feeling adventurous, and willing to explore Mathematica a bit more deeply, you can further improve this by limiting the amount of memory the cached definitions are allowed to use, as I described here.
Let's define a helper function for enabling memoization:
SetAttributes[memo, HoldAll]
SetAttributes[memoStore, HoldFirst]
SetAttributes[memoVals, HoldFirst]
memoVals[_] = {};
memoStore[f_, x_] :=
With[{vals = memoVals[f]},
If[Length[vals] > 100, f /: memoStore[f, First[vals]] =.;
memoVals[f] ^= Append[Rest[memoVals[f]], x],
memoVals[f] ^= Append[memoVals[f], x]];
f /: memoStore[f, x] = f[x]]
memo[f_Symbol][x_?NumericQ] := memoStore[f, x]
Then using the original, non-memoized fun function, plot as
ContourPlot[memo[fun][f][t], {f, 0, 5}, {t, 0, 30}]

Select Range of SQLDateTimes

table = {{ID1, SQLDateTime[{1978, 1, 10, 0, 0, 0.`}]},
{ID2, SQLDateTime[{1999, 1, 10, 0, 0, 0.`}]},
{ID3, SQLDateTime[{2010, 9, 10, 0, 0, 0.`}]},
{ID4, SQLDateTime[{2011, 1, 10, 0, 0, 0.`}]}}
I'd like to return all cases in table in which the SQLDateTime is within the last year (DatePlus[{-1, "Year"}]). How do I specify a search for those cases?
You could also use DateDifference:
Cases[table, {a_, SQLDateTime[b_]} /;
DateDifference[b, DateList[], "Year"][[1]] <= 1]
Select[table, (AbsoluteTime[ DatePlus[{-1, "Year"}]] <=
AbsoluteTime[ #[[2, 1]]] <= AbsoluteTime[ ] &)]
(* ==> {{ID3, SQLDateTime[{2010, 9, 10, 0, 0, 0.}]},
{ID4,SQLDateTime[{2011, 1, 10, 0, 0, 0.}]}
}
*)
Small update (pre-caching of Date[], based on Leonid's comments):
With[
{date = Date[]},
Select[table,
(AbsoluteTime[ DatePlus[date, {-1, "Year"}]] <=
AbsoluteTime[ #[[2, 1]]] <= AbsoluteTime[date ] &)]
]
This also removes a problem with the original DatePlus[{-1, "Year"}] which only takes today's date into account and not the current time.

Resources