Skip to content

Commit

Permalink
Merge a27144d into 89b35fa
Browse files Browse the repository at this point in the history
  • Loading branch information
ColasPinson committed Jul 29, 2022
2 parents 89b35fa + a27144d commit 4d59a9d
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 88 deletions.
50 changes: 43 additions & 7 deletions app/controllers/optimizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ def index
@optimizations = policy_scope(Optimization)
end

def destroy_selected
params[:optimization_request_ids].each do |optimization_selected|
authorize Optimization.find(optimization_selected.to_i)
Optimization.find(optimization_selected.to_i).destroy
def select
if params[:delete]
params[:optimization_request_ids].each do |optimization_selected|
authorize Optimization.find(optimization_selected.to_i)
Optimization.find(optimization_selected.to_i).destroy
end
redirect_to optimizations_url, notice: params[:optimization_request_ids].length > 1 ? "The #{params[:optimization_request_ids].length} optimizations were successfully deleted." : "The optimization was successfully deleted."
else
params[:optimization_request_ids].each do |optimization_selected|
authorize Optimization.find(optimization_selected)
end
redirect_to controller: 'optimizations', action: 'compare', optim_list: params[:optimization_request_ids]
end
redirect_to optimizations_url, notice: params[:optimization_request_ids].length > 1 ? "The #{params[:optimization_request_ids].length} optimizations were successfully deleted." : "The optimization was successfully deleted."
end

def show
Expand Down Expand Up @@ -42,9 +49,30 @@ def create
@optimization = Optimization.new(optimization_params)
if optimization_params[:kind] == "SEGOMOE"
@optimization.config["n_obj"] = 1
@optimization.config["xlimits"] = @optimization.str_to_array(optimization_params[:xlimits])
@optimization.config["xlimits"] = params[:optimization][:xlimits].map{|e| e.delete(' ').split(',').map{|s| s.to_i}}
unless params[:optimization][:options][0].empty? || params[:optimization][:options][1].empty?
@optimization.config["options"]["mod_obj__regr"] = params[:optimization][:options][0]
@optimization.config["options"]["optimizer"] = params[:optimization][:options][1]
end
else
@optimization.config["n_obj"] = optimization_params[:n_obj].to_i
@optimization.config["xtypes"] = params[:optimization][:xtypes].map do |e|
arr = e.delete(' ').split(',')
if arr[0] == "int_type"
arr[1] = arr[1].to_i
arr[2] = arr[2].to_i
else
arr[1] = arr[1].to_f
arr[2] = arr[2].to_f
end
{"type" => arr[0], "limits" => [arr[1], arr[2]]}
end
@optimization.config["n_obj"] = @optimization.config["xtypes"].length()
unless params[:optimization][:cstr_specs][0].empty?
@optimization.config["cstr_specs"] = params[:optimization][:cstr_specs].map do |e|
arr = e.delete(' ').split(',')
{"type"=>arr[0], "bound"=>arr[1].to_f, "tol"=>arr[2].to_f}
end
end
end
@optimization.outputs["status"] = -1
authorize @optimization
Expand All @@ -57,6 +85,14 @@ def create
end
end

def compare
@compare_optimizations_list = []
params[:optim_list].each do |optimization_selected|
authorize Optimization.find(optimization_selected)
@compare_optimizations_list << Optimization.find(optimization_selected)
end
end

