openforge 0.1.0__py3-none-any.whl
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.
OpenForge/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import random
|
|
3
|
+
|
|
4
|
+
class MarkovChains:
|
|
5
|
+
def __init__(self,data:list,lvl=6):
|
|
6
|
+
"""
|
|
7
|
+
Markov Chain-based sequence predictor.
|
|
8
|
+
|
|
9
|
+
Made By: Muhammad Ibrahim
|
|
10
|
+
https://github.com/Ibraheem5002/
|
|
11
|
+
|
|
12
|
+
Parameters:
|
|
13
|
+
-----------
|
|
14
|
+
data : list
|
|
15
|
+
List of possible outcome values
|
|
16
|
+
Best case if all are of same data type
|
|
17
|
+
|
|
18
|
+
lvl : int (optional)
|
|
19
|
+
Maximum pattern length to track (n-gram order)
|
|
20
|
+
Default value = 6
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
self.in_hist = []
|
|
24
|
+
self.patterns = {}
|
|
25
|
+
self.ops = data
|
|
26
|
+
self.N = len(self.ops)
|
|
27
|
+
self.probability = np.full(self.N,1/self.N)
|
|
28
|
+
self.in_op = None
|
|
29
|
+
self.out_op = None
|
|
30
|
+
self.Level = lvl
|
|
31
|
+
|
|
32
|
+
def _add_pattern(self,key,Z):
|
|
33
|
+
if key in self.patterns:
|
|
34
|
+
self.patterns[key].append(Z)
|
|
35
|
+
else:
|
|
36
|
+
self.patterns[key] = [Z]
|
|
37
|
+
|
|
38
|
+
def _update_pattern(self):
|
|
39
|
+
self.in_hist.append(self.in_op)
|
|
40
|
+
|
|
41
|
+
for L in range(1,self.Level+1):
|
|
42
|
+
if len(self.in_hist) >= L+1:
|
|
43
|
+
key = tuple(self.in_hist[-(L+1):-1])
|
|
44
|
+
Z = self.in_hist[-1]
|
|
45
|
+
self._add_pattern(key,Z)
|
|
46
|
+
|
|
47
|
+
def _normalize_prob(self):
|
|
48
|
+
total = sum(self.probability)
|
|
49
|
+
|
|
50
|
+
if total <= 0:
|
|
51
|
+
self.probability = np.full(self.N,1/self.N)
|
|
52
|
+
else:
|
|
53
|
+
self.probability = self.probability / total
|
|
54
|
+
|
|
55
|
+
def _cal_probability(self,key):
|
|
56
|
+
lst = self.patterns[key]
|
|
57
|
+
total = len(lst)
|
|
58
|
+
|
|
59
|
+
if total > 0:
|
|
60
|
+
for i in range(self.N):
|
|
61
|
+
self.probability[i] = lst.count(self.ops[i]) / total
|
|
62
|
+
else:
|
|
63
|
+
self.probability = np.full(self.N,1/self.N)
|
|
64
|
+
|
|
65
|
+
self._normalize_prob()
|
|
66
|
+
|
|
67
|
+
def _choose_ans(self):
|
|
68
|
+
sorted_prob = sorted(self.probability,reverse=True)
|
|
69
|
+
best = sorted_prob[0]
|
|
70
|
+
scnd = sorted_prob[1]
|
|
71
|
+
|
|
72
|
+
if best-scnd > 0.15:
|
|
73
|
+
max_idx = list(self.probability).index(best)
|
|
74
|
+
return self.ops[max_idx]
|
|
75
|
+
else:
|
|
76
|
+
return np.random.choice(self.ops,p=self.probability)
|
|
77
|
+
|
|
78
|
+
def _predict_ans(self):
|
|
79
|
+
self.probability = np.full(self.N,1/self.N)
|
|
80
|
+
probs = []
|
|
81
|
+
pLen = []
|
|
82
|
+
|
|
83
|
+
for L in range(self.Level,0,-1):
|
|
84
|
+
if len(self.in_hist) < L:
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
key = tuple(self.in_hist[-L:])
|
|
88
|
+
|
|
89
|
+
if key in self.patterns:
|
|
90
|
+
self._cal_probability(key)
|
|
91
|
+
probs.append(self.probability.copy())
|
|
92
|
+
pLen.append(len(self.patterns[key]))
|
|
93
|
+
|
|
94
|
+
if len(probs) == 0:
|
|
95
|
+
self.out_op = random.choice(self.ops)
|
|
96
|
+
else:
|
|
97
|
+
mx = -100000
|
|
98
|
+
idx = -1
|
|
99
|
+
|
|
100
|
+
for i in range(len(probs)):
|
|
101
|
+
pMax = max(probs[i])
|
|
102
|
+
score = pMax * pLen[i]
|
|
103
|
+
|
|
104
|
+
if score > mx:
|
|
105
|
+
mx = score
|
|
106
|
+
idx = i
|
|
107
|
+
|
|
108
|
+
self.probability = probs[idx]
|
|
109
|
+
self.out_op = self._choose_ans()
|
|
110
|
+
|
|
111
|
+
def predict(self,X):
|
|
112
|
+
"""
|
|
113
|
+
Make prediction and update patterns.
|
|
114
|
+
If first call, then output is total random
|
|
115
|
+
|
|
116
|
+
Parameters:
|
|
117
|
+
-----------
|
|
118
|
+
X : any
|
|
119
|
+
Observed input (must be in self.ops)
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Predicted next outcome
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
if X not in self.ops:
|
|
126
|
+
raise ValueError(f"Input {X} is not in valid operations: {self.ops}")
|
|
127
|
+
|
|
128
|
+
self.in_op = X
|
|
129
|
+
self._predict_ans()
|
|
130
|
+
self._update_pattern()
|
|
131
|
+
return self.out_op
|
|
132
|
+
|
|
133
|
+
def fit(self,lst:list):
|
|
134
|
+
"""
|
|
135
|
+
Reset and fit new sequence of observed data
|
|
136
|
+
All elements must be of given outcomes
|
|
137
|
+
|
|
138
|
+
Parameters:
|
|
139
|
+
-----------
|
|
140
|
+
lst : List
|
|
141
|
+
List of all observed input values
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
for i in range(len(lst)):
|
|
145
|
+
if lst[i] not in self.ops:
|
|
146
|
+
raise ValueError(f"Input {lst[i]} is not in valid operations: {self.ops}")
|
|
147
|
+
|
|
148
|
+
self.reset()
|
|
149
|
+
self.in_hist = lst
|
|
150
|
+
|
|
151
|
+
def reset(self):
|
|
152
|
+
"""Reset the model to initial state"""
|
|
153
|
+
self.in_hist = []
|
|
154
|
+
self.patterns = {}
|
|
155
|
+
self.probability = np.full(self.N,1/self.N)
|
|
156
|
+
self.in_op = None
|
|
157
|
+
self.out_op = None
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openforge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A public repository and museum for high-quality, reinvented machine learning modules and core computing algorithms.
|
|
5
|
+
Author-email: Muhammad Ibrahim <ibrahim@example.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE.txt
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# OpenForge
|
|
17
|
+
|
|
18
|
+
Welcome to **OpenForge**! This is a public Python library built for developers who love to build things from scratch.
|
|
19
|
+
|
|
20
|
+
Have you ever spent days coding a custom Linear Regression algorithm, a unique Markov Chain module, or a custom game engine just to learn how it works under the hood? You can't merge it into major libraries like Scikit-Learn because they already have itโbut your hard work shouldn't be wasted.
|
|
21
|
+
|
|
22
|
+
This library is a **museum of reinvented wheels**. It is a place to publish your custom-built modules, showcase your engineering grit, and leave your permanent mark on the open-source world.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## ๐ ๏ธ How It Works (The Import Layout)
|
|
27
|
+
|
|
28
|
+
To prevent anyone's code from overwriting someone else's, every single developer gets their own isolated **username space**. Users can import your exact code using this clean layout:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
# If your username is 'alex' and you built a tictactoe bot
|
|
32
|
+
from artisan_wheelhouse.alex import infinite_tictactoe
|
|
33
|
+
|
|
34
|
+
# If your username is 'sarah' and you organized your ML modules
|
|
35
|
+
from artisan_wheelhouse.sarah.ml.supervised import linear_regression
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## ๐ The Rules for Publishing
|
|
41
|
+
|
|
42
|
+
Anyone is welcome to contribute! To keep the library clean, functional, and organized, all submissions must follow these simple rules:
|
|
43
|
+
|
|
44
|
+
1. **Anyone Can Publish:** Whether you are a computer science student or a senior engineer, if you built something from scratch to learn, you can submit it.
|
|
45
|
+
2. **Unique Usernames:** Your username folder must be completely unique. Once a username is taken, it belongs to that developer.
|
|
46
|
+
3. **Username Format:** Your username folder name must be **all lowercase** and contain **no spaces** (use underscores if needed, e.g., `john_doe`). It must be a valid Python identifier.
|
|
47
|
+
4. **Strict Boundaries:** You can only add or modify files inside your own specific username folder. Touching or modifying another user's folder will result in immediate rejection.
|
|
48
|
+
5. **The `__init__.py` Requirement:** Every folder and sub-folder you create inside your namespace **must** contain an `__init__.py` file so Python can find and import your modules correctly.
|
|
49
|
+
6. **Honest & Working Code:** Your module must do exactly what it claims to do. It will be carefully reviewed. If it contains game-breaking bugs, malicious code, or does not work as advertised, it will be rejected.
|
|
50
|
+
7. **Keep Dependencies Low:** Try to use vanilla Python or basic standard libraries. If your module requires heavy external packages, explain why in your pull request.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## ๐ How to Submit Your Module
|
|
55
|
+
|
|
56
|
+
1. **Fork** the repository on GitHub.
|
|
57
|
+
2. Create your unique username folder under `artisan_wheelhouse/` (e.g., `artisan_wheelhouse/your_username/`).
|
|
58
|
+
3. Add an empty `__init__.py` file inside your folder.
|
|
59
|
+
4. Write your beautiful code, organize it into categories if you like, and include a short docstring explaining how to use it.
|
|
60
|
+
5. Open a **Pull Request (PR)**. Once reviewed and merged, your code will be bundled into the next official PyPI release for everyone to `pip install`!
|
|
61
|
+
|
|
62
|
+
*Let's build, reinvent, and leave a mark!*
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
OpenForge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
OpenForge/ibrahim/Markov_Chains_Module.py,sha256=3vm4Zw2vNW9Zsi6kr7UmuXJ2GjvmTzkRXZ2GyVv92dc,4456
|
|
3
|
+
openforge-0.1.0.dist-info/licenses/LICENSE.txt,sha256=GVkeeBv0Ma8dGvCFfltufWE2fP0C2A5Q1udfqQ-lXQ0,1092
|
|
4
|
+
openforge-0.1.0.dist-info/METADATA,sha256=xGOaq-5jeb0_1pN5tPjT3AOXv5Swq-T7eGgCcpZyBHU,3758
|
|
5
|
+
openforge-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
6
|
+
openforge-0.1.0.dist-info/top_level.txt,sha256=VgKNmRVFbcwVtxmy2yHT-LzmBSdpWteh4uAp0E_YuzE,10
|
|
7
|
+
openforge-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Muhammad Ibrahim
|
|
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 following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
OpenForge
|