Skip to content

DUMMY-PR#13

Closed
GREENRAT-K405 wants to merge 1 commit intoControlCore-Project:mainfrom
GREENRAT-K405:main
Closed

DUMMY-PR#13
GREENRAT-K405 wants to merge 1 commit intoControlCore-Project:mainfrom
GREENRAT-K405:main

Conversation

@GREENRAT-K405
Copy link
Contributor

Implement non-heuristic Best-First Search (UCS) for city mapping using an adjacency matrix and priority queue. The program finds the shortest path from Syracuse to Chicago and displays the explored paths and costs.

Implement non-heuristic Best-First Search (UCS) for city mapping using an adjacency matrix and priority queue. The program finds the shortest path from Syracuse to Chicago and displays the explored paths and costs.
@GREENRAT-K405
Copy link
Contributor Author

/gemini-review

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Gemini AI Code Review

Found 5 suggestions for improvement:

  • 💡 Medium: 5

This review was automatically generated by Gemini AI. Please review the suggestions carefully.

self.state = state # Current City Index
self.parent = parent # Parent Node
self.action = action # Next City Index
self.path_cost = path_cost # Total Distance from start node to current node

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PriorityQueue implementation is inefficient. The add method sorts the entire list (O(N log N)), and the pop method uses list.pop(0) (O(N)). For a graph with V vertices and E edges, this can lead to a time complexity significantly worse than optimal, especially for dense graphs or many expansions.

Python's built-in heapq module provides an efficient implementation of a min-heap, which is suitable for a priority queue. Using heapq.heappush and heapq.heappop would reduce the complexity of add and pop to O(log N), greatly improving performance.

(11,12,50),(11,13,107), # Bos: Pro 50, Por 107
(12,8,181) # Pro: NY 181 (Already covered)
]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The adj adjacency matrix is initialized twice. The first initialization on line 40 is redundant and can be removed, as it's re-initialized immediately after the edges and edges_clean definitions.

--- a/non-heuristic-BeFS-lab4.py
+++ b/non-heuristic-BeFS-lab4.py
@@ -37,9 +37,6 @@
     13: "Portland"
 }
 