private
def set_optimization
@optimization = Optimization.find(params[:id])
Expand Down
103 changes: 65 additions & 38 deletions app/javascript/optview/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,79 @@ class OptView extends React.PureComponent {
constructor(props) {
super(props);
const {
optim,
data,
type,
} = this.props;
console.log("Kenoobii");
this.input_list = [];

if (type === 'single') {
if (data[0].inputs.x) {
for (let i = 0; i < data[0].inputs.x[0].length; i += 1) {
this.definePlot(data[0].inputs.x, i, 'gray', `input ${i + 1}`);
}
this.definePlot(data[0].inputs.y, 0, 'red', 'output');
}
} else {
for (let i = 0; i < data.length; i += 1) {
if (data[i].inputs.x) {
this.definePlot(data[i].inputs.y, 0, 'red', `output of #${data[i].id}`);
}
}
}
}

definePlot(points, n, _color, _name) {
this.input_list.push({
x: Array.from(Array(points.length).keys()),
y: points.map((z) => z[n]),
type: 'scatter',
mode: 'markers lines',
name: _name,
marker: { color: _color },
});
}

render() {
const {
data,
type,
} = this.props;
if (!data[0].inputs.x && type === 'single') {
return (
<div className="container">
<div className="row">
{' '}
No data to see for entry :
{' '}
{data[0].id}
</div>
</div>
);
}

return (
<Plot
data={[
{
x: Array.from(Array(this.props.optim.inputs['x'].length).keys()),
y: this.props.optim.inputs['x'].map( x => x[0] ),
type: 'scatter',
mode: 'markers lines',
name: 'x[0]',
marker: {color: 'orange'}
},
{
x: Array.from(Array(this.props.optim.inputs['x'].length).keys()),
y: this.props.optim.inputs['x'].map( x => x[1] ),
type: 'scatter',
mode: 'markers lines',
name: 'x[1]',
marker: {color: 'red'},
},
{
x: Array.from(Array(this.props.optim.inputs['y'].length).keys()),
y: this.props.optim.inputs['y'].map( y => y[0] ),
type: 'scatter',
mode: 'markers lines',
name: 'y',
marker: {color: 'green'},
}
]}
layout={{
width: 800,
height: 500,
title: 'Visual representation of the input points',
xaxis: {title: "point's number"},
yaxis: {title: "variable's values"}
}}
/>
<div className="container">
<div className="row">
<div className="col-sm">
<Plot
data={this.input_list}
layout={{
width: 800,
height: 500,
title: 'Visual representation of the input points',
xaxis: { title: "point's number" },
yaxis: { title: "variable's values" },
}}
/>
</div>
</div>
</div>
);
}
}

OptView.propTypes = {
optim: PropTypes.object.isRequired,
data: PropTypes.array.isRequired,
type: PropTypes.string.isRequired,
};
export default OptView;
17 changes: 8 additions & 9 deletions app/javascript/packs/optview_application.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { useState} from 'react'
import ReactDOM from 'react-dom'
import React from 'react';
import ReactDOM from 'react-dom';
import OptView from 'optview';


document.addEventListener('DOMContentLoaded', () => {
const node = document.getElementById('optimization_plot')
const optimization_data = JSON.parse(node.getAttribute('optimization_data'))
const optim_plot = document.getElementById('optimization_plot');

ReactDOM.render(
<OptView optim={optimization_data}/>,
document.getElementById("optimization_plot"),
)
})
<OptView data={JSON.parse(optim_plot.getAttribute('optimization_data'))} type={optim_plot.getAttribute('type')} />,
optim_plot,
);
});
8 changes: 1 addition & 7 deletions app/models/optimization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def check_optimization_config
return
end

xtypes.each_with_index do |xt, i|
self.xtypes.each_with_index do |xt, i|
case xt['type']
when "float_type"
if xt['limits'].size != 2 && xt['limits'][0].to_f != xt['limits'][0] && xt['limits'][1].to_f != xt['limits'][1]
Expand Down Expand Up @@ -116,12 +116,6 @@ def optimization_number_limit
errors.add(:base, "You own too many optimizations (#{optim_num}), you must delete some before creating new ones") unless optim_num < 20
end



def str_to_array string
JSON.parse(string) rescue "Invalid JSON"
end

class OptimizationError < Exception; end

#after_initialize :check_optimization_config
Expand Down
12 changes: 8 additions & 4 deletions app/policies/optimization_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def create?
end

def index?
(@user.admin? || @user.has_role?(:owner, @record))
show?
end

def show?
Expand All @@ -27,11 +27,15 @@ def destroy?
(@user.admin? || @user.has_role?(:owner, @record))
end

def destroy_selected?
(@user.admin? || @user.has_role?(:owner, @record))
def select?
show?
end

def compare?
show?
end

def download?
(@user.admin? || @user.has_role?(:owner, @record))
show?
end
end
46 changes: 38 additions & 8 deletions app/views/optimizations/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@
<%= f.select :kind , Optimization::OPTIMIZER_KINDS.each_key, {}, {class: "form-control"} %>
</div>

