' kmeans.pb — K-Means clustering algorithm
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL dataX(100) AS DOUBLE
    LOCAL dataY(100) AS DOUBLE
    LOCAL centroidsX(10) AS DOUBLE
    LOCAL centroidsY(10) AS DOUBLE
    LOCAL assignments(100) AS LONG
    LOCAL numPoints AS LONG
    LOCAL numClusters AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL k AS LONG
    LOCAL minDist AS DOUBLE
    LOCAL dist AS DOUBLE
    LOCAL sumX AS DOUBLE
    LOCAL sumY AS DOUBLE
    LOCAL countVal AS LONG
    LOCAL changed AS LONG
    LOCAL iter AS LONG
    LOCAL maxIter AS LONG
    LOCAL clusterID AS LONG
    LOCAL totalDist AS DOUBLE
    LOCAL iterCount AS LONG
    LOCAL pointIdx AS LONG
    LOCAL cIdx AS LONG

    numPoints = 20
    numClusters = 3
    maxIter = 20

    PRINT "=== K-Means Clustering ==="
    PRINT "Points: " + STR$(numPoints) + " Clusters: " + STR$(numClusters)

    FOR i = 0 TO numPoints - 1
        dataX(i) = i * 10 + (i MOD 5) * 3
        dataY(i) = i * 5 + (i MOD 3) * 7
    NEXT i

    FOR i = 0 TO numClusters - 1
        centroidsX(i) = dataX(i * 7)
        centroidsY(i) = dataY(i * 7)
    NEXT i

    iterCount = 0
    WHILE 1
        iterCount = iterCount + 1
        IF iterCount > maxIter THEN EXIT LOOP
        changed = 0

        FOR pointIdx = 0 TO numPoints - 1
            minDist = 999999
            clusterID = 0
            FOR cIdx = 0 TO numClusters - 1
                dist = (dataX(pointIdx) - centroidsX(cIdx)) * (dataX(pointIdx) - centroidsX(cIdx))
                dist = dist + (dataY(pointIdx) - centroidsY(cIdx)) * (dataY(pointIdx) - centroidsY(cIdx))
                IF dist < minDist THEN
                    minDist = dist
                    clusterID = cIdx
                END IF
            NEXT cIdx
            IF assignments(pointIdx) <> clusterID THEN
                assignments(pointIdx) = clusterID
                changed = 1
            END IF
        NEXT pointIdx

        FOR cIdx = 0 TO numClusters - 1
            sumX = 0
            sumY = 0
            countVal = 0
            FOR pointIdx = 0 TO numPoints - 1
                IF assignments(pointIdx) = cIdx THEN
                    sumX = sumX + dataX(pointIdx)
                    sumY = sumY + dataY(pointIdx)
                    countVal = countVal + 1
                END IF
            NEXT pointIdx
            IF countVal > 0 THEN
                centroidsX(cIdx) = sumX / countVal
                centroidsY(cIdx) = sumY / countVal
            END IF
        NEXT cIdx

        IF changed = 0 THEN EXIT LOOP
    WEND

    PRINT "Clusters after " + STR$(iterCount) + " iterations:"
    FOR cIdx = 0 TO numClusters - 1
        countVal = 0
        FOR pointIdx = 0 TO numPoints - 1
            IF assignments(pointIdx) = cIdx THEN
                countVal = countVal + 1
            END IF
        NEXT pointIdx
        PRINT "  Cluster " + STR$(cIdx) + ": " + STR$(countVal) + " points"
        PRINT "    Center: (" + STR$(centroidsX(cIdx)) + "," + STR$(centroidsY(cIdx)) + ")"
    NEXT cIdx

    PRINT "=== End K-Means ==="
    FUNCTION = 0
END FUNCTION
