Finding a specific "route" through a network simulator - python

I'm writing something for a game that involves networks. In this game, a network is a class and the "connections" to each node are formatted like:
network.nodes = [router, computer1, computer2]
network.connections = [ [1, 2], [0], [0] ]
Each iteration in "network.nodes" works in parallel with each iteration in "network.connections", meaning "network.connections[0]" represents all the nodes "network.nodes[0]" is connected to. I'm trying to write a simple function in the network class that finds a route starting from the router - "network.connections[0]" - and then to a specific "node". The more thought I put into this, the more complicated the answer seems to be.
In this, rather simple case it should return something like
[router, computer1]
That's what I'd like to see if I was trying to find a route to "computer1", but I need something that will work with more complicated network simulations.
It's basically a simulator for a computer network. But in this game, I need to be able to know exactly which nodes something might travel though to reach a specific target.
Any help would be greatly appreciated. Thanks.

How about dropping the .nodes and .connections and just keeping them in one data structure like a dictionary.
network.nodes = {"router": [computer1, computer2],
"computer1": [router],
"computer2": [router]
}
You could even drop the strings as keys and use the objects themselves:
network.nodes = {router: [computer1, computer2],
computer1: [router],
computer2: [router]
}
That way if you need to access the the connections for the router you would do:
>>>network.nodes[router]
[computer1, computer2]
Because I don't have a full overview of your project, I can't just give you a function to do that, but I can try and point you in the right direction.
If you build the network 'map' up as a dictionary, and network.nodes[router] returns [computer1, computer2], the next thing you would need to do is network.nodes[computer1] and network.nodes[computer2].
In your firewall example from the comments, you would rebuild the network map to include the firewall. So the dictionary would look like this:
network.nodes = {router: [firewall, computer2],
firewall: [computer1]
computer1: [firewall],
computer2: [router]
}

Related

Design pattern for a data parsing&feature engineering pipeline

I know this question has been asked a few times on these boards in the past, but I have a more generic version of it, which might be applicable to someone else's projects in the future as well.
In short - I am building an ML system (with Python, but language choice in this case is not very critical), which has its ML model at the end of a pipeline of actions happening:
Data upload
Data parsing
Feature engineering
Feature engineering (in a different logical bracket from prev. step)
Feature engineering (in a different logical bracket from prev. steps)
... (more steps like the last 3)
Data passed to ML model
Each of the above steps, has its own series of actions it must take, in order to build a proper output, which is then used as an input in the next one etc. These sub-steps in turn, can either be completely decoupled from one another, or some of them might need some steps inside of that big step, to be completed first, to produce data these following steps use.
The thing right now is, that I need to build a custom pipeline, which will make it super easy to add new steps into the mix (both big and small), without upsetting the existing ones.
So far, I have this concept idea of how this might look like from an architecture perspective, as shown below:
While looking at this architecture, I am immediately thinking about a Chain of Responsibility Design Pattern, which manages BIG STEPS (1, 2, ..., n), and each of these BIG STEPS having their own small version of Chain of Responsibility happening inside of their guts, which happen independently for NO_REQ steps, and then for REQ steps (with REQ steps looping-over until they are all done). With a shared interface for running logic inside of big and small steps, it would probably run rather neatly.
Yet, I am wondering, if there is any better way of doing it? Moreover, what I do not like about a Chain of Responsibility, is that it would require a person adding new BIG/SMALL step, to always edit the "guts" of the logic setting up step bags, to manually include the newly added step. I would love to build something, which instead would just scan a folder specific to steps under each BIG STEP, and build a list of NO_REQ and REQ steps on its own (to uphold the Open/Closed SOLID principle).
I would be grateful for any ideas.
I did something similar recently. Challenge is to allow "steps" to be plugged in easily without much changes. So, what I did was, something like below. Core idea is to define interface 'process' and fix input and output format.
Code:
class Factory:
def process(self, input):
raise NotImplementedError
class Extract(Factory):
def process(self, input):
print("Extracting...")
output = {}
return output
class Parse(Factory):
def process(self, input):
print("Parsing...")
output = {}
return output
class Load(Factory):
def process(self, input):
print("Loading...")
output = {}
return output
pipeline = {
"Extract" : Extract(),
"Parse" : Parse(),
"Load" : Load(),
}
input_data = {} #vanilla input
for process_name, process_instance in pipeline.items():
output = process_instance.process(input_data)
input_data = output
Output:
Extracting...
Parsing...
Loading...
So, in case you need to add a 'step', 'append_headers' after parse, all you need to do is,
#Defining a new step.
class AppendHeaders(Factory):
def process(self, input):
print("adding headers...")
output = {}
return output
pipeline = {
"Extract" : Extract(),
"Append headers": AppendHeaders(), #adding a new step
"Parse" : Parse(),
"Load" : Load(),
}
New output:
Extracting...
adding headers...
Parsing...
Loading...
Additional requirement in your case where, you might want to scan specific folder for REQ/NOT_REQ, can be added as field in json and load it into pipeline, meaning, create those "steps" objects only if flag is set to REQ.
Not sure how much this idea can help. Thought, I will convey my thoughts.