-n = 14
-
-# adjacency matrix
-adj = [[0 for _ in range(n)] for _ in range(n)]
-
 edges = [
     (0,1,283),(0,2,354),(0,3,182), # Chicago: Det 283, Cle 354 (corrected from 345 in snippet to match prompt data), Ind 182
     (1,2,169),(1,6,256),           # Detroit: Cle 169, Buf 256

9: "Philadelphia",
10: "Baltimore",
11: "Boston",
12: "Providence",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are extensive comments regarding inconsistencies or questions about the edge data (e.g., "Chi 345 mismatch? Q1.py says Cle-Chi 345, Chi-Cle 354? Asymmetric? Map is usually symmetric."). While it's good to note potential issues during development, it's best practice to resolve these data discrepancies and present a clean, verified set of edges in the final code.

Consider clarifying the source of truth for the edge weights or ensuring that the edges_clean list is the definitive, corrected dataset, and remove the commented-out edges list entirely to avoid confusion.

(7,8,254), (7,11,312), # Syr: NY 254, Bos 312
(8,9,97), (8,12,181), (8,11,215), # NY: Phi 97, Pro 181, Bos 215
(9,10,101), # Phi: Bal 101
(11,12,50), (11,13,107) # Bos: Pro 50, Por 107

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The action field in the Node class is set to s_prime, which is the state of the child node. This makes action redundant as it holds the same information as the state of the child node. For path reconstruction, node.parent and node.state are sufficient.

While it doesn't cause a bug, it can be confusing. If action is meant to describe how we transitioned from parent.state to node.state, it might be better to remove it if unused, or make its purpose clearer (e.g., if it were a specific type of 'move' or 'edge label' beyond just the destination city).


def EXPAND(problem, node):
s = node.state
for action in problem.ACTIONS(s):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BEST_FIRST_SEARCH implementation, due to the custom PriorityQueue not supporting efficient updates or removal of existing elements, can lead to duplicate nodes (representing the same state but with different path_costs) being present in the frontier. While the reached array ensures that only the path with the lowest cost is eventually stored and used for path reconstruction, the algorithm might still extract and expand suboptimal duplicate nodes from the frontier before the optimal one is processed.

This is a common inefficiency in simpler UCS implementations. An optimized approach would involve using a heapq (as suggested earlier) and a mechanism to either update the priority of a node already in the frontier or mark older entries as invalid so they are skipped when popped.

@GREENRAT-K405
Copy link
Contributor Author

hello @pradeeban sir, it's working!

@pradeeban
Copy link
Member

That is awesome. Thanks, @GREENRAT-K405. If you make the same PR to the other two repositories (concore and concore-editor), I will merge those as well.

@pradeeban pradeeban closed this Feb 11, 2026
@GREENRAT-K405
Copy link
Contributor Author

@pradeeban , @Rahuljagwani

Best part:

  • anyone can use it.
  • maintainers can use this bot in following way
  • /gemini-review then give some custom instructions and inject prompts in the comment itself like
image

While we are at it, these are some limitations:

  • it won't be as descriptive as a full on copilot like ai review that comes with very premium versions
  • the gemini bot review that you are seeing in some of the beehive pull request isn't actually this bot, those are done by github extended gemini app.
  • contributors have to type the "/gemini-review" to use this feature (if they forget, maintainers can also do it for them)
  • adding custom prompts/instructions in the yaml file won't be of much use since that is out of practice.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Gemini AI Code Review

Found 3 suggestions for improvement:

  • 💡 Medium: 3

This review was automatically generated by Gemini AI. Please review the suggestions carefully.

self.state = state # Current City Index
self.parent = parent # Parent Node
self.action = action # Next City Index
self.path_cost = path_cost # Total Distance from start node to current node

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance: Inefficient Priority Queue Implementation

The current PriorityQueue implementation has significant performance drawbacks, especially for larger graphs or more complex search problems.

  1. add method: self.data.sort(key=self.f) sorts the entire list every time a new node is added. This operation has a time complexity of O(N log N), where N is the number of elements in the queue. For a priority queue, insertion should ideally be O(log N).
  2. pop method: self.data.pop(0) removes the first element from a list, which requires shifting all subsequent elements. This operation has a time complexity of O(N).

Combined, these lead to a much slower search algorithm than necessary. Python's built-in heapq module provides an efficient min-heap implementation, which is ideal for priority queues. Using heapq.heappush for add and heapq.heappop for pop would bring the complexity down to O(log N) for both operations, significantly improving performance.

Consider replacing the custom PriorityQueue with heapq for better scalability and efficiency.

def ACTION_COST(self, s, action, s_prime):
return adj[s][s_prime]

def EXPAND(problem, node):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability/Clarity: Ambiguous action variable

The action variable in the Node class and Problem methods (specifically RESULT) is defined as the "Next City Index" or the action to take. However, in RESULT(self, state, action), it directly returns action, meaning action is the s_prime (the next state). While functionally correct for this specific graph representation where an 'action' to move to a city is simply the city itself, it can be a bit confusing.

For improved clarity and maintainability, especially if the problem domain were to evolve (e.g., actions could be 'take bus', 'fly', etc., with different costs/results), it might be clearer to explicitly separate the concept of an action from the state it results in. For this simple graph, it's acceptable, but it's a point to be aware of for future extensions.

def BEST_FIRST_SEARCH(problem, f):
node = Node(problem.INITIAL) # Start Node

frontier = PriorityQueue(f)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor Inefficiency: Duplicate adj matrix initialization

The adj matrix is initialized twice:

  1. adj = [[0 for _ in range(n)] for _ in range(n)] on line 21.
  2. adj = [[0 for _ in range(n)] for _ in range(n)] on line 51.

The first initialization is immediately overwritten by the second one after the edges and edges_clean lists are defined. While this doesn't cause a bug, it's redundant and can be removed, making the code slightly cleaner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants