Spaces:
Sleeping
Sleeping
solve
Browse files
rlcube/rlcube/models/search.py
CHANGED
|
@@ -40,7 +40,7 @@ class Node:
|
|
| 40 |
|
| 41 |
def select_action(self):
|
| 42 |
scores = self.u()
|
| 43 |
-
return np.argmax(scores)
|
| 44 |
|
| 45 |
|
| 46 |
class MonteCarloTree:
|
|
|
|
| 40 |
|
| 41 |
def select_action(self):
|
| 42 |
scores = self.u()
|
| 43 |
+
return np.argmax(scores).item()
|
| 44 |
|
| 45 |
|
| 46 |
class MonteCarloTree:
|
src/components/state-modal.tsx
CHANGED
|
@@ -14,7 +14,7 @@ export type StateModalRef = {
|
|
| 14 |
|
| 15 |
export const StateModal = forwardRef<StateModalRef, unknown>((_, ref) => {
|
| 16 |
const [state, setState] = useState<Array<Array<number>>>([]);
|
| 17 |
-
const { isOpen, onOpen,
|
| 18 |
|
| 19 |
useImperativeHandle(ref, () => ({
|
| 20 |
open: (state: Array<Array<number>>) => {
|
|
@@ -27,27 +27,6 @@ export const StateModal = forwardRef<StateModalRef, unknown>((_, ref) => {
|
|
| 27 |
navigator.clipboard.writeText(JSON.stringify(state));
|
| 28 |
};
|
| 29 |
|
| 30 |
-
const solve = async () => {
|
| 31 |
-
try {
|
| 32 |
-
const response = await fetch('/api/solve', {
|
| 33 |
-
method: 'POST',
|
| 34 |
-
headers: {
|
| 35 |
-
'Content-Type': 'application/json',
|
| 36 |
-
},
|
| 37 |
-
body: JSON.stringify({ state }),
|
| 38 |
-
});
|
| 39 |
-
if (!response.ok) {
|
| 40 |
-
throw new Error('Server error', { cause: response });
|
| 41 |
-
}
|
| 42 |
-
const { steps } = await response.json();
|
| 43 |
-
rotationController.addRotationStepCode(...steps);
|
| 44 |
-
onClose();
|
| 45 |
-
} catch (err) {
|
| 46 |
-
alert('An error occurred. Check the console for details.');
|
| 47 |
-
console.error(err);
|
| 48 |
-
}
|
| 49 |
-
};
|
| 50 |
-
|
| 51 |
return (
|
| 52 |
<Modal isOpen={isOpen} onOpenChange={onOpenChange} placement="center">
|
| 53 |
<ModalContent>
|
|
@@ -95,9 +74,6 @@ export const StateModal = forwardRef<StateModalRef, unknown>((_, ref) => {
|
|
| 95 |
<Button color="primary" variant="light" size="sm" onPress={copy}>
|
| 96 |
Copy
|
| 97 |
</Button>
|
| 98 |
-
<Button color="success" size="sm" onPress={solve}>
|
| 99 |
-
Solve
|
| 100 |
-
</Button>
|
| 101 |
</ModalFooter>
|
| 102 |
</>
|
| 103 |
)}
|
|
|
|
| 14 |
|
| 15 |
export const StateModal = forwardRef<StateModalRef, unknown>((_, ref) => {
|
| 16 |
const [state, setState] = useState<Array<Array<number>>>([]);
|
| 17 |
+
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
| 18 |
|
| 19 |
useImperativeHandle(ref, () => ({
|
| 20 |
open: (state: Array<Array<number>>) => {
|
|
|
|
| 27 |
navigator.clipboard.writeText(JSON.stringify(state));
|
| 28 |
};
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
return (
|
| 31 |
<Modal isOpen={isOpen} onOpenChange={onOpenChange} placement="center">
|
| 32 |
<ModalContent>
|
|
|
|
| 74 |
<Button color="primary" variant="light" size="sm" onPress={copy}>
|
| 75 |
Copy
|
| 76 |
</Button>
|
|
|
|
|
|
|
|
|
|
| 77 |
</ModalFooter>
|
| 78 |
</>
|
| 79 |
)}
|
src/components/ui-controls.tsx
CHANGED
|
@@ -14,6 +14,7 @@ import { StateModal, StateModalRef } from './state-modal';
|
|
| 14 |
|
| 15 |
export const UIControls = () => {
|
| 16 |
const stateModalRef = useRef<StateModalRef | null>(null);
|
|
|
|
| 17 |
const [isControlsOpen, setIsControlsOpen] = useState(true);
|
| 18 |
const {
|
| 19 |
rubiksCubeRef,
|
|
@@ -24,10 +25,15 @@ export const UIControls = () => {
|
|
| 24 |
setCubeRoughness,
|
| 25 |
cubeSpeed,
|
| 26 |
setCubeSpeed,
|
|
|
|
|
|
|
| 27 |
} = useControlContext();
|
| 28 |
|
| 29 |
const scramble = () => {
|
| 30 |
-
const scrambleSteps = Array.from(
|
|
|
|
|
|
|
|
|
|
| 31 |
rubiksCubeRef?.current?.rotate(scrambleSteps);
|
| 32 |
};
|
| 33 |
|
|
@@ -41,7 +47,34 @@ export const UIControls = () => {
|
|
| 41 |
};
|
| 42 |
|
| 43 |
const train = () => {
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
};
|
| 46 |
|
| 47 |
return (
|
|
@@ -93,6 +126,15 @@ export const UIControls = () => {
|
|
| 93 |
maxValue={10}
|
| 94 |
step={1}
|
| 95 |
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
</div>
|
| 97 |
<div className="flex flex-col gap-2">
|
| 98 |
<div className="flex gap-2">
|
|
@@ -100,8 +142,11 @@ export const UIControls = () => {
|
|
| 100 |
<Button onPress={scramble}>Scramble</Button>
|
| 101 |
<Button onPress={reset}>Reset</Button>
|
| 102 |
</ButtonGroup>
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
<Button size="sm" className="ms-auto" color="success" onPress={
|
| 105 |
Solve
|
| 106 |
</Button>
|
| 107 |
</div>
|
|
|
|
| 14 |
|
| 15 |
export const UIControls = () => {
|
| 16 |
const stateModalRef = useRef<StateModalRef | null>(null);
|
| 17 |
+
const [isSolving, setIsSolving] = useState(false);
|
| 18 |
const [isControlsOpen, setIsControlsOpen] = useState(true);
|
| 19 |
const {
|
| 20 |
rubiksCubeRef,
|
|
|
|
| 25 |
setCubeRoughness,
|
| 26 |
cubeSpeed,
|
| 27 |
setCubeSpeed,
|
| 28 |
+
scrambleLength,
|
| 29 |
+
setScrambleLength,
|
| 30 |
} = useControlContext();
|
| 31 |
|
| 32 |
const scramble = () => {
|
| 33 |
+
const scrambleSteps = Array.from(
|
| 34 |
+
{ length: scrambleLength },
|
| 35 |
+
() => Actions[Math.floor(Math.random() * Actions.length)],
|
| 36 |
+
);
|
| 37 |
rubiksCubeRef?.current?.rotate(scrambleSteps);
|
| 38 |
};
|
| 39 |
|
|
|
|
| 47 |
};
|
| 48 |
|
| 49 |
const train = () => {
|
| 50 |
+
window.open('https://github.com/crossentropy-ai/rlcube', '_blank');
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
const solve = async () => {
|
| 54 |
+
try {
|
| 55 |
+
setIsSolving(true);
|
| 56 |
+
const response = await fetch('/api/solve', {
|
| 57 |
+
method: 'POST',
|
| 58 |
+
headers: {
|
| 59 |
+
'Content-Type': 'application/json',
|
| 60 |
+
},
|
| 61 |
+
body: JSON.stringify({ state: rotationController.getState() }),
|
| 62 |
+
});
|
| 63 |
+
if (response.status === 422) {
|
| 64 |
+
alert('Unable to solve the cube.');
|
| 65 |
+
return;
|
| 66 |
+
}
|
| 67 |
+
if (!response.ok) {
|
| 68 |
+
throw new Error('Server error', { cause: response });
|
| 69 |
+
}
|
| 70 |
+
const { steps } = await response.json();
|
| 71 |
+
rotationController.addRotationStepCode(...steps);
|
| 72 |
+
} catch (err) {
|
| 73 |
+
alert('An error occurred. Check the console for details.');
|
| 74 |
+
console.error(err);
|
| 75 |
+
} finally {
|
| 76 |
+
setIsSolving(false);
|
| 77 |
+
}
|
| 78 |
};
|
| 79 |
|
| 80 |
return (
|
|
|
|
| 126 |
maxValue={10}
|
| 127 |
step={1}
|
| 128 |
/>
|
| 129 |
+
<Slider
|
| 130 |
+
size="sm"
|
| 131 |
+
label="Scramble Length"
|
| 132 |
+
value={scrambleLength}
|
| 133 |
+
onChange={(value) => setScrambleLength(value as number)}
|
| 134 |
+
minValue={1}
|
| 135 |
+
maxValue={20}
|
| 136 |
+
step={1}
|
| 137 |
+
/>
|
| 138 |
</div>
|
| 139 |
<div className="flex flex-col gap-2">
|
| 140 |
<div className="flex gap-2">
|
|
|
|
| 142 |
<Button onPress={scramble}>Scramble</Button>
|
| 143 |
<Button onPress={reset}>Reset</Button>
|
| 144 |
</ButtonGroup>
|
| 145 |
+
<Button variant="light" size="sm" onPress={showState}>
|
| 146 |
+
Show State
|
| 147 |
+
</Button>
|
| 148 |
|
| 149 |
+
<Button size="sm" className="ms-auto" color="success" onPress={solve} isLoading={isSolving}>
|
| 150 |
Solve
|
| 151 |
</Button>
|
| 152 |
</div>
|
src/contexts/control-context.tsx
CHANGED
|
@@ -12,6 +12,8 @@ type ControlContextType = {
|
|
| 12 |
setCubeRoughness: (cubeRoughness: number) => void;
|
| 13 |
cubeSpeed: number;
|
| 14 |
setCubeSpeed: (cubeSpeed: number) => void;
|
|
|
|
|
|
|
| 15 |
background: PresetsType;
|
| 16 |
setBackground: (background: PresetsType) => void;
|
| 17 |
rubiksCubeRef?: RefObject<RubiksCubeRef | null>;
|
|
@@ -25,6 +27,8 @@ export const ControlContext = createContext<ControlContextType>({
|
|
| 25 |
setCubeRoughness: () => {},
|
| 26 |
cubeSpeed: 8,
|
| 27 |
setCubeSpeed: () => {},
|
|
|
|
|
|
|
| 28 |
background: 'sunset',
|
| 29 |
setBackground: () => {},
|
| 30 |
rubiksCubeRef: undefined,
|
|
@@ -39,6 +43,7 @@ export const ControlProvider = ({ children }: { children: React.ReactNode }) =>
|
|
| 39 |
const [showRotationIndicators, setShowRotationIndicators] = useState(false);
|
| 40 |
const [cubeRoughness, setCubeRoughness] = useState(0.5);
|
| 41 |
const [cubeSpeed, setCubeSpeed] = useState(8);
|
|
|
|
| 42 |
const [background, setBackground] = useState<PresetsType>('sunset');
|
| 43 |
const [rubiksCubeRef, setRubiksCubeRef] = useState<RefObject<RubiksCubeRef | null> | undefined>(undefined);
|
| 44 |
|
|
@@ -51,6 +56,8 @@ export const ControlProvider = ({ children }: { children: React.ReactNode }) =>
|
|
| 51 |
setCubeRoughness,
|
| 52 |
cubeSpeed,
|
| 53 |
setCubeSpeed,
|
|
|
|
|
|
|
| 54 |
background,
|
| 55 |
setBackground,
|
| 56 |
rubiksCubeRef,
|
|
|
|
| 12 |
setCubeRoughness: (cubeRoughness: number) => void;
|
| 13 |
cubeSpeed: number;
|
| 14 |
setCubeSpeed: (cubeSpeed: number) => void;
|
| 15 |
+
scrambleLength: number;
|
| 16 |
+
setScrambleLength: (scrambleLength: number) => void;
|
| 17 |
background: PresetsType;
|
| 18 |
setBackground: (background: PresetsType) => void;
|
| 19 |
rubiksCubeRef?: RefObject<RubiksCubeRef | null>;
|
|
|
|
| 27 |
setCubeRoughness: () => {},
|
| 28 |
cubeSpeed: 8,
|
| 29 |
setCubeSpeed: () => {},
|
| 30 |
+
scrambleLength: 8,
|
| 31 |
+
setScrambleLength: () => {},
|
| 32 |
background: 'sunset',
|
| 33 |
setBackground: () => {},
|
| 34 |
rubiksCubeRef: undefined,
|
|
|
|
| 43 |
const [showRotationIndicators, setShowRotationIndicators] = useState(false);
|
| 44 |
const [cubeRoughness, setCubeRoughness] = useState(0.5);
|
| 45 |
const [cubeSpeed, setCubeSpeed] = useState(8);
|
| 46 |
+
const [scrambleLength, setScrambleLength] = useState(8);
|
| 47 |
const [background, setBackground] = useState<PresetsType>('sunset');
|
| 48 |
const [rubiksCubeRef, setRubiksCubeRef] = useState<RefObject<RubiksCubeRef | null> | undefined>(undefined);
|
| 49 |
|
|
|
|
| 56 |
setCubeRoughness,
|
| 57 |
cubeSpeed,
|
| 58 |
setCubeSpeed,
|
| 59 |
+
scrambleLength,
|
| 60 |
+
setScrambleLength,
|
| 61 |
background,
|
| 62 |
setBackground,
|
| 63 |
rubiksCubeRef,
|