Linking two fields in 2 different nodes created proceduraly

I am creating a nuke node to easily manipulate my different lights in a node. I want to code it so that it doesn't matter how many lights are in any given file, and the code can figure it out and display the necessary tools to modify them. To achieve this, I first identify how many lights are in the file and store that value, which then gets fed to a 'for' cycle to create as many nodes and tools as lights are on the original file. 'tempNumber' is the number assigned to the original Lights on the file, and it helps create and manage all the tools, labeled to match the light they are modifying. It becomes complicated because the names of the nodes generated look like this:
globals()['expoParent{}'.format(tempNumber)]
Up to now everything has been working fine but I am stuck trying to link two different Exposure nodes to reflect the same values as the user modifies them. I created this code for that purpose on a separate script:
par = nuke.nodes.EXPTool(mode = 'Stops', name = 'Parent')
chi = nuke.nodes.EXPTool(mode = 'Stops', name = 'Child')
par.knob('knobChanged').setValue('chi["red"].setValue(par["red"].value())\nchi["green"].setValue(par["green"].value())\nchi["blue"].setValue(par["blue"].value())')
This previous bit of code works perfectly, it creates 2 Exposure nodes and it links the Child to the Parent so that any change made to the Parent is then automatically passed along to the Child immediately. Now the problem comes when I try to replace the variables par and chi with globals()['expoParent{}'.format(tempNumber)] and globals()['expoChild{}'.format(tempNumber)] . At this point the code stops working and the link is not successful. I have read plenty of people saying that variables should not be created through a for loop but I don't see any other way of doing it.
Why do it with a knobChanged function at all when you can just link the node fields with expressions?
Here's an example that links two grade nodes (Grade1 and Grade2) with Grade1 as the parent. You'll need to have these in your script before running the code. Though you could also create them procedurally.
parent = nuke.toNode('Grade1')
child = nuke.toNode('Grade2')
child['multiply'].setExpression('%s.multiply' % parent.name())
This is a lot cleaner, and would be represented visually in the node tree too.

module interconnection interface design

