129 lines
5.2 KiB
Python
129 lines
5.2 KiB
Python
import math
|
|
import numpy as np
|
|
|
|
# Cameras dataset
|
|
cameras = [
|
|
{"name": "Canon M10", "price": 80000, "iso": 25600, "af": 49, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Sony A5000", "price": 90000, "iso": 25600, "af": 25, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon M3", "price": 100000, "iso": 25600, "af": 49, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Sony A6000", "price": 110000, "iso": 25600, "af": 179, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon M50", "price": 130000, "iso": 51200, "af": 143, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Sony A6300", "price": 155000, "iso": 51200, "af": 425, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Fujifilm XA3", "price": 80000, "iso": 25600, "af": 77, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Sony A6400", "price": 185000, "iso": 51200, "af": 425, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Fujifilm XA5", "price": 90000, "iso": 25600, "af": 77, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Nikon J5", "price": 75000, "iso": 12800, "af": 171, "sensor": "1-inch", "sensor_score": 0.5},
|
|
{"name": "Fujifilm XT20", "price": 145000, "iso": 51200, "af": 325, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 500D", "price": 55000, "iso": 12800, "af": 9, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 60D", "price": 100000, "iso": 12800, "af": 9, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 1100D", "price": 55000, "iso": 12800, "af": 9, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 80D", "price": 140000, "price_spec": 140000, "iso": 25600, "af": 45, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 600D", "price": 80000, "iso": 12800, "af": 9, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 6D", "price": 165000, "iso": 102400, "af": 61, "sensor": "Full Frame", "sensor_score": 1.0},
|
|
{"name": "Canon 550D", "price": 75000, "iso": 12800, "af": 9, "sensor": "APS-C", "sensor_score": 0.7},
|
|
{"name": "Canon 5D Mark III", "price": 215000, "iso": 102400, "af": 61, "sensor": "Full Frame", "sensor_score": 1.0}
|
|
]
|
|
|
|
price_min = 55000
|
|
price_max = 215000
|
|
iso_max = 102400
|
|
af_max = 425
|
|
|
|
def php_round(val, decimals=2):
|
|
multiplier = 10 ** decimals
|
|
return math.floor(val * multiplier + 0.5) / multiplier
|
|
|
|
# Generate Decision Matrix X (0-1 scale)
|
|
X = []
|
|
for c in cameras:
|
|
ps = php_round((price_max - c["price"]) / (price_max - price_min), 2)
|
|
is_ = php_round(c["iso"] / iso_max, 2)
|
|
af = php_round(c["af"] / af_max, 2)
|
|
ss = php_round(c["sensor_score"], 2)
|
|
X.append([ps, is_, af, ss])
|
|
X = np.array(X)
|
|
|
|
m, n = X.shape
|
|
dividers = [math.sqrt(sum(X[i][j]**2 for i in range(m))) for j in range(n)]
|
|
|
|
print("Dividers:", [round(d, 4) for d in dividers])
|
|
|
|
# Normalization Matrix R
|
|
R = np.zeros((m, n))
|
|
for i in range(m):
|
|
for j in range(n):
|
|
R[i][j] = X[i][j] / dividers[j]
|
|
|
|
scenarios = {
|
|
"outdoor_day": {
|
|
"name": "Outdoor - Day (Siang)",
|
|
"bobot": [0.30, 0.15, 0.25, 0.30],
|
|
"jenis": ["cost", "benefit", "benefit", "benefit"]
|
|
},
|
|
"outdoor_night": {
|
|
"name": "Outdoor - Night (Malam)",
|
|
"bobot": [0.15, 0.50, 0.15, 0.20],
|
|
"jenis": ["cost", "benefit", "benefit", "benefit"]
|
|
},
|
|
"indoor_cerah": {
|
|
"name": "Indoor - Cerah",
|
|
"bobot": [0.35, 0.20, 0.20, 0.25],
|
|
"jenis": ["cost", "benefit", "benefit", "benefit"]
|
|
},
|
|
"indoor_gelap": {
|
|
"name": "Indoor - Gelap",
|
|
"bobot": [0.15, 0.55, 0.15, 0.15],
|
|
"jenis": ["cost", "benefit", "benefit", "benefit"]
|
|
},
|
|
"all": {
|
|
"name": "Semua Kondisi",
|
|
"bobot": [0.25, 0.30, 0.20, 0.25],
|
|
"jenis": ["cost", "benefit", "benefit", "benefit"]
|
|
}
|
|
}
|
|
|
|
for key, sc in scenarios.items():
|
|
print(f"\n================ {sc['name']} ================")
|
|
w = sc["bobot"]
|
|
jenis = sc["jenis"]
|
|
|
|
# Weighted normalized matrix Y
|
|
Y = np.zeros((m, n))
|
|
for i in range(m):
|
|
for j in range(n):
|
|
Y[i][j] = R[i][j] * w[j]
|
|
|
|
# Ideal solutions
|
|
ideal_pos = []
|
|
ideal_neg = []
|
|
for j in range(n):
|
|
col = Y[:, j]
|
|
if jenis[j] == 'benefit':
|
|
ideal_pos.append(max(col))
|
|
ideal_neg.append(min(col))
|
|
else:
|
|
ideal_pos.append(min(col))
|
|
ideal_neg.append(max(col))
|
|
|
|
print("A+:", [round(x, 6) for x in ideal_pos])
|
|
print("A-:", [round(x, 6) for x in ideal_neg])
|
|
|
|
# Jarak and Preferensi
|
|
results = []
|
|
for i in range(m):
|
|
dp = math.sqrt(sum((Y[i][j] - ideal_pos[j])**2 for j in range(n)))
|
|
dm = math.sqrt(sum((Y[i][j] - ideal_neg[j])**2 for j in range(n)))
|
|
v = dm / (dp + dm) if (dp + dm) > 0 else 0.0
|
|
results.append((cameras[i]["name"], X[i], dp, dm, v))
|
|
|
|
results.sort(key=lambda x: x[4], reverse=True)
|
|
|
|
print("Top 3:")
|
|
for rank in range(3):
|
|
res = results[rank]
|
|
print(f"Rank {rank+1}: {res[0]} | Scores: {res[1]} | D+: {res[2]:.6f} | D-: {res[3]:.6f} | V: {res[4]:.6f}")
|
|
|
|
print("Full ranking:")
|
|
for rank, res in enumerate(results):
|
|
print(f"{rank+1} | {res[0]} | {res[1][0]:.2f} | {res[1][1]:.2f} | {res[1][2]:.2f} | {res[1][3]:.2f} | {res[2]:.4f} | {res[3]:.4f} | {res[4]:.6f}")
|