-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
zilvinas
committed
Oct 15, 2024
1 parent
2a2a9c6
commit fdd6b87
Showing
25 changed files
with
1,297 additions
and
51 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export enum Action { | ||
L = "L", | ||
R = "R", | ||
U = "U", | ||
D = "D", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// utils/ConsoleUtils.ts | ||
export class ConsoleUtils { | ||
public static blue(text: string): string { | ||
return `\x1b[34m${text}\x1b[0m`; // Blue text | ||
} | ||
|
||
public static green(text: string): string { | ||
return `\x1b[32m${text}\x1b[0m`; // Green text | ||
} | ||
|
||
public static color(text: string, colorCode: number): string { | ||
return `\x1b[${colorCode}m${text}\x1b[0m`; // Color by code | ||
} | ||
|
||
public static clearScreen() { | ||
console.log("clearScrn ... "); | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import { Pair } from './utils/Pair'; | ||
import { Action } from './Action'; // Assuming Action is defined elsewhere | ||
import { EnvironmentState } from './EnvironmentState'; // Assuming EnvironmentState is defined elsewhere | ||
import { StateProducer } from './StateProducer'; // Assuming StateProducer is defined elsewhere | ||
import { EnvironmentActionResult } from './EnvironmentActionResult'; // Assuming EnvironmentActionResult is defined elsewhere | ||
import { GameUtils } from './GameUtils'; // Assuming GameUtils is defined elsewhere | ||
import { Utils } from './utils/Utils'; // Assuming Utils is defined elsewhere | ||
|
||
export class Environment { | ||
private state: EnvironmentState; | ||
private static stateProducer: StateProducer; | ||
private goals: number[]; | ||
|
||
public reverseAction: Action | null = null; | ||
private bigCircleAction1: Action[] = []; | ||
private bigCircleAction2: Action[] = []; | ||
private smallCircleAction1: Action[] = []; | ||
private smallCircleAction2: Action[] = []; | ||
private circleAction: Action[] = []; | ||
|
||
constructor(stateProducer: StateProducer) { | ||
Environment.stateProducer = stateProducer; | ||
|
||
Environment.stateProducer.resetState(); | ||
const state = Environment.stateProducer.getState(); | ||
this.goals = Environment.stateProducer.getGoals(); | ||
this.state = new EnvironmentState(state, Environment.stateProducer); | ||
} | ||
|
||
public static isTerminalSuccess(state: EnvironmentState): boolean { | ||
return Environment._isTerminalSuccess(state.getState(), state.getGoals()); | ||
} | ||
|
||
public reset(): void { | ||
this.reverseAction = null; | ||
|
||
this.circleAction = []; | ||
this.bigCircleAction1 = []; | ||
this.bigCircleAction2 = []; | ||
this.smallCircleAction1 = []; | ||
this.smallCircleAction2 = []; | ||
|
||
this.bigCircleAction1.push(Action.L, Action.L, Action.D, Action.D, Action.R, Action.R, Action.U, Action.U); | ||
this.bigCircleAction2.push(Action.R, Action.R, Action.D, Action.D, Action.L, Action.L, Action.U, Action.U); | ||
this.smallCircleAction1.push(Action.L, Action.D, Action.R, Action.U, Action.L); | ||
this.smallCircleAction2.push(Action.R, Action.D, Action.L, Action.U, Action.R); | ||
} | ||
|
||
public getInitState(): EnvironmentState { | ||
Environment.stateProducer.resetState(); | ||
const state = Environment.stateProducer.getState(); | ||
this.goals = Environment.stateProducer.getGoals(); | ||
this.state = new EnvironmentState(state, Environment.stateProducer); | ||
return this.state; | ||
} | ||
|
||
public static getPossibleActions(state: EnvironmentState): Action[] { | ||
const io = state.getState().indexOf(-1); | ||
const fixedStateIndexes = state.getFixedElements().map(e => e - 1); | ||
return GameUtils.getValidMoves(io, fixedStateIndexes); | ||
} | ||
|
||
public executeAction(state0: EnvironmentState, action: Action): EnvironmentActionResult { | ||
const newState = GameUtils.makeMove(state0.getState(), action); | ||
const environmentState = new EnvironmentState(newState, Environment.stateProducer); | ||
|
||
let isTerminal = Environment._isTerminalSuccess(newState, this.goals); | ||
this.state = new EnvironmentState(newState, Environment.stateProducer); | ||
|
||
let r: number = NaN; | ||
|
||
this.reverseAction = GameUtils.getReverseAction(action); | ||
this.circleAction.push(action); | ||
if (this.circleAction.length > 8) this.circleAction.shift(); | ||
|
||
if (Utils.equalArrays(this.circleAction, this.bigCircleAction1) || | ||
Utils.equalArrays(this.circleAction, this.bigCircleAction2) || | ||
Utils.equalArrays(this.circleAction, this.smallCircleAction1) || | ||
Utils.equalArrays(this.circleAction, this.smallCircleAction2)) { | ||
isTerminal = true; | ||
} | ||
|
||
const io = this.state.getState().indexOf(-1); | ||
if (Environment.stateProducer.isLockedIndex(io)) { | ||
isTerminal = true; | ||
r = -1; | ||
} | ||
|
||
if (isNaN(r)) { | ||
r = this.getReward(newState, this.goals); | ||
} | ||
|
||
return new EnvironmentActionResult(environmentState, action, r, isTerminal); | ||
} | ||
|
||
public static _isTerminalSuccess(newState: number[], goals: number[]): boolean { | ||
if (newState.length !== 16) throw new Error("newState.size() != 16"); | ||
|
||
return goals.filter(e => newState[e - 1] === e).length === goals.length; | ||
} | ||
|
||
public prntInfo(): void { | ||
Utils.prnt("\n\n================================================\n"); | ||
|
||
const state = this.state.getState(); | ||
const io = state.indexOf(-1); | ||
const xy = GameUtils.getXY(io); | ||
Utils.prnt(xy); | ||
const indx = GameUtils.getIndex(xy.getKey(), xy.getValue()); // Assuming getXY returns a tuple | ||
Utils.prnt(`${io} - ${indx}`); | ||
const moves = GameUtils._getValidMoves(io); | ||
Utils.prnt(moves); | ||
const r = this.getReward(state, this.goals); | ||
Utils.prnt(r); | ||
// prnt("\n"); | ||
|
||
const stateAsString = GameUtils.stateAsString(state, this.goals); | ||
Utils.prnt(stateAsString); | ||
} | ||
|
||
private getReward(state: number[], goals: number[]): number { | ||
const ih = state.indexOf(-1); | ||
const xyh = GameUtils.getXY(ih); | ||
|
||
const floatStream = goals.map(e => this.getDistance(GameUtils.getXY(state.indexOf(e)), GameUtils.getXY(e - 1))); | ||
const d0Sum = floatStream.reduce((acc, val) => acc + val, 0); | ||
|
||
if (d0Sum === 0) { | ||
return 100.5; | ||
} | ||
|
||
const d1Sum = goals.reduce((acc, e) => acc + this.getDistance(GameUtils.getXY(state.indexOf(e)), xyh), 0); | ||
|
||
Utils.prnt(`d0Sum: ${d0Sum}`); | ||
Utils.prnt(`d1Sum: ${d1Sum}`); | ||
|
||
return 1 / (d0Sum + d1Sum); | ||
} | ||
|
||
private getDistance(v1: Pair<number, number>, v2: Pair<number, number>): number { | ||
const pow1 = Math.pow(v2.getKey() - v1.getKey(), 2); | ||
const pow2 = Math.pow(v2.getValue() - v1.getValue(), 2); | ||
return Math.sqrt(pow1 + pow2); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Action } from './Action'; | ||
import { EnvironmentState } from './EnvironmentState'; | ||
|
||
export class EnvironmentActionResult { | ||
state: EnvironmentState; | ||
action: Action; | ||
reward: number; | ||
isTerminal: boolean; | ||
|
||
constructor( | ||
state: EnvironmentState, | ||
action: Action, | ||
reward: number = 0, | ||
isTerminal: boolean = false | ||
) { | ||
this.state = state; // Initialize with a default if not provided | ||
this.action = action; // Assuming Action has a default like NONE | ||
this.reward = reward; | ||
this.isTerminal = isTerminal; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { StateProducer } from './StateProducer'; | ||
|
||
export class EnvironmentState { | ||
private state: number[]; | ||
private goals: number[]; | ||
public fixedElements: number[]; | ||
|
||
constructor(state: number[], stateProducer: StateProducer); | ||
constructor(state: EnvironmentState); | ||
constructor(state: number[] | EnvironmentState, stateProducer?: StateProducer) { | ||
if (state instanceof EnvironmentState) { | ||
// Copy constructor logic | ||
this.state = [...state.getState()]; | ||
this.goals = [...state.getGoals()]; | ||
this.fixedElements = [...state.getFixedElements()]; | ||
} else { | ||
// Regular constructor logic | ||
this.state = [...state]; | ||
this.goals = [...(stateProducer?.getGoals() ?? [])]; | ||
this.fixedElements = [...(stateProducer?.getLockedStateElements() ?? [])]; | ||
} | ||
} | ||
|
||
public getState(): number[] { | ||
return this.state; | ||
} | ||
|
||
public setState(state: number[]): void { | ||
this.state = state; | ||
} | ||
|
||
public getGoals(): number[] { | ||
return this.goals; | ||
} | ||
|
||
public setGoals(goals: number[]): void { | ||
this.goals = goals; | ||
} | ||
|
||
public getFixedElements(): number[] { | ||
return this.fixedElements; | ||
} | ||
|
||
public setFixedElements(fixedElements: number[]): void { | ||
this.fixedElements = fixedElements; | ||
} | ||
|
||
public getHashCodeV2(): number { | ||
const hashCode = this.getHashCodeV3__(); | ||
return this.hashString(hashCode); | ||
} | ||
|
||
public getHashCodeV3__(): string { | ||
return Array.from({ length: 16 }, (_, e) => { | ||
let v: string; | ||
const o = this.state[e]; | ||
if (o === -1) v = "*"; | ||
else if (this.goals.includes(o)) v = String(o); | ||
else if (this.goals.includes(e + 1)) v = "o"; | ||
else v = " "; | ||
v = v + "\t"; | ||
if (e !== 0 && (e + 1) % 4 === 0) v = v + "\n"; | ||
return v; | ||
}).join(""); | ||
} | ||
|
||
public getHashCode(): number { | ||
const a = this.state.map(String).join(","); | ||
return this.hashString(a); | ||
} | ||
|
||
private hashString(str: string): number { | ||
let hash = 0; | ||
for (let i = 0; i < str.length; i++) { | ||
const char = str.charCodeAt(i); | ||
hash = (hash << 5) - hash + char; | ||
hash |= 0; // Convert to 32bit integer | ||
} | ||
return hash; | ||
} | ||
|
||
public equals(other: EnvironmentState): boolean { | ||
return this.getHashCode() === other.getHashCode(); | ||
} | ||
|
||
public hashCode(): number { | ||
return this.getHashCode(); | ||
} | ||
} | ||
|
Oops, something went wrong.