I want to have some simple interfaces for the users to connect some pre-defined modules (I'm free to modify them if I have to).
Each module has a few named inputs and outputs.
One module may connect to a few modules.
A few modules can connect to a single module.
This is what I have in my mind so far:
Option 1:
Each module has "in" and "out" dictionary for input and output, and the connection is made through code like this:
a.out["out 1"].to(b.in["in 1"]) # connect a's "out 1" output to b's "in 1" input
a.out["out 2"].to(b.in["in 2"]) # connect a's "out 2" output to b's "in 2" input
But this looks quite tedious, so I came up with Option 2:
# connect a to b and c, then list which inputs connect to which outputs
a.to(b,{"out 1":"in 1",
"out 2":"in 2"},
c,{"out 4":"in 1",
"out 3":"in 2"})
This seems to look better as it's clearer to me which modules are connected and also the mapping between their outputs and inputs are clearly listed.
I wonder if there is any room to improve the above, to clearly show:
module level connections, e.g. module a connect to module b
outputs and inputs connections
simple and clear interface. By 'simple', I mean less typing; 'clear' means easy to understand. I understand that sometimes I can't have both in that case, 'clear' interface is preferable.
I'm not proficient in Python(2.7) so there might be some syntax or operator or data structure that I am not aware of but I may be able to take advantage for this purpose.
I have run into this exact issue, the issue of being able to clearly describe directed graphs linearly. None are particularly pleasant... Personally, I believe showing how the sources and sinks (node inputs and outputs) connect is more important than showing which nodes are connected, because the relationship is more specific.
Of the two designs you listed I would recommend the first, since it is clearer. It shows exactly how each input and output connects. However, I would slightly augment your implementation. I would make the node class capable of creating new handles for inputs and outputs that are actual attributes in the object. Then use those handles when describing the graph and capturing traffic, etc. Making the inputs and outputs actual objects instead of labels means construction-time checking and the ability to generate better error messages. For example:
b = Node()
b.input("in1", "in2") # this creates a new input object that is located in 'b' with the attribute name of the given string
b.output("out1") # this could be in the constructor
c = Node(in=["in1", "in2"], out=["out1"]) # like so
# describe the connections
a.out1.to(b.in1)
a.out2.to(b.in2)
a.out3.to(c.in2)
a.out4.to(c.in1)
# maybe syntax like 'a.out3 >> c.in2' would be prettier?
module_graph_output = c.out1.capture()
# do stuff with the graph output
Additionally, the module definitions can be passed these output and input object handlers for the user as they implement the module logic.
All this aside, how you are going to run the module graph is the bigger issue. If I'm not intruding, what is the application of this?

Python How to avoid many if statements

I'll try to simplify my problem. I'm writing a test program using py.test and appium. Now:
In the application I have 4 media formats: Video, Audio, Image and Document.
I have a control interface with previous, next, play , stop buttons.
Each media formats has a unique ID like
video_playbutton, audio_playbutton, document_playbutton, image_playbutton, video_stopbutton audio_stopbutton ...etc etc.
But the operation I have to do is the same for all of them e.g press on playbutton.
I can address playbutton of each when i give them explicitly like this
find_element_by_id("video_playbutton")
And when i want to press on other playbuttons I've to repeat above line each time. Like this:
find_element_by_id("video_playbutton")
find_element_by_id("audio_playbutton")
find_element_by_id("image_playbutton")
find_element_by_id("document_playbutton")
And because I'm calling this function from another script I would have to distinguish first what string I got e.g:
def play(mediatype):
if mediatype == "video"
el = find_element_by_id("video_playbutton")
el.click()
if mediatype == "audio"
el = find_element_by_id("audio_playbutton")
el.click()
if .....
What is the best way to solve this situation? I want to avoid hundreds of if-statements because there is also stop, next , previous etc buttons.
I'm rather searching for something like this
def play(mediatype)
find_element_by_id(mediatype.playbutton)
You can separate out the selectors and operations in two dictionaries which scales better. Otherwise the mapping eventually gets huge. Here is the example.
dictMedia = {'video':['video_playbutton', 'video_stopbutton','video_nextbutton'], 'audio':['audio_playbutton', 'audio_stopbutton', 'audio_nextbutton']}
dictOperations = {'play':0, 'stop':1, 'next':2}
def get_selector(mediatype, operation):
return dictMedia[mediatype][dictOperations[operation]]
print get_selector('video', 'play')
PS: The above operation doesn't check for key not found errors.
However, I still feel, if the media specific operations grow, then a page object model would be better.

libtorrent dht peer request?

Ive been playing around with the python bindings for libtorrent/rasterbar.
What I wanted to do was generate a new 'node-id' and reannounce it to the other nodes.
I read that a 'bencoded dicionary' needs to be created and I assume announced using something like force_dht_reannounce, is this correct?
You can force libtorrent to use a specific node ID for the DHT by crafting a session-state file, and feed it to the session::load_state() function. Once you do this, you also need to restart the DHT by calling session::stop_dht() followed by session::start_dht().
The relevant parts of the session state you need to craft have the following format (bencoded):
{
"dht state": {
"node-id": "<20-byte binary node-ID>"
}
}
If you want to keep the rest of the session state, it might be a good idea to first call session::save_state() and then simply insert/overwrite the node-id field.
Something like this:
state = ses.save_state()
state["dht state"]["node-id"] = "<...>";
ses.load_state(state)
ses.stop_dht()
ses.start_dht()

Categories

Resources