ruby - Strange code execution: should assign one element, assigns all -
i trying write genetic algorithm function approximation. part of code responsible mutation of 1 gene changes whole chromosome array. changes array not used in part. here's code.
print "\n\nchrom_array5: ", @chrom_array print "\n\nchrom_array5: ", @chrom_array random = rand if @no_of_chrom*@no_of_variables*@mutation_rate > random z=( rand * @no_of_chrom ).to_i print "\n\nz: ", z v=( rand * @no_of_variables).to_i print "\n\nv: ", v ble=new_chrom_array[0][0] print "\nnew_chrom_array[0][0]: ", new_chrom_array new_chrom_array[z][v] = ble + ble*rand - ble*random print "\nnew_chrom_array[z][v]: ", new_chrom_array end print "\n\nchrom_array6: ", @chrom_array print "\nnew_chrom_array6: ", new_chrom_array @chrom_array = new_chrom_array ...
here's output mutating iteration:
chrom_array5: [[128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78]]
new_chrom_array5: [[128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78]]
z: 2
v: 0
new_chrom_array[0][0]: [[128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78], [128383853580908.78]]
new_chrom_array[z][v]: [[143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22]]
chrom_array6: [[143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22]]
new_chrom_array6: [[143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22], [143481948278275.22]]
do know reason such behaviour?
one way can happen if elements of new_chrom_array contain same object. example, using irb
interactively execute ruby code:
~ ∙ irb irb(main):001:0> sub_array = [1] => [1] irb(main):002:0> array1 = [sub_array, sub_array, sub_array] => [[1], [1], [1]] irb(main):003:0> array2 = [sub_array, sub_array, sub_array, sub_array] => [[1], [1], [1], [1]] irb(main):004:0> array1[1][0] = 'x' => "x" irb(main):005:0> array1 => [["x"], ["x"], ["x"]] irb(main):006:0> array2 => [["x"], ["x"], ["x"], ["x"]]
so here making assignment array[1][0]
affects both array1
, array2
because object in of elements sub_array
.
this can confirmed looking @ object_id
of array elements:
irb(main):007:0> array1[0].object_id => 70353532235320 irb(main):008:0> array1[1].object_id => 70353532235320 irb(main):009:0> array2[1].object_id => 70353532235320
in experience there couple of things cause this:
creating array using array.new
use same object of elements:
irb(main):010:0> = array.new(5, ['x']) => [["x"], ["x"], ["x"], ["x"], ["x"]] irb(main):011:0> a[0].object_id => 70353539884820 irb(main):012:0> a[4].object_id => 70353539884820
you can avoid using block initialize elements, block return new object each time called - note different object_id
s
irb(main):013:0> b = array.new(5) {['x']} => [["x"], ["x"], ["x"], ["x"], ["x"]] irb(main):014:0> b[0].object_id => 70353535993240 irb(main):015:0> b[4].object_id => 70353535992900
the second common problem use of .dup
make copies of array , not remembering makes shallow copy:
irb(main):016:0> a1 = [['x']] => [["x"]] irb(main):017:0> a2 = a1.dup => [["x"]] irb(main):018:0> a2[0][0] = 'y' => "y" irb(main):019:0> a1 => [["y"]] irb(main):020:0> a2 => [["y"]]
you can use object_id
see contents of arrays are. 1 way deep copy divorces copy original use ruby's marshal
make copy of data structure - here see altering a3
doesn't affect a1
irb(main):021:0> a3 = marshal.load(marshal.dump(a1)) => [["y"]] irb(main):022:0> a3[0][0] = 'z' => "z" irb(main):023:0> a1 => [["y"]]
Comments
Post a Comment