<div class="form-group">
<%= f.label :n_obj %>
<%= f.number_field :n_obj, class: "form-control" %>
</div>

<div class="form-group">
<%= f.label :xlimits %>
<%= f.text_field :xlimits, class: "form-control" %>
<div id="options" class="form-group">
</div>

<div class="form-group">
Expand All @@ -33,3 +26,40 @@
</div>
</div>
<% end %>
<% content_for :document_ready do %>
<script type="text/javascript">

$(document).ready(updateOptions());
$("#optimization_kind").change(function() {updateOptions();});

function updateOptions() {
$("#options").empty()
if ($("#optimization_kind").val() == "SEGOMOE") {
$("#options").html(
"<label>Xlimits <a href='#' data-bs-toggle='tooltip' style='color:#000000;' title='For each field : min, max'><i class='fas fa-question-circle'></i></a></label>" +
"<div id='xlimits'></div>" +
"<label for='optimization_options'>Options <a href='#' data-bs-toggle='tooltip' style='color:#000000;' title='For example : constant, cobyla'><i class='fas fa-question-circle'></i></a></label>" +
"<input class='form-control' type='text' name='optimization[options][]' id='optimization_options_mod_obj__regr' placeholder='mod_obj__regr''>" +
"<input class='form-control' type='text' name='optimization[options][]' id='optimization_options_optimizer' placeholder='optimizer'>"
)
addField('xlimits', 'Add a dimension to the input')
} else {
$("#options").html(
"<label>Xtypes <a href='#' data-bs-toggle='tooltip' style='color:#000000;' title='For each field : type, min, max ex: float_type, 1.0, 2.0'><i class='fas fa-question-circle'></i></a></label>" +
"<div id='xtypes'></div>" +
"<label>cstr_specs <a href='#' data-bs-toggle='tooltip' style='color:#000000;' title='For each field : type, bound, tol ex: <, 0.0, 0.0001'><i class='fas fa-question-circle'></i></a></label>" +
"<div id='cstr_specs'></div>"
)
addField('xtypes', 'Add a dimension to the input')
addField('cstr_specs', 'Add a spec')
}
}

function addField(type, message) {
$('.add' + type).remove()
$('#' + type).append("<input class='form-control' type='text' name='optimization[" + type + "][]'><a href='#' class='add" + type + "'>" + message + "</a>");
$('.add' + type).click(function(){addField(type, message);});
}
</script>
<% end %>
40 changes: 40 additions & 0 deletions app/views/optimizations/compare.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<h2>Compare <%= @compare_optimizations_list.length %> entries : <%= params[:optim_list].join(', ') %></h2>

<%= content_tag :div, id: "optimization_plot", optimization_data: @compare_optimizations_list.to_json, type: "compare" do %>
<% end %>

<p>
<table id="compare_table" class="table table-striped">
<thead>
<tr>
<th style="10%">Id</th>
<th style="20%">Optimizer</th>
<th style="20%">Config</th>
<th style="20%">Options</th>
<th style="20%">Number of Points</th>
<th style="20%">Result</th>
</tr>
</thead>

<tbody>
<% @compare_optimizations_list.each do |optimization_to_compare| %>
<tr class='table_row'>
<td>#<%= optimization_to_compare.id %></td>
<td><%= optimization_to_compare.kind %></td>
<td><%=
if optimization_to_compare.kind == "SEGOMOE"
"xlimits : " + optimization_to_compare.config["xlimits"].map { |i| "[" + i.join(", ")+ "]" }.join(", ")
else
"xtypes : " + optimization_to_compare.config["xtypes"].map { |i| "{" + i["type"] + ", [" + i["limits"].join(", ") + "]}" }.join(", ")
end
%></td>
<td><%= optimization_to_compare.config["options"].to_s %></td>
<td><%= nb_points(optimization_to_compare.inputs) %></td>
<td><%= if optimization_to_compare.outputs["y_best"].nil? then "NaN" else optimization_to_compare.outputs["y_best"][-1] end %></td>
</tr>
<% end %>
</tbody>
</table>
</p>

<%= javascript_pack_tag 'optview_application' %>
Loading

0 comments on commit 4d59a9d

Please sign in to comment.