Skip to content

Commit 837af51

Browse files
committed
Clean up examples, link 04 and 05. Commented where incomplete code begins (in IM.run function).
1 parent 3d44b0d commit 837af51

File tree

9 files changed

+402
-459
lines changed

9 files changed

+402
-459
lines changed

.gitignore

65 Bytes
Binary file not shown.

famodel/installation/04_step2_actionItems.py

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,61 +14,58 @@
1414

1515
import matplotlib.pyplot as plt
1616
import os
17-
from fadesign.conceptual.conceptDesign import ConceptDesign
18-
import numpy as np
19-
from famodel.project import Project
20-
from famodel.mooring.mooring import Mooring
21-
from fadesign.conceptual import metrics as mtr
2217
import yaml
23-
import networkx as nx
2418
import pickle
25-
from . import install_helpers as inst
26-
19+
from . import vessel as V
2720

2821
# FILE LOCATIONS
2922
filePath = os.path.dirname(os.path.abspath(__file__))
3023
itemFile = os.path.join(filePath, "temp_files", "mtrlPkgs.pkl")
3124

25+
# Load package info
3226
with open(itemFile, 'rb') as f:
3327
pkgs = pickle.load(f)
3428

35-
vesselFile = os.path.join(filePath, "input_files/agent_yamls", "vesselDesc.yaml")
29+
# Load vessel info
30+
vesselsFile = os.path.join(filePath, "input_files/agent_yamls", "vesselDesc.yaml")
3631
vesselNames = ['AHTS']
3732

38-
with open(vesselFile) as file:
33+
with open(vesselsFile) as file:
3934
vesselDisc = yaml.load(file, Loader=yaml.FullLoader)
4035

36+
# Create a dictionary to hold vessel objects with the vessel names as keys
37+
vesselDict = {name: V.Vessel(vesselDisc = vesselDisc[name]) for name in vesselNames} # Filter vessel descriptions to only include specified names
38+
39+
40+
# Action list: for each vessel
41+
for name in vesselNames:
42+
vessel = vesselDict[name] # Get the vessel object
43+
44+
# Mobilization (needs to initialize before transport because transport depends on mobilization ActionItems)
45+
pkg = pkgs[0] # example
46+
mobilize = vessel.get_mobilize_action(pkg = pkg)
47+
print("Vessel State: \n", vessel.state)
48+
49+
# Transport
50+
distance2port = 250 # km [not sure where this information would be handled]
51+
transit_to = vessel.get_transit_to_action(distance2port = distance2port)
52+
print("Vessel State: \n", vessel.state)
53+
54+
# Installation
55+
pkg = pkgs[0] # example
56+
install = vessel.get_install_action(pkg = pkg)
57+
print("Vessel State: \n", vessel.state)
58+
59+
mobilize.visualize()
60+
plt.show()
61+
62+
transit_to.visualize()
63+
plt.show()
64+
65+
install.visualize()
66+
plt.show()
4167

42-
for vesselName in vesselNames:
43-
vessel = vesselDisc[vesselName]
44-
vessel['state'] = {
45-
'remaining_cargo': vessel['storage_specs']['max_cargo'],
46-
'remaining_deck_space': vessel['storage_specs']['max_deck_space'],
47-
'remaining_spool_capacity': vessel['storage_specs']['max_spool_capacity'],
48-
'assigned_materials': []
49-
}
50-
51-
# Action list:
52-
# Transport
53-
distance2port = 250 # km [not sure where this information would be handled]
54-
transport_V1 = inst.tranportTo_actionItem(vessel, distance2port)
55-
# Mobilization
56-
pkg = pkgs[0] # example
57-
mobilize_V1, vessel = inst.mobilizeM_actionItem(vessel, pkg)
58-
59-
# TODO: This seems like the same as vessel.mobilize? Are these two different approaches that are duplicates? How do we map this out?
60-
61-
print(vessel['state'])
62-
# Installation
63-
pkg = pkgs[0] # example
64-
install_V1, vessel = inst.install_actionItem(vessel, pkg)
65-
print(vessel['state'])
66-
67-
inst.visualizeAction(transport_V1)
68-
plt.show()
69-
70-
inst.visualizeAction(mobilize_V1)
71-
plt.show()
72-
73-
inst.visualizeAction(install_V1)
74-
plt.show()
68+
# Pickle the vessels for loading later
69+
output = os.path.join(filePath, "temp_files", "vessels.pkl")
70+
with open(output, 'wb') as f:
71+
pickle.dump(vesselDict, f)
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
an example of how install manager is used to register a vessel and port, and schedule an event and run (not finished yet).
3-
This is independent of 04_step2_actionItems.py and 03_step1_materialItems.py
3+
This is loads in the vessels from 04 and their respective actions.
44
55
Steps
66
-----
@@ -15,24 +15,32 @@
1515
# from fadesign.conceptual.installation.vessel import Vessel
1616
# from fadesign.conceptual.installation.port import Port
1717
from .install_manager import InstallManager as IM
18-
from pyproj import Proj, Transformer
19-
import pandas as pd
2018
import os
19+
import pickle
2120

