diff --git a/4-Beyond-Classical-Search/index.html b/4-Beyond-Classical-Search/index.html index 71e70a0..d272877 100644 --- a/4-Beyond-Classical-Search/index.html +++ b/4-Beyond-Classical-Search/index.html @@ -31,7 +31,7 @@
-
+

Beyond classical search

Optimization Problem

@@ -230,7 +230,6 @@

Third Party License Information

-
diff --git a/6-Constraint-Satisfaction-Problems/c_mapColoring.js b/6-Constraint-Satisfaction-Problems/c_mapColoring.js new file mode 100644 index 0000000..57830fd --- /dev/null +++ b/6-Constraint-Satisfaction-Problems/c_mapColoring.js @@ -0,0 +1,141 @@ +class AustraliaMapDiagram { + constructor(selector, h, w) { + this.w = w; + this.h = h; + this.root = selector; + this.territories = [ + ['WA','#WA',1/16,1/4], + ['NT','#NT',1/7.5,1/6], + ['SA','#SA',1/7,1/3.5], + ['Q','#Q',1/4.5,1/4.5], + ['NSW','#NSW',1/4.5,1/3], + ['V','#V',1/5,1/2.45], + ['T','#T',1/4.4,1/2] + ]; + this.colors = [ + ['nc'], + ['r','.r',this.h/50,this.w/4], + ['g','.g',this.h/50,this.w/4+30], + ['b','.b',this.h/50,this.w/4+60] + ]; + } + + init(problem) { + this.problem = problem; + this.activeColor = 'nc'; + this.drawText(); + this.bindClicks(); + this.drawPalette(); + this.drawStatus(); + } + + drawStatus() { + this.status = this.root.select('#states') + .append('g') + .classed('status', true); + this.statusText = this.status.append('text') + .attr('y', this.h / 2.2) + .attr('x', this.w / 50) + .text('7 uncolored states'); + } + + updateStatus() { + let unassigned = this.problem.countUnassigned(); + if (unassigned > 0) { + this.statusText.attr('fill', 'black').text(`${unassigned} uncolored states`); + } else { + this.statusText.attr('fill', 'green').text(`Correct Assignment \u2714`); + } + } + + checkConsistency() { + //Remove any previous highlights for inconsistencies + this.root.selectAll('.inconsistent-state').classed('inconsistent-state', false); + let result = this.problem.checkConsistency(); + //If not consistent, highlight the inconsistent states. + if (!result.consistent) { + for (let i = 0; i < result.inconsistencies.length; i++) { + this.root.select(`#${result.inconsistencies[i][0]}`).classed('inconsistent-state', true); + this.root.select(`#${result.inconsistencies[i][1]}`).classed('inconsistent-state', true); + } + this.statusText.attr('fill', 'red').text('Inconsistent \u2718'); + } else { + this.updateStatus(); + } + } + + drawPalette() { + this.palette = this.root.select('#states') + .append('g') + .classed('palette', true); + for(let i = 1; i < this.colors.length; i++) { + let color = this.colors[i]; + this.palette + .append('circle') + .attr('r', 10) + .attr('cy', color[2]) + .attr('cx', color[3]) + .classed('palette-color', true) + .classed(color[0], true) + .classed('clickable', true) + .on('mousedown', () => { + this.palette.selectAll('.active-palette').classed('active-palette',false); + this.palette.select(color[1]).classed('active-palette',true); + this.activeColor = color[0]; + }); + } + } + + removeColor(state) { + this.root.select(`#${state}`) + .classed('nc', false) + .classed('r', false) + .classed('g', false) + .classed('b', false) + } + + colorState(state) { + //Remove previous colors + this.removeColor(state); + this.root.select(`#${state}`) + .classed(this.activeColor, true); + this.problem.assign(state, this.activeColor); + this.checkConsistency(); + } + + bindClicks() { + for(let i = 0; i < this.territories.length; i++) { + let territory = this.territories[i]; + this.root.select(territory[1]).classed('clickable', true).on('mousedown', () => { + this.colorState(territory[0]); + }); + } + } + + drawText() { + for(let i = 0; i < this.territories.length; i++) { + let territory = this.territories[i]; + this.root.select(territory[1]) + + .append('text') + .classed('territory-text',true) + .attr('x', this.w *territory[2]) + .attr('y', this.h *territory[3]) + .text(territory[0]); + } + } +} + +$(document).ready(function() { + function init() { + //Load external SVG async + d3.xml('../third-party/australia.svg', (xml) => { + $('#mapColoring .canvas').html(xml.documentElement); + var australiaMapDiagram = new AustraliaMapDiagram(d3.select('#mapColoring').select('.canvas'), 500, 1000); + australiaMapColoringProblem.emptyAssignment(); + australiaMapDiagram.init(australiaMapColoringProblem); + }) + } + init(); + $('#mapColoring .restart-button').click(init); +}); diff --git a/6-Constraint-Satisfaction-Problems/index.html b/6-Constraint-Satisfaction-Problems/index.html index b612e2e..34c6383 100644 --- a/6-Constraint-Satisfaction-Problems/index.html +++ b/6-Constraint-Satisfaction-Problems/index.html @@ -1,26 +1,55 @@ + 6 Constraint Satisfaction Problems + - + + + + + +
-
+

Constraint Satisfaction Problems

+

Defining CSP with Map Coloring Problem

+

+ A map coloring problem is a type of CSP where each state can be assigned a color from the set (red,green,blue). The constraint involved says that no two neighbouring state is allowed to have the same color. +

+

+ Given below is a map of Australia showing its states and territories. You can select a color from the color palette given on the top right and then click on any state to color it with the selected color. +

+

+ Try to color all the states while satisfying the condition that neighbouring states cannot have the same color. +

+
+
+
Restart
+
+
+
+ +
+
+
+ +

Arc consistency

@@ -32,30 +61,38 @@

Arc consistency

Step by step visualization of the procedure. Click to restart the simulation.

-
+

 
       

Backtracking

Map colouring using backtracking. Click to restart the simulation.

-
+

       

Min Conflicts

Min conflicts stuff

-
+

 
       

Tree CSP

Tree CSP Stuff

-
+

 
+      
+

Third Party License Information

+ +
+
-
+
+ diff --git a/6-Constraint-Satisfaction-Problems/main.css b/6-Constraint-Satisfaction-Problems/main.css new file mode 100644 index 0000000..3b5dbe1 --- /dev/null +++ b/6-Constraint-Satisfaction-Problems/main.css @@ -0,0 +1,35 @@ +.clickable { + cursor: pointer; +} + +/*nc -> No color*/ +.territory-text{ + stroke:none; + fill:black; +} +svg .nc { + fill: hsl(0, 0%, 83%); +} +svg .r { + fill: hsl(20, 80%, 70%); +} +svg .g { + fill: hsl(110, 80%, 70%); +} +svg .b { + fill: hsl(250, 80%, 70%); +} +.palette-color { + opacity: 0.4; +} +.active-palette { + opacity: 1; +} +.inconsistent-state { + stroke: hsl(20, 100%, 50%); + stroke-width: 1.5; +} +.status { + fill: black; + stroke: none; +} diff --git a/6-Constraint-Satisfaction-Problems/mapColoring.js b/6-Constraint-Satisfaction-Problems/mapColoring.js new file mode 100644 index 0000000..844c9b1 --- /dev/null +++ b/6-Constraint-Satisfaction-Problems/mapColoring.js @@ -0,0 +1,88 @@ +class mapColoringProblem { + constructor(variables, domains, neighbours, condition) { + this.variables = variables; + this.domains = domains; + this.neighbours = neighbours; + this.condition = condition; + this.assignment = {}; + this.emptyAssignment(); + } + //Assigns value 'a' to variable 'A' + assign(A, a) { + //Check if given value is in domain + let domain = this.domains[A]; + if (domain.includes(a)) { + this.assignment[A] = a; + return true; + } else { + return false; + } + } + + emptyAssignment() { + for (let i = 0; i < this.variables.length; i++) { + //'NIL' represents No assignment + this.assignment[this.variables[i]] = 'nc'; + } + } + + countUnassigned() { + let answer = 0; + for (let i = 0; i < this.variables.length; i++) { + //'NIL' represents No assignment + if (this.assignment[this.variables[i]] == 'nc') { + answer++; + }; + } + return answer; + } + + checkConsistency() { + //'consistence' is true if the current assignment is correct + //inconsistencies contains the list of neighbours that violate the condition + let answer = { + 'consistent': true, + 'inconsistencies': [] + } + + for (let i = 0; i < this.variables.length; i++) { + let variable = this.variables[i]; + for (let j = 0; j < this.neighbours[variable].length; j++) { + let neighbour = this.neighbours[variable][j]; + if (!this.condition(variable, this.assignment[variable], neighbour, this.assignment[neighbour])) { + answer['consistent'] = false; + answer['inconsistencies'].push([variable, neighbour]); + } + } + } + return answer; + } + +} + +//Map Coloring Problem for Australia +var australiaMapColoringProblem = new mapColoringProblem( + ["WA", "NT", "SA", "Q", "NSW", "V", "T"], { + "WA": ["r", "g", "b"], + "NT": ["r", "g", "b"], + "SA": ["r", "g", "b"], + "Q": ["r", "g", "b"], + "NSW": ["r", "g", "b"], + "V": ["r", "g", "b"], + "T": ["r", "g", "b"] + }, { + "WA": ["NT", "SA"], + "NT": ["WA", "SA", "Q"], + "SA": ["WA", "NT", "Q", "NSW", "V"], + "Q": ["NT", "SA", "NSW"], + "NSW": ["Q", "SA", "V"], + "V": ["SA", "NSW"], + "T": [] + }, + function(A, a, B, b) { + //If no color + if (a == 'nc' || b == 'nc') { + return true; + } + return a != b; + }); diff --git a/third-party/australia.svg b/third-party/australia.svg new file mode 100644 index 0000000..e3d37fa --- /dev/null +++ b/third-party/australia.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third-party/read-me.txt b/third-party/read-me.txt index 9192212..f0ce16e 100644 --- a/third-party/read-me.txt +++ b/third-party/read-me.txt @@ -1,2 +1,5 @@ robot.png from Simon Child, The Noun Project, Creative Commons BY-3.0 https://thenounproject.com/term/robot/1248/ + vacuum-cleaner.svg from Delapouite under CC BY 3.0 http://game-icons.net/delapouite/originals/vacuum-cleaner.html + +Australia Map svg from Lokal_Profil [CC BY-SA 2.5 (http://creativecommons.org/licenses/by-sa/2.5), GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)], via Wikimedia Commons