practical08 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- practical08-0.4.0/LICENSE +14 -0
- practical08-0.4.0/PKG-INFO +51 -0
- practical08-0.4.0/README.md +37 -0
- practical08-0.4.0/pyproject.toml +23 -0
- practical08-0.4.0/setup.cfg +4 -0
- practical08-0.4.0/src/practical08/__init__.py +165 -0
- practical08-0.4.0/src/practical08.egg-info/PKG-INFO +51 -0
- practical08-0.4.0/src/practical08.egg-info/SOURCES.txt +9 -0
- practical08-0.4.0/src/practical08.egg-info/dependency_links.txt +1 -0
- practical08-0.4.0/src/practical08.egg-info/top_level.txt +1 -0
- practical08-0.4.0/tests/test_package.py +28 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Practical08 Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the conditions of the MIT License.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
13
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
14
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: practical08
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Searchable AIML practical program library with simple ask interface
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Keywords: education,machine-learning,practicals,jupyter
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Topic :: Education
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# Practical08
|
|
16
|
+
|
|
17
|
+
Finalized question-to-code library containing 30 AIML practical programs from Units IV, V and VI.
|
|
18
|
+
|
|
19
|
+
## Simple Jupyter use
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
%pip install --upgrade practical08
|
|
23
|
+
from practical08 import ask
|
|
24
|
+
|
|
25
|
+
ask("Write a program for DBSCAN clustering")
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`ask(question)` prints the best matching program, a brief explanation, the complete code and required libraries. It does not print an extra dictionary afterward.
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
ask("Implement Random Forest classifier")
|
|
34
|
+
ask("Calculate discounted return using gamma")
|
|
35
|
+
ask("Find frequent items using Apriori")
|
|
36
|
+
ask("Update Q value using Q-Learning")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Optional exact lookup
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from practical08 import get_program
|
|
43
|
+
print(get_program("IV04")["code"])
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Search behavior
|
|
47
|
+
- Recognizes aliases such as DBSCAN / density-based clustering, XGBoost / extreme gradient boosting, and Q-learning / Q value update.
|
|
48
|
+
- Uses topic-focused scoring and rejects weak matches instead of silently selecting unrelated programs.
|
|
49
|
+
- No AI API key is required; matching uses Python's standard library and works offline after installation.
|
|
50
|
+
- Some returned examples need additional packages (e.g. `scikit-learn`, `numpy`, or `xgboost`) to execute.
|
|
51
|
+
- `ask()` prints code but never executes it automatically.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Practical08
|
|
2
|
+
|
|
3
|
+
Finalized question-to-code library containing 30 AIML practical programs from Units IV, V and VI.
|
|
4
|
+
|
|
5
|
+
## Simple Jupyter use
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
%pip install --upgrade practical08
|
|
9
|
+
from practical08 import ask
|
|
10
|
+
|
|
11
|
+
ask("Write a program for DBSCAN clustering")
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`ask(question)` prints the best matching program, a brief explanation, the complete code and required libraries. It does not print an extra dictionary afterward.
|
|
15
|
+
|
|
16
|
+
## Examples
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
ask("Implement Random Forest classifier")
|
|
20
|
+
ask("Calculate discounted return using gamma")
|
|
21
|
+
ask("Find frequent items using Apriori")
|
|
22
|
+
ask("Update Q value using Q-Learning")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Optional exact lookup
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from practical08 import get_program
|
|
29
|
+
print(get_program("IV04")["code"])
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Search behavior
|
|
33
|
+
- Recognizes aliases such as DBSCAN / density-based clustering, XGBoost / extreme gradient boosting, and Q-learning / Q value update.
|
|
34
|
+
- Uses topic-focused scoring and rejects weak matches instead of silently selecting unrelated programs.
|
|
35
|
+
- No AI API key is required; matching uses Python's standard library and works offline after installation.
|
|
36
|
+
- Some returned examples need additional packages (e.g. `scikit-learn`, `numpy`, or `xgboost`) to execute.
|
|
37
|
+
- `ask()` prints code but never executes it automatically.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "practical08"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "Searchable AIML practical program library with simple ask interface"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
keywords = ["education", "machine-learning", "practicals", "jupyter"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Topic :: Education",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[tool.setuptools]
|
|
20
|
+
package-dir = {"" = "src"}
|
|
21
|
+
|
|
22
|
+
[tool.setuptools.packages.find]
|
|
23
|
+
where = ["src"]
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""PracticalPrep: retrieve stored practical programs by natural-language question."""
|
|
2
|
+
from difflib import SequenceMatcher
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
_PROGRAMS = [{'id': 'IV01', 'unit': 'IV', 'topic': 'K-Means clustering', 'statement': 'Apply K-Means clustering to group data points.', 'keywords': ['kmeans', 'clustering', 'partition', 'groups'], 'code': "from sklearn.cluster import KMeans\nimport numpy as np\n\nX = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])\nk = int(input('Enter number of clusters: '))\nmodel = KMeans(n_clusters=k, random_state=42, n_init=10)\nlabels = model.fit_predict(X)\nprint('Cluster labels:', labels)\nprint('Centroids:\\n', model.cluster_centers_)", 'explanation': 'K-Means assigns each point to one of k clusters and updates cluster centers.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'IV02', 'unit': 'IV', 'topic': 'Hierarchical clustering', 'statement': 'Perform agglomerative hierarchical clustering.', 'keywords': ['hierarchical', 'agglomerative', 'dendrogram', 'clustering'], 'code': "from sklearn.cluster import AgglomerativeClustering\nimport numpy as np\n\nX = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])\nk = int(input('Enter number of clusters: '))\nmodel = AgglomerativeClustering(n_clusters=k)\nprint('Cluster labels:', model.fit_predict(X))", 'explanation': 'Agglomerative clustering starts with individual points and repeatedly merges nearby clusters.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'IV03', 'unit': 'IV', 'topic': 'Apriori frequent items', 'statement': 'Find frequent single items in a transaction dataset using minimum support.', 'keywords': ['apriori', 'frequent', 'itemsets', 'transactions', 'support'], 'code': "transactions = [\n ['bread', 'milk'], ['bread', 'diaper', 'beer', 'eggs'],\n ['milk', 'diaper', 'beer', 'cola'], ['bread', 'milk', 'diaper', 'beer'],\n ['bread', 'milk', 'diaper', 'cola']\n]\nmin_support = int(input('Minimum support count: '))\ncounts = {}\nfor transaction in transactions:\n for item in set(transaction):\n counts[item] = counts.get(item, 0) + 1\nprint('Frequent items:')\nfor item, count in sorted(counts.items()):\n if count >= min_support:\n print(item, 'support =', count)", 'explanation': 'This compact Apriori-style demonstration counts frequent individual items. Full Apriori also generates and tests item combinations.', 'libraries': ['standard library']}, {'id': 'IV04', 'unit': 'IV', 'topic': 'DBSCAN clustering', 'statement': 'Group data using density-based spatial clustering and identify noise points.', 'keywords': ['dbscan', 'density', 'based', 'clustering', 'noise', 'eps', 'min_samples'], 'code': "from sklearn.cluster import DBSCAN\nimport numpy as np\n\nX = np.array([[1, 2], [2, 2], [2, 3], [8, 7], [8, 8], [25, 80]])\neps = float(input('Enter eps: '))\nmin_samples = int(input('Enter min_samples: '))\nlabels = DBSCAN(eps=eps, min_samples=min_samples).fit_predict(X)\nprint('Cluster labels:', labels)\nprint('-1 represents noise/outliers.')", 'explanation': 'DBSCAN forms dense regions into clusters; points labelled -1 are treated as noise.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'IV05', 'unit': 'IV', 'topic': 'WCSS calculation', 'statement': 'Calculate within-cluster sum of squares for K-Means.', 'keywords': ['wcss', 'inertia', 'within', 'cluster', 'sum', 'squares', 'elbow'], 'code': "from sklearn.cluster import KMeans\nimport numpy as np\n\nX = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])\nk = int(input('Enter number of clusters: '))\nmodel = KMeans(n_clusters=k, random_state=42, n_init=10).fit(X)\nprint('WCSS:', model.inertia_)", 'explanation': 'WCSS is the sum of squared distances from points to their assigned cluster centers; scikit-learn exposes it as inertia_.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'IV06', 'unit': 'IV', 'topic': 'Silhouette score per point', 'statement': 'Calculate silhouette score for every data point.', 'keywords': ['silhouette', 'samples', 'score', 'each', 'point', 'clustering'], 'code': "from sklearn.cluster import KMeans\nfrom sklearn.metrics import silhouette_samples\nimport numpy as np\n\nX = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])\nk = int(input('Enter number of clusters (2 to n-1): '))\nlabels = KMeans(n_clusters=k, random_state=42, n_init=10).fit_predict(X)\nprint('Silhouette scores:', silhouette_samples(X, labels))", 'explanation': 'Silhouette scores range from -1 to 1; higher values generally indicate better-separated clusters.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'IV07', 'unit': 'IV', 'topic': 'Davies-Bouldin Index', 'statement': 'Evaluate clustering quality using Davies-Bouldin Index.', 'keywords': ['davies', 'bouldin', 'index', 'clustering', 'evaluation'], 'code': "from sklearn.cluster import KMeans\nfrom sklearn.metrics import davies_bouldin_score\nimport numpy as np\n\nX = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])\nk = int(input('Enter number of clusters: '))\nlabels = KMeans(n_clusters=k, random_state=42, n_init=10).fit_predict(X)\nprint('Davies-Bouldin Index:', davies_bouldin_score(X, labels))", 'explanation': 'Lower Davies-Bouldin Index values generally indicate more compact, better-separated clusters.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'IV08', 'unit': 'IV', 'topic': 'Threshold anomaly detection', 'statement': 'Detect anomalies using a numeric threshold.', 'keywords': ['threshold', 'anomaly', 'outlier', 'detection'], 'code': "values = [10, 12, 11, 13, 80, 9, 12]\nthreshold = float(input('Enter anomaly threshold: '))\nfor i, value in enumerate(values):\n if value > threshold:\n print('Anomaly at index', i, ':', value)", 'explanation': 'A value is flagged when it crosses the chosen threshold. The threshold should suit the data and problem.', 'libraries': ['standard library']}, {'id': 'IV09', 'unit': 'IV', 'topic': 'Group documents by common words', 'statement': 'Find common words in two documents.', 'keywords': ['documents', 'common', 'words', 'text', 'intersection'], 'code': "doc1 = 'machine learning helps analyse data'\ndoc2 = 'data science uses machine learning'\nwords1 = set(doc1.lower().split())\nwords2 = set(doc2.lower().split())\nprint('Common words:', sorted(words1 & words2))", 'explanation': 'Convert document words into sets and use set intersection to find shared words.', 'libraries': ['standard library']}, {'id': 'IV10', 'unit': 'IV', 'topic': 'Retail customer segmentation', 'statement': 'Segment retail customers by annual income and spending score.', 'keywords': ['retail', 'customer', 'segmentation', 'income', 'spending', 'kmeans'], 'code': "from sklearn.cluster import KMeans\nimport numpy as np\n\ncustomers = np.array([[15, 39], [16, 81], [17, 6], [18, 77], [19, 40], [20, 76]]) # income, spending score\nk = int(input('Enter number of segments: '))\nlabels = KMeans(n_clusters=k, random_state=42, n_init=10).fit_predict(customers)\nfor i, label in enumerate(labels, start=1):\n print(f'Customer {i}: Segment {label}')", 'explanation': 'K-Means groups customers with similar income and spending-score patterns.', 'libraries': ['scikit-learn', 'numpy']}, {'id': 'V01', 'unit': 'V', 'topic': 'Max voting ensemble', 'statement': 'Combine classifier predictions using majority voting.', 'keywords': ['max', 'voting', 'majority', 'vote', 'ensemble', 'classifier'], 'code': "from collections import Counter\n\npredictions = ['Yes', 'No', 'Yes', 'Yes', 'No']\ncounts = Counter(predictions)\nprint('Vote counts:', counts)\nprint('Final prediction:', counts.most_common(1)[0][0])", 'explanation': 'The class receiving the most votes becomes the ensemble prediction.', 'libraries': ['standard library']}, {'id': 'V02', 'unit': 'V', 'topic': 'Averaging predictions', 'statement': 'Combine numerical predictions by averaging them.', 'keywords': ['averaging', 'predictions', 'regression', 'ensemble'], 'code': "predictions = [120.5, 118.0, 123.5]\nprint('Average prediction:', sum(predictions) / len(predictions))", 'explanation': 'Averaging is commonly used to combine numeric outputs from multiple regression models.', 'libraries': ['standard library']}, {'id': 'V03', 'unit': 'V', 'topic': 'Weighted averaging', 'statement': 'Combine predictions using assigned model weights.', 'keywords': ['weighted', 'average', 'predictions', 'ensemble'], 'code': "predictions = [120.5, 118.0, 123.5]\nweights = [0.5, 0.3, 0.2]\nif len(predictions) != len(weights) or abs(sum(weights) - 1.0) > 1e-8:\n raise ValueError('Weights must match predictions and sum to 1.')\nprint('Weighted prediction:', sum(p*w for p, w in zip(predictions, weights)))", 'explanation': 'Models with larger weights contribute more. These example weights sum to one.', 'libraries': ['standard library']}, {'id': 'V04', 'unit': 'V', 'topic': 'Bagging ensemble', 'statement': 'Train a bagging classifier using bootstrap samples.', 'keywords': ['bagging', 'bootstrap', 'aggregation', 'classifier'], 'code': "from sklearn.ensemble import BaggingClassifier\nfrom sklearn.tree import DecisionTreeClassifier\nfrom sklearn.datasets import load_iris\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = load_iris(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\nmodel = BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=10, random_state=42)\nmodel.fit(X_train, y_train)\nprint('Accuracy:', accuracy_score(y_test, model.predict(X_test)))", 'explanation': 'Bagging trains models on bootstrap samples and aggregates their predictions.', 'libraries': ['scikit-learn']}, {'id': 'V05', 'unit': 'V', 'topic': 'AdaBoost classifier', 'statement': 'Train an AdaBoost classifier using decision stumps.', 'keywords': ['adaboost', 'adaptive', 'boosting', 'decision', 'stump'], 'code': "from sklearn.ensemble import AdaBoostClassifier\nfrom sklearn.tree import DecisionTreeClassifier\nfrom sklearn.datasets import load_iris\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = load_iris(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\nstump = DecisionTreeClassifier(max_depth=1, random_state=42)\nmodel = AdaBoostClassifier(estimator=stump, n_estimators=50, random_state=42)\nmodel.fit(X_train, y_train)\nprint('Accuracy:', accuracy_score(y_test, model.predict(X_test)))", 'explanation': 'AdaBoost gives more attention to examples previous weak learners classified incorrectly.', 'libraries': ['scikit-learn']}, {'id': 'V06', 'unit': 'V', 'topic': 'Gradient Boosting classifier', 'statement': 'Train a Gradient Boosting classifier and evaluate accuracy.', 'keywords': ['gradient', 'boosting', 'classifier', 'sequential', 'trees'], 'code': "from sklearn.ensemble import GradientBoostingClassifier\nfrom sklearn.datasets import load_iris\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = load_iris(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\nmodel = GradientBoostingClassifier(random_state=42)\nmodel.fit(X_train, y_train)\nprint('Accuracy:', accuracy_score(y_test, model.predict(X_test)))", 'explanation': 'Gradient Boosting adds weak learners sequentially to improve on earlier errors.', 'libraries': ['scikit-learn']}, {'id': 'V07', 'unit': 'V', 'topic': 'XGBoost classifier', 'statement': 'Train an XGBoost classifier on a sample classification dataset.', 'keywords': ['xgboost', 'classifier', 'extreme', 'gradient', 'boosting'], 'code': "from xgboost import XGBClassifier\nfrom sklearn.datasets import load_iris\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = load_iris(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\nmodel = XGBClassifier(n_estimators=50, max_depth=3, learning_rate=0.1, eval_metric='mlogloss')\nmodel.fit(X_train, y_train)\nprint('Accuracy:', accuracy_score(y_test, model.predict(X_test)))", 'explanation': 'XGBoost is an optimized gradient-boosting library. Install it separately with pip install xgboost.', 'libraries': ['xgboost', 'scikit-learn']}, {'id': 'V08', 'unit': 'V', 'topic': 'Random Forest classifier', 'statement': 'Train and evaluate a Random Forest classifier.', 'keywords': ['random', 'forest', 'classifier', 'ensemble', 'decision', 'trees'], 'code': "from sklearn.ensemble import RandomForestClassifier\nfrom sklearn.datasets import load_iris\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = load_iris(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\nmodel = RandomForestClassifier(n_estimators=100, random_state=42)\nmodel.fit(X_train, y_train)\nprint('Accuracy:', accuracy_score(y_test, model.predict(X_test)))", 'explanation': 'Random Forest averages/votes across many decision trees trained with randomness.', 'libraries': ['scikit-learn']}, {'id': 'V09', 'unit': 'V', 'topic': 'Stacking ensemble', 'statement': 'Combine multiple base estimators using a meta-classifier.', 'keywords': ['stacking', 'classifier', 'meta', 'learner', 'ensemble'], 'code': "from sklearn.ensemble import StackingClassifier\nfrom sklearn.tree import DecisionTreeClassifier\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.datasets import load_iris\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = load_iris(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\nbase = [('tree', DecisionTreeClassifier(max_depth=3)), ('knn', KNeighborsClassifier(n_neighbors=5))]\nmodel = StackingClassifier(estimators=base, final_estimator=LogisticRegression(max_iter=1000))\nmodel.fit(X_train, y_train)\nprint('Accuracy:', accuracy_score(y_test, model.predict(X_test)))", 'explanation': 'Stacking trains a meta-model to combine predictions from multiple base models.', 'libraries': ['scikit-learn']}, {'id': 'V10', 'unit': 'V', 'topic': 'Fraud detection with multiple models', 'statement': 'Compare Logistic Regression and Random Forest for fraud classification.', 'keywords': ['fraud', 'detection', 'multiple', 'models', 'compare'], 'code': "from sklearn.datasets import make_classification\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score\n\nX, y = make_classification(n_samples=1000, n_features=12, weights=[0.95, 0.05], random_state=42)\nX_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.2, random_state=42)\nmodels = {'Logistic Regression': LogisticRegression(max_iter=1000), 'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42)}\nfor name, model in models.items():\n model.fit(X_train, y_train)\n print(name, 'accuracy:', round(accuracy_score(y_test, model.predict(X_test)), 3))", 'explanation': 'This uses synthetic data to demonstrate model comparison; it is not a production fraud detector.', 'libraries': ['scikit-learn']}, {'id': 'VI01', 'unit': 'VI', 'topic': 'Epsilon-greedy multi-armed bandit', 'statement': 'Choose an arm using epsilon-greedy exploration.', 'keywords': ['multi', 'armed', 'bandit', 'epsilon', 'greedy', 'explore', 'exploit'], 'code': "import random\n\nestimated_values = [0.2, 0.7, 0.5] # estimated reward per arm\nepsilon = float(input('Enter epsilon (0 to 1): '))\nif random.random() < epsilon:\n action = random.randrange(len(estimated_values))\n print('Exploration: selected random arm', action)\nelse:\n action = max(range(len(estimated_values)), key=estimated_values.__getitem__)\n print('Exploitation: selected best estimated arm', action)", 'explanation': 'With probability epsilon, explore a random arm; otherwise exploit the arm with the highest estimated reward.', 'libraries': ['standard library']}, {'id': 'VI02', 'unit': 'VI', 'topic': 'Discounted return', 'statement': 'Calculate discounted return from a reward sequence.', 'keywords': ['discounted', 'return', 'gamma', 'rewards', 'reinforcement', 'learning'], 'code': "rewards = [1, 2, 3]\ngamma = float(input('Enter discount factor gamma (0 to 1): '))\nG = 0\nfor reward in reversed(rewards):\n G = reward + gamma * G\nprint('Discounted return:', G)", 'explanation': 'The return is the sum of future rewards discounted by powers of gamma.', 'libraries': ['standard library']}, {'id': 'VI03', 'unit': 'VI', 'topic': 'State value from rewards', 'statement': 'Estimate a state value from observed rewards.', 'keywords': ['state', 'value', 'mean', 'rewards', 'reinforcement', 'learning'], 'code': "rewards = [2, 1, 4, 3, 5]\nvalue = sum(rewards) / len(rewards)\nprint('Estimated state value:', value)", 'explanation': 'This simplified estimate uses the average observed reward. Full RL state values estimate expected long-term return.', 'libraries': ['standard library']}, {'id': 'VI04', 'unit': 'VI', 'topic': 'Bellman state value update', 'statement': 'Update a state value using the Bellman expectation-style equation.', 'keywords': ['bellman', 'equation', 'state', 'value', 'reward', 'next', 'value', 'gamma'], 'code': "reward = float(input('Immediate reward: '))\ngamma = float(input('Discount factor gamma: '))\nnext_value = float(input('Value of next state: '))\nvalue = reward + gamma * next_value\nprint('Updated value:', value)", 'explanation': 'For a deterministic single next state, this simplified update is reward + gamma times next-state value.', 'libraries': ['standard library']}, {'id': 'VI05', 'unit': 'VI', 'topic': 'Q-Learning update', 'statement': 'Update a Q-value using the Q-Learning equation.', 'keywords': ['q', 'learning', 'update', 'alpha', 'gamma', 'max', 'next', 'q'], 'code': "q = float(input('Current Q value: '))\nreward = float(input('Reward: '))\nmax_next_q = float(input('Maximum next-state Q value: '))\nalpha = float(input('Learning rate alpha: '))\ngamma = float(input('Discount factor gamma: '))\nupdated_q = q + alpha * (reward + gamma * max_next_q - q)\nprint('Updated Q value:', updated_q)", 'explanation': 'Q-Learning is off-policy: it uses the maximum next-state Q-value in its update target.', 'libraries': ['standard library']}, {'id': 'VI06', 'unit': 'VI', 'topic': 'SARSA update', 'statement': 'Update a Q-value using the SARSA equation.', 'keywords': ['sarsa', 'update', 'next', 'action', 'q', 'on', 'policy'], 'code': "q = float(input('Current Q value: '))\nreward = float(input('Reward: '))\nnext_q = float(input('Q value for next chosen action: '))\nalpha = float(input('Learning rate alpha: '))\ngamma = float(input('Discount factor gamma: '))\nupdated_q = q + alpha * (reward + gamma * next_q - q)\nprint('Updated Q value:', updated_q)", 'explanation': 'SARSA is on-policy: it uses the Q-value of the next action actually chosen by the policy.', 'libraries': ['standard library']}, {'id': 'VI07', 'unit': 'VI', 'topic': 'Epsilon-greedy action selection', 'statement': 'Select an action from Q-values using epsilon-greedy.', 'keywords': ['epsilon', 'greedy', 'action', 'selection', 'q', 'values'], 'code': "import random\n\nq_values = [1.2, 0.5, 2.1]\nepsilon = float(input('Enter epsilon (0 to 1): '))\nif random.random() < epsilon:\n action = random.randrange(len(q_values))\nelse:\n action = max(range(len(q_values)), key=q_values.__getitem__)\nprint('Selected action index:', action)", 'explanation': 'Epsilon controls exploration; with probability 1-epsilon the action with the largest Q-value is selected.', 'libraries': ['standard library']}, {'id': 'VI08', 'unit': 'VI', 'topic': 'Simple Markov Decision Process', 'statement': 'Represent a small MDP using states, actions, and rewards.', 'keywords': ['mdp', 'markov', 'decision', 'process', 'states', 'actions', 'rewards'], 'code': "states = ['Start', 'Goal']\nactions = {'Start': ['move_right', 'stay'], 'Goal': []}\nrewards = {('Start', 'move_right', 'Goal'): 10, ('Start', 'stay', 'Start'): -1}\nprint('States:', states)\nprint('Actions:', actions)\nprint('Rewards:')\nfor transition, reward in rewards.items():\n print(transition, '->', reward)", 'explanation': 'An MDP is defined by states, actions, transition probabilities, rewards, and a discount factor. This example illustrates states/actions/rewards only.', 'libraries': ['standard library']}, {'id': 'VI09', 'unit': 'VI', 'topic': 'Temporal Difference learning update', 'statement': 'Update a state value using a one-step TD target.', 'keywords': ['temporal', 'difference', 'td', 'learning', 'update'], 'code': "value = float(input('Current state value: '))\nreward = float(input('Observed reward: '))\nnext_value = float(input('Next-state value: '))\nalpha = float(input('Learning rate alpha: '))\ngamma = float(input('Discount factor gamma: '))\nupdated = value + alpha * (reward + gamma * next_value - value)\nprint('Updated state value:', updated)", 'explanation': 'TD learning updates the current estimate toward reward + gamma times the next-state estimate.', 'libraries': ['standard library']}, {'id': 'VI10', 'unit': 'VI', 'topic': 'Robot maze Q-Learning', 'statement': 'Demonstrate Q-Learning for a tiny three-state robot path.', 'keywords': ['robot', 'maze', 'q', 'learning', 'reinforcement', 'learning'], 'code': "import random\n\n# States 0 -> 1 -> 2 (goal); actions: 0=left, 1=right\nQ = [[0.0, 0.0] for _ in range(3)]\nalpha, gamma, epsilon = 0.5, 0.9, 0.2\nfor episode in range(200):\n state = 0\n for _ in range(10):\n if random.random() < epsilon:\n action = random.randrange(2)\n else:\n action = max(range(2), key=lambda a: Q[state][a])\n next_state = max(0, min(2, state + (1 if action == 1 else -1)))\n reward = 10 if next_state == 2 else -1\n best_next = max(Q[next_state]) if next_state != 2 else 0\n Q[state][action] += alpha * (reward + gamma * best_next - Q[state][action])\n state = next_state\n if state == 2:\n break\nprint('Learned Q-table:')\nfor state, values in enumerate(Q):\n print(state, values)", 'explanation': 'The agent explores the tiny maze and updates Q-values to learn actions that lead to the goal.', 'libraries': ['standard library']}]
|
|
6
|
+
_THEORY = [{'unit': 'IV', 'topic': 'Clustering', 'explanation': 'Grouping similar data points without predefined labels.'}, {'unit': 'IV', 'topic': 'K-Means', 'explanation': 'Partitions data into k clusters by iteratively updating centroids.'}, {'unit': 'IV', 'topic': 'Hierarchical clustering', 'explanation': 'Builds a hierarchy of clusters through repeated merges or splits.'}, {'unit': 'IV', 'topic': 'DBSCAN', 'explanation': 'Density-based clustering that can identify noise points.'}, {'unit': 'IV', 'topic': 'Apriori', 'explanation': 'Finds frequent itemsets using support and candidate pruning.'}, {'unit': 'IV', 'topic': 'Support count', 'explanation': 'Number of transactions containing an itemset.'}, {'unit': 'IV', 'topic': 'WCSS', 'explanation': 'Sum of squared distances from samples to their assigned cluster centers.'}, {'unit': 'IV', 'topic': 'Silhouette score', 'explanation': 'Measures how well a point fits its cluster compared with the nearest other cluster.'}, {'unit': 'IV', 'topic': 'Davies-Bouldin Index', 'explanation': 'Cluster quality metric; lower values are generally better.'}, {'unit': 'IV', 'topic': 'Anomaly detection', 'explanation': 'Identifies observations that differ substantially from expected patterns.'}, {'unit': 'V', 'topic': 'Ensemble learning', 'explanation': 'Combines several models to improve robustness or predictive performance.'}, {'unit': 'V', 'topic': 'Voting', 'explanation': 'Combines classification predictions by majority or weighted votes.'}, {'unit': 'V', 'topic': 'Averaging', 'explanation': 'Combines numeric model outputs by taking their mean.'}, {'unit': 'V', 'topic': 'Weighted averaging', 'explanation': 'Averages predictions with larger influence assigned to selected models.'}, {'unit': 'V', 'topic': 'Bagging', 'explanation': 'Trains models on bootstrap samples and aggregates their outputs.'}, {'unit': 'V', 'topic': 'Boosting', 'explanation': 'Trains weak learners sequentially to correct prior errors.'}, {'unit': 'V', 'topic': 'AdaBoost', 'explanation': 'Reweights difficult training examples as weak learners are added.'}, {'unit': 'V', 'topic': 'Gradient Boosting', 'explanation': 'Adds learners that reduce a loss function, often by fitting residual-like gradients.'}, {'unit': 'V', 'topic': 'XGBoost', 'explanation': 'An optimized gradient-boosted tree library.'}, {'unit': 'V', 'topic': 'Random Forest', 'explanation': 'Uses randomized decision trees and aggregates their predictions.'}, {'unit': 'V', 'topic': 'Stacking', 'explanation': 'Trains a meta-model on predictions from base models.'}, {'unit': 'VI', 'topic': 'Reinforcement Learning', 'explanation': 'An agent learns actions through interaction and rewards.'}, {'unit': 'VI', 'topic': 'MDP', 'explanation': 'A model with states, actions, transition probabilities, rewards, and discount factor.'}, {'unit': 'VI', 'topic': 'Exploration', 'explanation': 'Trying actions to learn their outcomes.'}, {'unit': 'VI', 'topic': 'Exploitation', 'explanation': 'Choosing the currently best-known action.'}, {'unit': 'VI', 'topic': 'Epsilon-greedy', 'explanation': 'Explores randomly with probability epsilon and otherwise exploits.'}, {'unit': 'VI', 'topic': 'Discounted return', 'explanation': 'Future rewards summed with discount factor gamma.'}, {'unit': 'VI', 'topic': 'Bellman equation', 'explanation': "Relates a state's value to immediate reward and future value."}, {'unit': 'VI', 'topic': 'Q-Learning', 'explanation': 'Off-policy learning using the maximum next-state action value.'}, {'unit': 'VI', 'topic': 'SARSA', 'explanation': 'On-policy learning using the next action actually selected.'}, {'unit': 'VI', 'topic': 'TD learning', 'explanation': 'Updates value estimates using a one-step prediction error.'}]
|
|
7
|
+
|
|
8
|
+
_ALIASES = {
|
|
9
|
+
"IV01": ["kmeans", "k means", "centroid clustering", "partition clustering"],
|
|
10
|
+
"IV02": ["hierarchical clustering", "agglomerative clustering", "bottom up clustering"],
|
|
11
|
+
"IV03": ["apriori", "frequent items", "frequent itemsets", "market basket analysis", "support count"],
|
|
12
|
+
"IV04": ["dbscan", "density based clustering", "density-based clustering", "noise points", "density clustering"],
|
|
13
|
+
"IV05": ["wcss", "within cluster sum of squares", "within-cluster sum of squares", "elbow method"],
|
|
14
|
+
"IV06": ["silhouette", "silhouette score", "silhouette samples", "silhouette score per point"],
|
|
15
|
+
"IV07": ["davies bouldin", "davies-bouldin", "db index", "davies bouldin index"],
|
|
16
|
+
"IV08": ["anomaly detection", "threshold anomaly", "outlier detection"],
|
|
17
|
+
"IV09": ["common words", "document similarity", "words common between documents"],
|
|
18
|
+
"IV10": ["customer segmentation", "retail segmentation", "spending score", "customer clusters"],
|
|
19
|
+
"V01": ["max voting", "majority voting", "majority vote", "hard voting"],
|
|
20
|
+
"V02": ["averaging predictions", "average predictions", "mean ensemble"],
|
|
21
|
+
"V03": ["weighted averaging", "weighted average", "weighted predictions"],
|
|
22
|
+
"V04": ["bagging", "bootstrap aggregation", "bootstrap samples"],
|
|
23
|
+
"V05": ["adaboost", "ada boost", "adaptive boosting"],
|
|
24
|
+
"V06": ["gradient boosting", "gradientboosting"],
|
|
25
|
+
"V07": ["xgboost", "xg boost", "extreme gradient boosting"],
|
|
26
|
+
"V08": ["random forest", "randomforest", "forest classifier"],
|
|
27
|
+
"V09": ["stacking", "stacked ensemble", "meta learner", "meta-model"],
|
|
28
|
+
"V10": ["fraud detection", "fraud classification", "compare models for fraud"],
|
|
29
|
+
"VI01": ["multi armed bandit", "multi-armed bandit", "epsilon greedy bandit"],
|
|
30
|
+
"VI02": ["discounted return", "discounted reward", "return gamma", "cumulative discounted reward"],
|
|
31
|
+
"VI03": ["state value", "value from rewards", "state value from rewards"],
|
|
32
|
+
"VI04": ["bellman", "bellman equation", "bellman update", "state value update"],
|
|
33
|
+
"VI05": ["q learning", "q-learning", "q learning update", "q value update"],
|
|
34
|
+
"VI06": ["sarsa", "sarsa update", "on policy update"],
|
|
35
|
+
"VI07": ["epsilon greedy", "epsilon-greedy", "action selection", "exploration exploitation"],
|
|
36
|
+
"VI08": ["mdp", "markov decision process", "states actions rewards"],
|
|
37
|
+
"VI09": ["temporal difference", "td learning", "td update"],
|
|
38
|
+
"VI10": ["robot maze", "maze q learning", "robot q learning"]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def _normalize(text):
|
|
42
|
+
text = str(text).lower().replace("-", " ").replace("_", " ")
|
|
43
|
+
text = re.sub(r"[^a-z0-9]+", " ", text)
|
|
44
|
+
return " ".join(text.split())
|
|
45
|
+
|
|
46
|
+
def _tokens(text):
|
|
47
|
+
# Remove generic command words that add little meaning to a practical question.
|
|
48
|
+
ignored = {"write", "program", "code", "implement", "create", "make", "perform",
|
|
49
|
+
"calculate", "find", "using", "use", "for", "the", "a", "an", "to",
|
|
50
|
+
"on", "with", "and", "of", "in", "from", "apply", "develop", "show"}
|
|
51
|
+
return {t for t in _normalize(text).split() if t not in ignored}
|
|
52
|
+
|
|
53
|
+
def _score(query, entry):
|
|
54
|
+
qnorm = _normalize(query)
|
|
55
|
+
qtokens = _tokens(query)
|
|
56
|
+
if not qnorm or not qtokens:
|
|
57
|
+
return 0.0
|
|
58
|
+
|
|
59
|
+
pid = entry.get("id", "")
|
|
60
|
+
topic = _normalize(entry.get("topic", ""))
|
|
61
|
+
statement = _normalize(entry.get("statement", ""))
|
|
62
|
+
keywords = [_normalize(k) for k in entry.get("keywords", [])]
|
|
63
|
+
aliases = [_normalize(a) for a in _ALIASES.get(pid, [])]
|
|
64
|
+
candidates = [topic, statement] + keywords + aliases
|
|
65
|
+
|
|
66
|
+
# Strong exact phrase / known alias match, which fixes ambiguous matches such as DBSCAN.
|
|
67
|
+
best_phrase = max((1.0 if c and (c in qnorm or qnorm in c) else 0.0 for c in candidates), default=0.0)
|
|
68
|
+
if best_phrase:
|
|
69
|
+
return 0.98 if any(a and a in qnorm for a in aliases) else 0.96
|
|
70
|
+
|
|
71
|
+
# Token overlap against the topic and aliases matters more than broad statement overlap.
|
|
72
|
+
topic_tokens = _tokens(topic)
|
|
73
|
+
alias_tokens = set().union(*(_tokens(a) for a in aliases)) if aliases else set()
|
|
74
|
+
keyword_tokens = set().union(*(_tokens(k) for k in keywords)) if keywords else set()
|
|
75
|
+
statement_tokens = _tokens(statement)
|
|
76
|
+
def overlap(target):
|
|
77
|
+
return len(qtokens & target) / max(1, len(qtokens))
|
|
78
|
+
focused = max(overlap(topic_tokens), overlap(alias_tokens), overlap(keyword_tokens))
|
|
79
|
+
broad = overlap(statement_tokens)
|
|
80
|
+
from difflib import SequenceMatcher
|
|
81
|
+
fuzzy = max([SequenceMatcher(None, qnorm, c).ratio() for c in candidates] or [0.0])
|
|
82
|
+
return round(min(0.94, 0.68 * focused + 0.20 * broad + 0.12 * fuzzy), 4)
|
|
83
|
+
|
|
84
|
+
def search_programs(query, limit=5, unit=None):
|
|
85
|
+
"""Return matching program dictionaries ranked by relevance, including a score."""
|
|
86
|
+
results = []
|
|
87
|
+
for p in _PROGRAMS:
|
|
88
|
+
if unit and p["unit"].upper() != str(unit).upper():
|
|
89
|
+
continue
|
|
90
|
+
item = dict(p)
|
|
91
|
+
item["score"] = _score(query, p)
|
|
92
|
+
results.append(item)
|
|
93
|
+
results.sort(key=lambda x: x["score"], reverse=True)
|
|
94
|
+
return results[:max(0, int(limit))]
|
|
95
|
+
|
|
96
|
+
def find_program(query, min_score=0.40, unit=None):
|
|
97
|
+
"""Return the best matching program dictionary, or None for a weak match."""
|
|
98
|
+
results = search_programs(query, limit=1, unit=unit)
|
|
99
|
+
if not results or results[0]["score"] < float(min_score):
|
|
100
|
+
return None
|
|
101
|
+
return results[0]
|
|
102
|
+
|
|
103
|
+
def get_program(program_id):
|
|
104
|
+
"""Get a stored program by ID, such as IV04, V08, or VI05."""
|
|
105
|
+
key = str(program_id).strip().upper()
|
|
106
|
+
for p in _PROGRAMS:
|
|
107
|
+
if p["id"].upper() == key:
|
|
108
|
+
return dict(p)
|
|
109
|
+
raise KeyError(f"Unknown program ID: {program_id!r}")
|
|
110
|
+
|
|
111
|
+
def list_programs(unit=None):
|
|
112
|
+
"""List stored programs; optionally filter by IV, V, or VI."""
|
|
113
|
+
return [dict(p, code=None) for p in _PROGRAMS
|
|
114
|
+
if unit is None or p["unit"].upper() == str(unit).upper()]
|
|
115
|
+
|
|
116
|
+
def search_theory(query, unit=None, limit=5):
|
|
117
|
+
"""Return ranked theory-note dictionaries."""
|
|
118
|
+
results = []
|
|
119
|
+
for note in _THEORY:
|
|
120
|
+
if unit and note["unit"].upper() != str(unit).upper():
|
|
121
|
+
continue
|
|
122
|
+
entry = dict(note, keywords=[])
|
|
123
|
+
entry["score"] = _score(query, entry)
|
|
124
|
+
results.append(entry)
|
|
125
|
+
results.sort(key=lambda x: x["score"], reverse=True)
|
|
126
|
+
return results[:max(0, int(limit))]
|
|
127
|
+
|
|
128
|
+
def list_theory_topics(unit=None):
|
|
129
|
+
"""List theory topics, optionally filtered by unit."""
|
|
130
|
+
return [dict(n) for n in _THEORY
|
|
131
|
+
if unit is None or n["unit"].upper() == str(unit).upper()]
|
|
132
|
+
|
|
133
|
+
def __dir__():
|
|
134
|
+
return sorted(set(globals()) | {"find_program", "search_programs", "get_program",
|
|
135
|
+
"list_programs", "search_theory", "list_theory_topics"})
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def ask(question, unit=None):
|
|
140
|
+
"""Print the best matching practical program. Returns nothing to keep notebooks tidy."""
|
|
141
|
+
result = find_program(question, unit=unit)
|
|
142
|
+
if result is None:
|
|
143
|
+
print("I couldn't confidently match that question.")
|
|
144
|
+
print("Try the topic name or a keyword such as DBSCAN, XGBoost, SARSA, or WCSS.")
|
|
145
|
+
print("You can also use search_programs(question) to inspect possible matches.")
|
|
146
|
+
return
|
|
147
|
+
print(f"[{result['id']}] {result['topic']} (match: {result['score'] * 100:.1f}%)")
|
|
148
|
+
print(result["explanation"])
|
|
149
|
+
print("\n--- COMPLETE CODE ---\n")
|
|
150
|
+
print(result["code"])
|
|
151
|
+
print("\nRequired libraries:", ", ".join(result["libraries"]))
|
|
152
|
+
|
|
153
|
+
def run():
|
|
154
|
+
"""Interactive terminal loop: type practical questions, or 'exit' to quit."""
|
|
155
|
+
print("Practical08 — type a practical question (or 'exit' to quit).")
|
|
156
|
+
while True:
|
|
157
|
+
try:
|
|
158
|
+
question = input("\nQuestion: ").strip()
|
|
159
|
+
except (EOFError, KeyboardInterrupt):
|
|
160
|
+
print("\nExiting Practical08.")
|
|
161
|
+
break
|
|
162
|
+
if question.lower() in {"exit", "quit", "q"}:
|
|
163
|
+
break
|
|
164
|
+
if question:
|
|
165
|
+
ask(question)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: practical08
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Searchable AIML practical program library with simple ask interface
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Keywords: education,machine-learning,practicals,jupyter
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Topic :: Education
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# Practical08
|
|
16
|
+
|
|
17
|
+
Finalized question-to-code library containing 30 AIML practical programs from Units IV, V and VI.
|
|
18
|
+
|
|
19
|
+
## Simple Jupyter use
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
%pip install --upgrade practical08
|
|
23
|
+
from practical08 import ask
|
|
24
|
+
|
|
25
|
+
ask("Write a program for DBSCAN clustering")
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`ask(question)` prints the best matching program, a brief explanation, the complete code and required libraries. It does not print an extra dictionary afterward.
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
ask("Implement Random Forest classifier")
|
|
34
|
+
ask("Calculate discounted return using gamma")
|
|
35
|
+
ask("Find frequent items using Apriori")
|
|
36
|
+
ask("Update Q value using Q-Learning")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Optional exact lookup
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from practical08 import get_program
|
|
43
|
+
print(get_program("IV04")["code"])
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Search behavior
|
|
47
|
+
- Recognizes aliases such as DBSCAN / density-based clustering, XGBoost / extreme gradient boosting, and Q-learning / Q value update.
|
|
48
|
+
- Uses topic-focused scoring and rejects weak matches instead of silently selecting unrelated programs.
|
|
49
|
+
- No AI API key is required; matching uses Python's standard library and works offline after installation.
|
|
50
|
+
- Some returned examples need additional packages (e.g. `scikit-learn`, `numpy`, or `xgboost`) to execute.
|
|
51
|
+
- `ask()` prints code but never executes it automatically.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
practical08
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from practical08 import ask, find_program, get_program, list_programs
|
|
2
|
+
|
|
3
|
+
def test_has_30_programs():
|
|
4
|
+
assert len(list_programs()) == 30
|
|
5
|
+
|
|
6
|
+
def test_dbscan_query_matches_dbscan():
|
|
7
|
+
result = find_program("Write a program for DBSCAN clustering")
|
|
8
|
+
assert result and result["id"] == "IV04"
|
|
9
|
+
|
|
10
|
+
def test_density_alias_matches_dbscan():
|
|
11
|
+
result = find_program("density-based clustering")
|
|
12
|
+
assert result and result["id"] == "IV04"
|
|
13
|
+
|
|
14
|
+
def test_other_known_queries():
|
|
15
|
+
assert find_program("Random Forest classifier")["id"] == "V08"
|
|
16
|
+
assert find_program("Apriori frequent items")["id"] == "IV03"
|
|
17
|
+
assert find_program("SARSA update")["id"] == "VI06"
|
|
18
|
+
assert find_program("discounted return using gamma")["id"] == "VI02"
|
|
19
|
+
|
|
20
|
+
def test_weak_query_rejected():
|
|
21
|
+
assert find_program("please do the thing") is None
|
|
22
|
+
|
|
23
|
+
def test_ask_does_not_return_dict(capsys):
|
|
24
|
+
assert ask("DBSCAN clustering") is None
|
|
25
|
+
assert "[IV04]" in capsys.readouterr().out
|
|
26
|
+
|
|
27
|
+
def test_exact_lookup():
|
|
28
|
+
assert get_program("VI05")["topic"] == "Q-Learning update"
|