2221
# FILE LOCATIONS
23-
filePath = os.path.dirname(os.path.abspath(__file__))
24-
vessel1_file = os.path.join(filePath, "ahts.yaml")
25-
port1_file = os.path.join(filePath, "humboldt_bay.yaml")
22+
filePath = os.path.join(os.path.dirname(os.path.abspath(__file__)))
23+
port1_file = os.path.join(filePath, "input_files/agent_yamls", "humboldt_bay.yaml")
24+
vesselsFile = os.path.join(filePath, "temp_files", "vessels.pkl")
25+
26+
# Load vessel info
27+
with open(vesselsFile, 'rb') as f:
28+
vesselDict = pickle.load(f)
2629

2730
# Initialize
2831
im = IM()
2932

3033
# Register Port
3134
im.registerPort(port1_file)
32-
# Register Vessels
33-
im.registerVessel(vessel1_file)
3435

35-
# Register vessel mob activity
36-
im.scheduleEvent(im.now, im.vesselList['3gs'], action='mob', params={"portLocation": [0, 0]}) # TODO: how does this relate to 04? In 04 you create actions. Here you schedule events and it seems like the action is defined as a method of the class (not a separate object).
36+
# Register Vessels (set up for a list of vessels, currently only one)
37+
for keys in vesselDict.keys():
38+
vessel = vesselDict[keys]
39+
# Register the vessel with the InstallManager
40+
im.registerVessel(vessel)
41+
42+
# Register vessel action (INCOMPLETE) - have not finished how to call the actions in a time loop, how time is handled, and stnadard action input/outputs. Have not considered port locations.
43+
# im.scheduleEvent(im.now, im.vesselList['AHTS'], action='mob', params={"portLocation": [0, 0]}) # Incomplete. This calls vessel.mob(), which is a function that's decoupled from the other actions in the class.
44+
im.scheduleEvent(im.now, im.vesselList['AHTS'], action=vessel.mobilize, params={"portLocation": [0, 0]}) # Incomplete. This calls vessel.mob(), which is a function that's decoupled from the other actions in the class.
3745
# Register
3846
im.run()

famodel/installation/action.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import matplotlib.pyplot as plt
2+
import networkx as nx
3+
14
"Action base class"
25

36
__author__ = "Rudy Alkarem"
@@ -122,14 +125,15 @@ def addItem(self, name, duration, cost=0, dependencies=None):
122125
-------
123126
None
124127
"""
125-
deps = []
126-
if dependencies:
127-
for dep_action, dep_item in dependencies:
128-
action = self.name if dep_action == "self" else dep_action
129-
deps.append((action, dep_item))
128+
# Old code from when dependencies were tuples of (action, item). Now are just items themselves.
129+
# deps = []
130+
# if dependencies:
131+
# for dep_action, dep_item in dependencies:
132+
# action = self.name if dep_action == "self" else dep_action
133+
# deps.append((action, dep_item))
130134

131-
item = ActionItem(name, duration, cost, deps)
132-
self.item[name] = item
135+
item = ActionItem(name, duration, cost, dependencies)
136+
self.items[name] = item
133137

134138
def get_dependencies(self, item_name):
135139
"""
@@ -160,4 +164,48 @@ def __repr__(self):
160164
out = f"Action({self.name}):\n"
161165
for name, item in self.items.items():
162166
out += f" {name}: duration={item.duration}, cost={item.cost}, deps={item.dependencies}\n"
163-
return out
167+
return out
168+
169+
170+
def visualize(self):
171+
"""
172+
Visualizes the action items as a directed graph.
173+
174+
Parameters
175+
----------
176+
action : dict
177+
The action items to be visualized.
178+
179+
Returns
180+
-------
181+
None
182+
"""
183+
# Create the graph
184+
G = nx.DiGraph()
185+
for key in self.items.keys():
186+
item = self.items[key]
187+
for dep in item.dependencies:
188+
G.add_edge(dep, item, duration=item.duration) # Store duration as edge attribute
189+
190+
# Compute longest path & total duration
191+
longest_path = nx.dag_longest_path(G, weight='duration')
192+
longest_path_edges = list(zip(longest_path, longest_path[1:])) # Convert path into edge pairs
193+
total_duration = sum(node.duration for node in longest_path)
194+
195+
if len(longest_path)>=1:
196+
last_node = longest_path[-1] # Identify last node of the longest path
197+
# Define layout
198+
pos = nx.shell_layout(G)
199+
# Draw all nodes and edges (default gray)
200+
nx.draw(G, pos, with_labels=True, labels = {node: node.name for node in G.nodes()}, node_size=500, node_color='skyblue', font_size=10, font_weight='bold', font_color='black', edge_color='gray')
201+
202+
# Highlight longest path in red
203+
nx.draw_networkx_edges(G, pos, edgelist=longest_path_edges, edge_color='red', width=2)
204+
205+
# Annotate last node with total duration in red
206+
plt.text(pos[last_node][0], pos[last_node][1] - 0.1, f"{total_duration:.2f} hr", fontsize=12, color='red', fontweight='bold', ha='center')
207+
208+
plt.suptitle(f"Action: {self.name} - Total Duration: {total_duration:.2f} hr")
209+
210+
else:
211+
pass

famodel/installation/input_files/agent_yamls/ahts.yaml

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)